18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2006 Intel Corporation. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include "e1000.h"
58c2ecf20Sopenharmony_ci#include <net/ip6_checksum.h>
68c2ecf20Sopenharmony_ci#include <linux/io.h>
78c2ecf20Sopenharmony_ci#include <linux/prefetch.h>
88c2ecf20Sopenharmony_ci#include <linux/bitops.h>
98c2ecf20Sopenharmony_ci#include <linux/if_vlan.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cichar e1000_driver_name[] = "e1000";
128c2ecf20Sopenharmony_cistatic char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
138c2ecf20Sopenharmony_cistatic const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/* e1000_pci_tbl - PCI Device ID Table
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * Last entry must be all 0s
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * Macro expands to...
208c2ecf20Sopenharmony_ci *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
218c2ecf20Sopenharmony_ci */
228c2ecf20Sopenharmony_cistatic const struct pci_device_id e1000_pci_tbl[] = {
238c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1000),
248c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1001),
258c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1004),
268c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1008),
278c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1009),
288c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x100C),
298c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x100D),
308c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x100E),
318c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x100F),
328c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1010),
338c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1011),
348c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1012),
358c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1013),
368c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1014),
378c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1015),
388c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1016),
398c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1017),
408c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1018),
418c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1019),
428c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x101A),
438c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x101D),
448c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x101E),
458c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1026),
468c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1027),
478c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1028),
488c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1075),
498c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1076),
508c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1077),
518c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1078),
528c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1079),
538c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x107A),
548c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x107B),
558c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x107C),
568c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x108A),
578c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x1099),
588c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x10B5),
598c2ecf20Sopenharmony_ci	INTEL_E1000_ETHERNET_DEVICE(0x2E6E),
608c2ecf20Sopenharmony_ci	/* required last entry */
618c2ecf20Sopenharmony_ci	{0,}
628c2ecf20Sopenharmony_ci};
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ciint e1000_up(struct e1000_adapter *adapter);
678c2ecf20Sopenharmony_civoid e1000_down(struct e1000_adapter *adapter);
688c2ecf20Sopenharmony_civoid e1000_reinit_locked(struct e1000_adapter *adapter);
698c2ecf20Sopenharmony_civoid e1000_reset(struct e1000_adapter *adapter);
708c2ecf20Sopenharmony_ciint e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
718c2ecf20Sopenharmony_ciint e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
728c2ecf20Sopenharmony_civoid e1000_free_all_tx_resources(struct e1000_adapter *adapter);
738c2ecf20Sopenharmony_civoid e1000_free_all_rx_resources(struct e1000_adapter *adapter);
748c2ecf20Sopenharmony_cistatic int e1000_setup_tx_resources(struct e1000_adapter *adapter,
758c2ecf20Sopenharmony_ci				    struct e1000_tx_ring *txdr);
768c2ecf20Sopenharmony_cistatic int e1000_setup_rx_resources(struct e1000_adapter *adapter,
778c2ecf20Sopenharmony_ci				    struct e1000_rx_ring *rxdr);
788c2ecf20Sopenharmony_cistatic void e1000_free_tx_resources(struct e1000_adapter *adapter,
798c2ecf20Sopenharmony_ci				    struct e1000_tx_ring *tx_ring);
808c2ecf20Sopenharmony_cistatic void e1000_free_rx_resources(struct e1000_adapter *adapter,
818c2ecf20Sopenharmony_ci				    struct e1000_rx_ring *rx_ring);
828c2ecf20Sopenharmony_civoid e1000_update_stats(struct e1000_adapter *adapter);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic int e1000_init_module(void);
858c2ecf20Sopenharmony_cistatic void e1000_exit_module(void);
868c2ecf20Sopenharmony_cistatic int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
878c2ecf20Sopenharmony_cistatic void e1000_remove(struct pci_dev *pdev);
888c2ecf20Sopenharmony_cistatic int e1000_alloc_queues(struct e1000_adapter *adapter);
898c2ecf20Sopenharmony_cistatic int e1000_sw_init(struct e1000_adapter *adapter);
908c2ecf20Sopenharmony_ciint e1000_open(struct net_device *netdev);
918c2ecf20Sopenharmony_ciint e1000_close(struct net_device *netdev);
928c2ecf20Sopenharmony_cistatic void e1000_configure_tx(struct e1000_adapter *adapter);
938c2ecf20Sopenharmony_cistatic void e1000_configure_rx(struct e1000_adapter *adapter);
948c2ecf20Sopenharmony_cistatic void e1000_setup_rctl(struct e1000_adapter *adapter);
958c2ecf20Sopenharmony_cistatic void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
968c2ecf20Sopenharmony_cistatic void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
978c2ecf20Sopenharmony_cistatic void e1000_clean_tx_ring(struct e1000_adapter *adapter,
988c2ecf20Sopenharmony_ci				struct e1000_tx_ring *tx_ring);
998c2ecf20Sopenharmony_cistatic void e1000_clean_rx_ring(struct e1000_adapter *adapter,
1008c2ecf20Sopenharmony_ci				struct e1000_rx_ring *rx_ring);
1018c2ecf20Sopenharmony_cistatic void e1000_set_rx_mode(struct net_device *netdev);
1028c2ecf20Sopenharmony_cistatic void e1000_update_phy_info_task(struct work_struct *work);
1038c2ecf20Sopenharmony_cistatic void e1000_watchdog(struct work_struct *work);
1048c2ecf20Sopenharmony_cistatic void e1000_82547_tx_fifo_stall_task(struct work_struct *work);
1058c2ecf20Sopenharmony_cistatic netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
1068c2ecf20Sopenharmony_ci				    struct net_device *netdev);
1078c2ecf20Sopenharmony_cistatic int e1000_change_mtu(struct net_device *netdev, int new_mtu);
1088c2ecf20Sopenharmony_cistatic int e1000_set_mac(struct net_device *netdev, void *p);
1098c2ecf20Sopenharmony_cistatic irqreturn_t e1000_intr(int irq, void *data);
1108c2ecf20Sopenharmony_cistatic bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
1118c2ecf20Sopenharmony_ci			       struct e1000_tx_ring *tx_ring);
1128c2ecf20Sopenharmony_cistatic int e1000_clean(struct napi_struct *napi, int budget);
1138c2ecf20Sopenharmony_cistatic bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
1148c2ecf20Sopenharmony_ci			       struct e1000_rx_ring *rx_ring,
1158c2ecf20Sopenharmony_ci			       int *work_done, int work_to_do);
1168c2ecf20Sopenharmony_cistatic bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
1178c2ecf20Sopenharmony_ci				     struct e1000_rx_ring *rx_ring,
1188c2ecf20Sopenharmony_ci				     int *work_done, int work_to_do);
1198c2ecf20Sopenharmony_cistatic void e1000_alloc_dummy_rx_buffers(struct e1000_adapter *adapter,
1208c2ecf20Sopenharmony_ci					 struct e1000_rx_ring *rx_ring,
1218c2ecf20Sopenharmony_ci					 int cleaned_count)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_cistatic void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
1258c2ecf20Sopenharmony_ci				   struct e1000_rx_ring *rx_ring,
1268c2ecf20Sopenharmony_ci				   int cleaned_count);
1278c2ecf20Sopenharmony_cistatic void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
1288c2ecf20Sopenharmony_ci					 struct e1000_rx_ring *rx_ring,
1298c2ecf20Sopenharmony_ci					 int cleaned_count);
1308c2ecf20Sopenharmony_cistatic int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
1318c2ecf20Sopenharmony_cistatic int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
1328c2ecf20Sopenharmony_ci			   int cmd);
1338c2ecf20Sopenharmony_cistatic void e1000_enter_82542_rst(struct e1000_adapter *adapter);
1348c2ecf20Sopenharmony_cistatic void e1000_leave_82542_rst(struct e1000_adapter *adapter);
1358c2ecf20Sopenharmony_cistatic void e1000_tx_timeout(struct net_device *dev, unsigned int txqueue);
1368c2ecf20Sopenharmony_cistatic void e1000_reset_task(struct work_struct *work);
1378c2ecf20Sopenharmony_cistatic void e1000_smartspeed(struct e1000_adapter *adapter);
1388c2ecf20Sopenharmony_cistatic int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
1398c2ecf20Sopenharmony_ci				       struct sk_buff *skb);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic bool e1000_vlan_used(struct e1000_adapter *adapter);
1428c2ecf20Sopenharmony_cistatic void e1000_vlan_mode(struct net_device *netdev,
1438c2ecf20Sopenharmony_ci			    netdev_features_t features);
1448c2ecf20Sopenharmony_cistatic void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
1458c2ecf20Sopenharmony_ci				     bool filter_on);
1468c2ecf20Sopenharmony_cistatic int e1000_vlan_rx_add_vid(struct net_device *netdev,
1478c2ecf20Sopenharmony_ci				 __be16 proto, u16 vid);
1488c2ecf20Sopenharmony_cistatic int e1000_vlan_rx_kill_vid(struct net_device *netdev,
1498c2ecf20Sopenharmony_ci				  __be16 proto, u16 vid);
1508c2ecf20Sopenharmony_cistatic void e1000_restore_vlan(struct e1000_adapter *adapter);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic int __maybe_unused e1000_suspend(struct device *dev);
1538c2ecf20Sopenharmony_cistatic int __maybe_unused e1000_resume(struct device *dev);
1548c2ecf20Sopenharmony_cistatic void e1000_shutdown(struct pci_dev *pdev);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
1578c2ecf20Sopenharmony_ci/* for netdump / net console */
1588c2ecf20Sopenharmony_cistatic void e1000_netpoll (struct net_device *netdev);
1598c2ecf20Sopenharmony_ci#endif
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci#define COPYBREAK_DEFAULT 256
1628c2ecf20Sopenharmony_cistatic unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT;
1638c2ecf20Sopenharmony_cimodule_param(copybreak, uint, 0644);
1648c2ecf20Sopenharmony_ciMODULE_PARM_DESC(copybreak,
1658c2ecf20Sopenharmony_ci	"Maximum size of packet that is copied to a new buffer on receive");
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistatic pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
1688c2ecf20Sopenharmony_ci						pci_channel_state_t state);
1698c2ecf20Sopenharmony_cistatic pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
1708c2ecf20Sopenharmony_cistatic void e1000_io_resume(struct pci_dev *pdev);
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic const struct pci_error_handlers e1000_err_handler = {
1738c2ecf20Sopenharmony_ci	.error_detected = e1000_io_error_detected,
1748c2ecf20Sopenharmony_ci	.slot_reset = e1000_io_slot_reset,
1758c2ecf20Sopenharmony_ci	.resume = e1000_io_resume,
1768c2ecf20Sopenharmony_ci};
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(e1000_pm_ops, e1000_suspend, e1000_resume);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic struct pci_driver e1000_driver = {
1818c2ecf20Sopenharmony_ci	.name     = e1000_driver_name,
1828c2ecf20Sopenharmony_ci	.id_table = e1000_pci_tbl,
1838c2ecf20Sopenharmony_ci	.probe    = e1000_probe,
1848c2ecf20Sopenharmony_ci	.remove   = e1000_remove,
1858c2ecf20Sopenharmony_ci	.driver = {
1868c2ecf20Sopenharmony_ci		.pm = &e1000_pm_ops,
1878c2ecf20Sopenharmony_ci	},
1888c2ecf20Sopenharmony_ci	.shutdown = e1000_shutdown,
1898c2ecf20Sopenharmony_ci	.err_handler = &e1000_err_handler
1908c2ecf20Sopenharmony_ci};
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ciMODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
1938c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
1948c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
1978c2ecf20Sopenharmony_cistatic int debug = -1;
1988c2ecf20Sopenharmony_cimodule_param(debug, int, 0);
1998c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci/**
2028c2ecf20Sopenharmony_ci * e1000_get_hw_dev - helper function for getting netdev
2038c2ecf20Sopenharmony_ci * @hw: pointer to HW struct
2048c2ecf20Sopenharmony_ci *
2058c2ecf20Sopenharmony_ci * return device used by hardware layer to print debugging information
2068c2ecf20Sopenharmony_ci *
2078c2ecf20Sopenharmony_ci **/
2088c2ecf20Sopenharmony_cistruct net_device *e1000_get_hw_dev(struct e1000_hw *hw)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = hw->back;
2118c2ecf20Sopenharmony_ci	return adapter->netdev;
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci/**
2158c2ecf20Sopenharmony_ci * e1000_init_module - Driver Registration Routine
2168c2ecf20Sopenharmony_ci *
2178c2ecf20Sopenharmony_ci * e1000_init_module is the first routine called when the driver is
2188c2ecf20Sopenharmony_ci * loaded. All it does is register with the PCI subsystem.
2198c2ecf20Sopenharmony_ci **/
2208c2ecf20Sopenharmony_cistatic int __init e1000_init_module(void)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	int ret;
2238c2ecf20Sopenharmony_ci	pr_info("%s\n", e1000_driver_string);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	pr_info("%s\n", e1000_copyright);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	ret = pci_register_driver(&e1000_driver);
2288c2ecf20Sopenharmony_ci	if (copybreak != COPYBREAK_DEFAULT) {
2298c2ecf20Sopenharmony_ci		if (copybreak == 0)
2308c2ecf20Sopenharmony_ci			pr_info("copybreak disabled\n");
2318c2ecf20Sopenharmony_ci		else
2328c2ecf20Sopenharmony_ci			pr_info("copybreak enabled for "
2338c2ecf20Sopenharmony_ci				   "packets <= %u bytes\n", copybreak);
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci	return ret;
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cimodule_init(e1000_init_module);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci/**
2418c2ecf20Sopenharmony_ci * e1000_exit_module - Driver Exit Cleanup Routine
2428c2ecf20Sopenharmony_ci *
2438c2ecf20Sopenharmony_ci * e1000_exit_module is called just before the driver is removed
2448c2ecf20Sopenharmony_ci * from memory.
2458c2ecf20Sopenharmony_ci **/
2468c2ecf20Sopenharmony_cistatic void __exit e1000_exit_module(void)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	pci_unregister_driver(&e1000_driver);
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cimodule_exit(e1000_exit_module);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic int e1000_request_irq(struct e1000_adapter *adapter)
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
2568c2ecf20Sopenharmony_ci	irq_handler_t handler = e1000_intr;
2578c2ecf20Sopenharmony_ci	int irq_flags = IRQF_SHARED;
2588c2ecf20Sopenharmony_ci	int err;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
2618c2ecf20Sopenharmony_ci			  netdev);
2628c2ecf20Sopenharmony_ci	if (err) {
2638c2ecf20Sopenharmony_ci		e_err(probe, "Unable to allocate interrupt Error: %d\n", err);
2648c2ecf20Sopenharmony_ci	}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	return err;
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic void e1000_free_irq(struct e1000_adapter *adapter)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	free_irq(adapter->pdev->irq, netdev);
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/**
2778c2ecf20Sopenharmony_ci * e1000_irq_disable - Mask off interrupt generation on the NIC
2788c2ecf20Sopenharmony_ci * @adapter: board private structure
2798c2ecf20Sopenharmony_ci **/
2808c2ecf20Sopenharmony_cistatic void e1000_irq_disable(struct e1000_adapter *adapter)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	ew32(IMC, ~0);
2858c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
2868c2ecf20Sopenharmony_ci	synchronize_irq(adapter->pdev->irq);
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci/**
2908c2ecf20Sopenharmony_ci * e1000_irq_enable - Enable default interrupt generation settings
2918c2ecf20Sopenharmony_ci * @adapter: board private structure
2928c2ecf20Sopenharmony_ci **/
2938c2ecf20Sopenharmony_cistatic void e1000_irq_enable(struct e1000_adapter *adapter)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	ew32(IMS, IMS_ENABLE_MASK);
2988c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
2998c2ecf20Sopenharmony_ci}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_cistatic void e1000_update_mng_vlan(struct e1000_adapter *adapter)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
3048c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
3058c2ecf20Sopenharmony_ci	u16 vid = hw->mng_cookie.vlan_id;
3068c2ecf20Sopenharmony_ci	u16 old_vid = adapter->mng_vlan_id;
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	if (!e1000_vlan_used(adapter))
3098c2ecf20Sopenharmony_ci		return;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	if (!test_bit(vid, adapter->active_vlans)) {
3128c2ecf20Sopenharmony_ci		if (hw->mng_cookie.status &
3138c2ecf20Sopenharmony_ci		    E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
3148c2ecf20Sopenharmony_ci			e1000_vlan_rx_add_vid(netdev, htons(ETH_P_8021Q), vid);
3158c2ecf20Sopenharmony_ci			adapter->mng_vlan_id = vid;
3168c2ecf20Sopenharmony_ci		} else {
3178c2ecf20Sopenharmony_ci			adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
3188c2ecf20Sopenharmony_ci		}
3198c2ecf20Sopenharmony_ci		if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
3208c2ecf20Sopenharmony_ci		    (vid != old_vid) &&
3218c2ecf20Sopenharmony_ci		    !test_bit(old_vid, adapter->active_vlans))
3228c2ecf20Sopenharmony_ci			e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q),
3238c2ecf20Sopenharmony_ci					       old_vid);
3248c2ecf20Sopenharmony_ci	} else {
3258c2ecf20Sopenharmony_ci		adapter->mng_vlan_id = vid;
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic void e1000_init_manageability(struct e1000_adapter *adapter)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	if (adapter->en_mng_pt) {
3348c2ecf20Sopenharmony_ci		u32 manc = er32(MANC);
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci		/* disable hardware interception of ARP */
3378c2ecf20Sopenharmony_ci		manc &= ~(E1000_MANC_ARP_EN);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci		ew32(MANC, manc);
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic void e1000_release_manageability(struct e1000_adapter *adapter)
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	if (adapter->en_mng_pt) {
3488c2ecf20Sopenharmony_ci		u32 manc = er32(MANC);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci		/* re-enable hardware interception of ARP */
3518c2ecf20Sopenharmony_ci		manc |= E1000_MANC_ARP_EN;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci		ew32(MANC, manc);
3548c2ecf20Sopenharmony_ci	}
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci/**
3588c2ecf20Sopenharmony_ci * e1000_configure - configure the hardware for RX and TX
3598c2ecf20Sopenharmony_ci * @adapter: private board structure
3608c2ecf20Sopenharmony_ci **/
3618c2ecf20Sopenharmony_cistatic void e1000_configure(struct e1000_adapter *adapter)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
3648c2ecf20Sopenharmony_ci	int i;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	e1000_set_rx_mode(netdev);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	e1000_restore_vlan(adapter);
3698c2ecf20Sopenharmony_ci	e1000_init_manageability(adapter);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	e1000_configure_tx(adapter);
3728c2ecf20Sopenharmony_ci	e1000_setup_rctl(adapter);
3738c2ecf20Sopenharmony_ci	e1000_configure_rx(adapter);
3748c2ecf20Sopenharmony_ci	/* call E1000_DESC_UNUSED which always leaves
3758c2ecf20Sopenharmony_ci	 * at least 1 descriptor unused to make sure
3768c2ecf20Sopenharmony_ci	 * next_to_use != next_to_clean
3778c2ecf20Sopenharmony_ci	 */
3788c2ecf20Sopenharmony_ci	for (i = 0; i < adapter->num_rx_queues; i++) {
3798c2ecf20Sopenharmony_ci		struct e1000_rx_ring *ring = &adapter->rx_ring[i];
3808c2ecf20Sopenharmony_ci		adapter->alloc_rx_buf(adapter, ring,
3818c2ecf20Sopenharmony_ci				      E1000_DESC_UNUSED(ring));
3828c2ecf20Sopenharmony_ci	}
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ciint e1000_up(struct e1000_adapter *adapter)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	/* hardware has been reset, we need to reload some things */
3908c2ecf20Sopenharmony_ci	e1000_configure(adapter);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	clear_bit(__E1000_DOWN, &adapter->flags);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	napi_enable(&adapter->napi);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	e1000_irq_enable(adapter);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	netif_wake_queue(adapter->netdev);
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	/* fire a link change interrupt to start the watchdog */
4018c2ecf20Sopenharmony_ci	ew32(ICS, E1000_ICS_LSC);
4028c2ecf20Sopenharmony_ci	return 0;
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci/**
4068c2ecf20Sopenharmony_ci * e1000_power_up_phy - restore link in case the phy was powered down
4078c2ecf20Sopenharmony_ci * @adapter: address of board private structure
4088c2ecf20Sopenharmony_ci *
4098c2ecf20Sopenharmony_ci * The phy may be powered down to save power and turn off link when the
4108c2ecf20Sopenharmony_ci * driver is unloaded and wake on lan is not enabled (among others)
4118c2ecf20Sopenharmony_ci * *** this routine MUST be followed by a call to e1000_reset ***
4128c2ecf20Sopenharmony_ci **/
4138c2ecf20Sopenharmony_civoid e1000_power_up_phy(struct e1000_adapter *adapter)
4148c2ecf20Sopenharmony_ci{
4158c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
4168c2ecf20Sopenharmony_ci	u16 mii_reg = 0;
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	/* Just clear the power down bit to wake the phy back up */
4198c2ecf20Sopenharmony_ci	if (hw->media_type == e1000_media_type_copper) {
4208c2ecf20Sopenharmony_ci		/* according to the manual, the phy will retain its
4218c2ecf20Sopenharmony_ci		 * settings across a power-down/up cycle
4228c2ecf20Sopenharmony_ci		 */
4238c2ecf20Sopenharmony_ci		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
4248c2ecf20Sopenharmony_ci		mii_reg &= ~MII_CR_POWER_DOWN;
4258c2ecf20Sopenharmony_ci		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic void e1000_power_down_phy(struct e1000_adapter *adapter)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	/* Power down the PHY so no link is implied when interface is down *
4348c2ecf20Sopenharmony_ci	 * The PHY cannot be powered down if any of the following is true *
4358c2ecf20Sopenharmony_ci	 * (a) WoL is enabled
4368c2ecf20Sopenharmony_ci	 * (b) AMT is active
4378c2ecf20Sopenharmony_ci	 * (c) SoL/IDER session is active
4388c2ecf20Sopenharmony_ci	 */
4398c2ecf20Sopenharmony_ci	if (!adapter->wol && hw->mac_type >= e1000_82540 &&
4408c2ecf20Sopenharmony_ci	   hw->media_type == e1000_media_type_copper) {
4418c2ecf20Sopenharmony_ci		u16 mii_reg = 0;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci		switch (hw->mac_type) {
4448c2ecf20Sopenharmony_ci		case e1000_82540:
4458c2ecf20Sopenharmony_ci		case e1000_82545:
4468c2ecf20Sopenharmony_ci		case e1000_82545_rev_3:
4478c2ecf20Sopenharmony_ci		case e1000_82546:
4488c2ecf20Sopenharmony_ci		case e1000_ce4100:
4498c2ecf20Sopenharmony_ci		case e1000_82546_rev_3:
4508c2ecf20Sopenharmony_ci		case e1000_82541:
4518c2ecf20Sopenharmony_ci		case e1000_82541_rev_2:
4528c2ecf20Sopenharmony_ci		case e1000_82547:
4538c2ecf20Sopenharmony_ci		case e1000_82547_rev_2:
4548c2ecf20Sopenharmony_ci			if (er32(MANC) & E1000_MANC_SMBUS_EN)
4558c2ecf20Sopenharmony_ci				goto out;
4568c2ecf20Sopenharmony_ci			break;
4578c2ecf20Sopenharmony_ci		default:
4588c2ecf20Sopenharmony_ci			goto out;
4598c2ecf20Sopenharmony_ci		}
4608c2ecf20Sopenharmony_ci		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
4618c2ecf20Sopenharmony_ci		mii_reg |= MII_CR_POWER_DOWN;
4628c2ecf20Sopenharmony_ci		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
4638c2ecf20Sopenharmony_ci		msleep(1);
4648c2ecf20Sopenharmony_ci	}
4658c2ecf20Sopenharmony_ciout:
4668c2ecf20Sopenharmony_ci	return;
4678c2ecf20Sopenharmony_ci}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_cistatic void e1000_down_and_stop(struct e1000_adapter *adapter)
4708c2ecf20Sopenharmony_ci{
4718c2ecf20Sopenharmony_ci	set_bit(__E1000_DOWN, &adapter->flags);
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&adapter->watchdog_task);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	/*
4768c2ecf20Sopenharmony_ci	 * Since the watchdog task can reschedule other tasks, we should cancel
4778c2ecf20Sopenharmony_ci	 * it first, otherwise we can run into the situation when a work is
4788c2ecf20Sopenharmony_ci	 * still running after the adapter has been turned down.
4798c2ecf20Sopenharmony_ci	 */
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&adapter->phy_info_task);
4828c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&adapter->fifo_stall_task);
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	/* Only kill reset task if adapter is not resetting */
4858c2ecf20Sopenharmony_ci	if (!test_bit(__E1000_RESETTING, &adapter->flags))
4868c2ecf20Sopenharmony_ci		cancel_work_sync(&adapter->reset_task);
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_civoid e1000_down(struct e1000_adapter *adapter)
4908c2ecf20Sopenharmony_ci{
4918c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
4928c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
4938c2ecf20Sopenharmony_ci	u32 rctl, tctl;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	/* disable receives in the hardware */
4968c2ecf20Sopenharmony_ci	rctl = er32(RCTL);
4978c2ecf20Sopenharmony_ci	ew32(RCTL, rctl & ~E1000_RCTL_EN);
4988c2ecf20Sopenharmony_ci	/* flush and sleep below */
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	netif_tx_disable(netdev);
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	/* disable transmits in the hardware */
5038c2ecf20Sopenharmony_ci	tctl = er32(TCTL);
5048c2ecf20Sopenharmony_ci	tctl &= ~E1000_TCTL_EN;
5058c2ecf20Sopenharmony_ci	ew32(TCTL, tctl);
5068c2ecf20Sopenharmony_ci	/* flush both disables and wait for them to finish */
5078c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
5088c2ecf20Sopenharmony_ci	msleep(10);
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	/* Set the carrier off after transmits have been disabled in the
5118c2ecf20Sopenharmony_ci	 * hardware, to avoid race conditions with e1000_watchdog() (which
5128c2ecf20Sopenharmony_ci	 * may be running concurrently to us, checking for the carrier
5138c2ecf20Sopenharmony_ci	 * bit to decide whether it should enable transmits again). Such
5148c2ecf20Sopenharmony_ci	 * a race condition would result into transmission being disabled
5158c2ecf20Sopenharmony_ci	 * in the hardware until the next IFF_DOWN+IFF_UP cycle.
5168c2ecf20Sopenharmony_ci	 */
5178c2ecf20Sopenharmony_ci	netif_carrier_off(netdev);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	napi_disable(&adapter->napi);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	e1000_irq_disable(adapter);
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	/* Setting DOWN must be after irq_disable to prevent
5248c2ecf20Sopenharmony_ci	 * a screaming interrupt.  Setting DOWN also prevents
5258c2ecf20Sopenharmony_ci	 * tasks from rescheduling.
5268c2ecf20Sopenharmony_ci	 */
5278c2ecf20Sopenharmony_ci	e1000_down_and_stop(adapter);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	adapter->link_speed = 0;
5308c2ecf20Sopenharmony_ci	adapter->link_duplex = 0;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	e1000_reset(adapter);
5338c2ecf20Sopenharmony_ci	e1000_clean_all_tx_rings(adapter);
5348c2ecf20Sopenharmony_ci	e1000_clean_all_rx_rings(adapter);
5358c2ecf20Sopenharmony_ci}
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_civoid e1000_reinit_locked(struct e1000_adapter *adapter)
5388c2ecf20Sopenharmony_ci{
5398c2ecf20Sopenharmony_ci	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
5408c2ecf20Sopenharmony_ci		msleep(1);
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	/* only run the task if not already down */
5438c2ecf20Sopenharmony_ci	if (!test_bit(__E1000_DOWN, &adapter->flags)) {
5448c2ecf20Sopenharmony_ci		e1000_down(adapter);
5458c2ecf20Sopenharmony_ci		e1000_up(adapter);
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	clear_bit(__E1000_RESETTING, &adapter->flags);
5498c2ecf20Sopenharmony_ci}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_civoid e1000_reset(struct e1000_adapter *adapter)
5528c2ecf20Sopenharmony_ci{
5538c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
5548c2ecf20Sopenharmony_ci	u32 pba = 0, tx_space, min_tx_space, min_rx_space;
5558c2ecf20Sopenharmony_ci	bool legacy_pba_adjust = false;
5568c2ecf20Sopenharmony_ci	u16 hwm;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	/* Repartition Pba for greater than 9k mtu
5598c2ecf20Sopenharmony_ci	 * To take effect CTRL.RST is required.
5608c2ecf20Sopenharmony_ci	 */
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
5638c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
5648c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
5658c2ecf20Sopenharmony_ci	case e1000_82543:
5668c2ecf20Sopenharmony_ci	case e1000_82544:
5678c2ecf20Sopenharmony_ci	case e1000_82540:
5688c2ecf20Sopenharmony_ci	case e1000_82541:
5698c2ecf20Sopenharmony_ci	case e1000_82541_rev_2:
5708c2ecf20Sopenharmony_ci		legacy_pba_adjust = true;
5718c2ecf20Sopenharmony_ci		pba = E1000_PBA_48K;
5728c2ecf20Sopenharmony_ci		break;
5738c2ecf20Sopenharmony_ci	case e1000_82545:
5748c2ecf20Sopenharmony_ci	case e1000_82545_rev_3:
5758c2ecf20Sopenharmony_ci	case e1000_82546:
5768c2ecf20Sopenharmony_ci	case e1000_ce4100:
5778c2ecf20Sopenharmony_ci	case e1000_82546_rev_3:
5788c2ecf20Sopenharmony_ci		pba = E1000_PBA_48K;
5798c2ecf20Sopenharmony_ci		break;
5808c2ecf20Sopenharmony_ci	case e1000_82547:
5818c2ecf20Sopenharmony_ci	case e1000_82547_rev_2:
5828c2ecf20Sopenharmony_ci		legacy_pba_adjust = true;
5838c2ecf20Sopenharmony_ci		pba = E1000_PBA_30K;
5848c2ecf20Sopenharmony_ci		break;
5858c2ecf20Sopenharmony_ci	case e1000_undefined:
5868c2ecf20Sopenharmony_ci	case e1000_num_macs:
5878c2ecf20Sopenharmony_ci		break;
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	if (legacy_pba_adjust) {
5918c2ecf20Sopenharmony_ci		if (hw->max_frame_size > E1000_RXBUFFER_8192)
5928c2ecf20Sopenharmony_ci			pba -= 8; /* allocate more FIFO for Tx */
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci		if (hw->mac_type == e1000_82547) {
5958c2ecf20Sopenharmony_ci			adapter->tx_fifo_head = 0;
5968c2ecf20Sopenharmony_ci			adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
5978c2ecf20Sopenharmony_ci			adapter->tx_fifo_size =
5988c2ecf20Sopenharmony_ci				(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
5998c2ecf20Sopenharmony_ci			atomic_set(&adapter->tx_fifo_stall, 0);
6008c2ecf20Sopenharmony_ci		}
6018c2ecf20Sopenharmony_ci	} else if (hw->max_frame_size >  ETH_FRAME_LEN + ETH_FCS_LEN) {
6028c2ecf20Sopenharmony_ci		/* adjust PBA for jumbo frames */
6038c2ecf20Sopenharmony_ci		ew32(PBA, pba);
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci		/* To maintain wire speed transmits, the Tx FIFO should be
6068c2ecf20Sopenharmony_ci		 * large enough to accommodate two full transmit packets,
6078c2ecf20Sopenharmony_ci		 * rounded up to the next 1KB and expressed in KB.  Likewise,
6088c2ecf20Sopenharmony_ci		 * the Rx FIFO should be large enough to accommodate at least
6098c2ecf20Sopenharmony_ci		 * one full receive packet and is similarly rounded up and
6108c2ecf20Sopenharmony_ci		 * expressed in KB.
6118c2ecf20Sopenharmony_ci		 */
6128c2ecf20Sopenharmony_ci		pba = er32(PBA);
6138c2ecf20Sopenharmony_ci		/* upper 16 bits has Tx packet buffer allocation size in KB */
6148c2ecf20Sopenharmony_ci		tx_space = pba >> 16;
6158c2ecf20Sopenharmony_ci		/* lower 16 bits has Rx packet buffer allocation size in KB */
6168c2ecf20Sopenharmony_ci		pba &= 0xffff;
6178c2ecf20Sopenharmony_ci		/* the Tx fifo also stores 16 bytes of information about the Tx
6188c2ecf20Sopenharmony_ci		 * but don't include ethernet FCS because hardware appends it
6198c2ecf20Sopenharmony_ci		 */
6208c2ecf20Sopenharmony_ci		min_tx_space = (hw->max_frame_size +
6218c2ecf20Sopenharmony_ci				sizeof(struct e1000_tx_desc) -
6228c2ecf20Sopenharmony_ci				ETH_FCS_LEN) * 2;
6238c2ecf20Sopenharmony_ci		min_tx_space = ALIGN(min_tx_space, 1024);
6248c2ecf20Sopenharmony_ci		min_tx_space >>= 10;
6258c2ecf20Sopenharmony_ci		/* software strips receive CRC, so leave room for it */
6268c2ecf20Sopenharmony_ci		min_rx_space = hw->max_frame_size;
6278c2ecf20Sopenharmony_ci		min_rx_space = ALIGN(min_rx_space, 1024);
6288c2ecf20Sopenharmony_ci		min_rx_space >>= 10;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci		/* If current Tx allocation is less than the min Tx FIFO size,
6318c2ecf20Sopenharmony_ci		 * and the min Tx FIFO size is less than the current Rx FIFO
6328c2ecf20Sopenharmony_ci		 * allocation, take space away from current Rx allocation
6338c2ecf20Sopenharmony_ci		 */
6348c2ecf20Sopenharmony_ci		if (tx_space < min_tx_space &&
6358c2ecf20Sopenharmony_ci		    ((min_tx_space - tx_space) < pba)) {
6368c2ecf20Sopenharmony_ci			pba = pba - (min_tx_space - tx_space);
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci			/* PCI/PCIx hardware has PBA alignment constraints */
6398c2ecf20Sopenharmony_ci			switch (hw->mac_type) {
6408c2ecf20Sopenharmony_ci			case e1000_82545 ... e1000_82546_rev_3:
6418c2ecf20Sopenharmony_ci				pba &= ~(E1000_PBA_8K - 1);
6428c2ecf20Sopenharmony_ci				break;
6438c2ecf20Sopenharmony_ci			default:
6448c2ecf20Sopenharmony_ci				break;
6458c2ecf20Sopenharmony_ci			}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci			/* if short on Rx space, Rx wins and must trump Tx
6488c2ecf20Sopenharmony_ci			 * adjustment or use Early Receive if available
6498c2ecf20Sopenharmony_ci			 */
6508c2ecf20Sopenharmony_ci			if (pba < min_rx_space)
6518c2ecf20Sopenharmony_ci				pba = min_rx_space;
6528c2ecf20Sopenharmony_ci		}
6538c2ecf20Sopenharmony_ci	}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	ew32(PBA, pba);
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	/* flow control settings:
6588c2ecf20Sopenharmony_ci	 * The high water mark must be low enough to fit one full frame
6598c2ecf20Sopenharmony_ci	 * (or the size used for early receive) above it in the Rx FIFO.
6608c2ecf20Sopenharmony_ci	 * Set it to the lower of:
6618c2ecf20Sopenharmony_ci	 * - 90% of the Rx FIFO size, and
6628c2ecf20Sopenharmony_ci	 * - the full Rx FIFO size minus the early receive size (for parts
6638c2ecf20Sopenharmony_ci	 *   with ERT support assuming ERT set to E1000_ERT_2048), or
6648c2ecf20Sopenharmony_ci	 * - the full Rx FIFO size minus one full frame
6658c2ecf20Sopenharmony_ci	 */
6668c2ecf20Sopenharmony_ci	hwm = min(((pba << 10) * 9 / 10),
6678c2ecf20Sopenharmony_ci		  ((pba << 10) - hw->max_frame_size));
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	hw->fc_high_water = hwm & 0xFFF8;	/* 8-byte granularity */
6708c2ecf20Sopenharmony_ci	hw->fc_low_water = hw->fc_high_water - 8;
6718c2ecf20Sopenharmony_ci	hw->fc_pause_time = E1000_FC_PAUSE_TIME;
6728c2ecf20Sopenharmony_ci	hw->fc_send_xon = 1;
6738c2ecf20Sopenharmony_ci	hw->fc = hw->original_fc;
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	/* Allow time for pending master requests to run */
6768c2ecf20Sopenharmony_ci	e1000_reset_hw(hw);
6778c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82544)
6788c2ecf20Sopenharmony_ci		ew32(WUC, 0);
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	if (e1000_init_hw(hw))
6818c2ecf20Sopenharmony_ci		e_dev_err("Hardware Error\n");
6828c2ecf20Sopenharmony_ci	e1000_update_mng_vlan(adapter);
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
6858c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82544 &&
6868c2ecf20Sopenharmony_ci	    hw->autoneg == 1 &&
6878c2ecf20Sopenharmony_ci	    hw->autoneg_advertised == ADVERTISE_1000_FULL) {
6888c2ecf20Sopenharmony_ci		u32 ctrl = er32(CTRL);
6898c2ecf20Sopenharmony_ci		/* clear phy power management bit if we are in gig only mode,
6908c2ecf20Sopenharmony_ci		 * which if enabled will attempt negotiation to 100Mb, which
6918c2ecf20Sopenharmony_ci		 * can cause a loss of link at power off or driver unload
6928c2ecf20Sopenharmony_ci		 */
6938c2ecf20Sopenharmony_ci		ctrl &= ~E1000_CTRL_SWDPIN3;
6948c2ecf20Sopenharmony_ci		ew32(CTRL, ctrl);
6958c2ecf20Sopenharmony_ci	}
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
6988c2ecf20Sopenharmony_ci	ew32(VET, ETHERNET_IEEE_VLAN_TYPE);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	e1000_reset_adaptive(hw);
7018c2ecf20Sopenharmony_ci	e1000_phy_get_info(hw, &adapter->phy_info);
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	e1000_release_manageability(adapter);
7048c2ecf20Sopenharmony_ci}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci/* Dump the eeprom for users having checksum issues */
7078c2ecf20Sopenharmony_cistatic void e1000_dump_eeprom(struct e1000_adapter *adapter)
7088c2ecf20Sopenharmony_ci{
7098c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
7108c2ecf20Sopenharmony_ci	struct ethtool_eeprom eeprom;
7118c2ecf20Sopenharmony_ci	const struct ethtool_ops *ops = netdev->ethtool_ops;
7128c2ecf20Sopenharmony_ci	u8 *data;
7138c2ecf20Sopenharmony_ci	int i;
7148c2ecf20Sopenharmony_ci	u16 csum_old, csum_new = 0;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	eeprom.len = ops->get_eeprom_len(netdev);
7178c2ecf20Sopenharmony_ci	eeprom.offset = 0;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	data = kmalloc(eeprom.len, GFP_KERNEL);
7208c2ecf20Sopenharmony_ci	if (!data)
7218c2ecf20Sopenharmony_ci		return;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	ops->get_eeprom(netdev, &eeprom, data);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	csum_old = (data[EEPROM_CHECKSUM_REG * 2]) +
7268c2ecf20Sopenharmony_ci		   (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8);
7278c2ecf20Sopenharmony_ci	for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2)
7288c2ecf20Sopenharmony_ci		csum_new += data[i] + (data[i + 1] << 8);
7298c2ecf20Sopenharmony_ci	csum_new = EEPROM_SUM - csum_new;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	pr_err("/*********************/\n");
7328c2ecf20Sopenharmony_ci	pr_err("Current EEPROM Checksum : 0x%04x\n", csum_old);
7338c2ecf20Sopenharmony_ci	pr_err("Calculated              : 0x%04x\n", csum_new);
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	pr_err("Offset    Values\n");
7368c2ecf20Sopenharmony_ci	pr_err("========  ======\n");
7378c2ecf20Sopenharmony_ci	print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0);
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	pr_err("Include this output when contacting your support provider.\n");
7408c2ecf20Sopenharmony_ci	pr_err("This is not a software error! Something bad happened to\n");
7418c2ecf20Sopenharmony_ci	pr_err("your hardware or EEPROM image. Ignoring this problem could\n");
7428c2ecf20Sopenharmony_ci	pr_err("result in further problems, possibly loss of data,\n");
7438c2ecf20Sopenharmony_ci	pr_err("corruption or system hangs!\n");
7448c2ecf20Sopenharmony_ci	pr_err("The MAC Address will be reset to 00:00:00:00:00:00,\n");
7458c2ecf20Sopenharmony_ci	pr_err("which is invalid and requires you to set the proper MAC\n");
7468c2ecf20Sopenharmony_ci	pr_err("address manually before continuing to enable this network\n");
7478c2ecf20Sopenharmony_ci	pr_err("device. Please inspect the EEPROM dump and report the\n");
7488c2ecf20Sopenharmony_ci	pr_err("issue to your hardware vendor or Intel Customer Support.\n");
7498c2ecf20Sopenharmony_ci	pr_err("/*********************/\n");
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	kfree(data);
7528c2ecf20Sopenharmony_ci}
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci/**
7558c2ecf20Sopenharmony_ci * e1000_is_need_ioport - determine if an adapter needs ioport resources or not
7568c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
7578c2ecf20Sopenharmony_ci *
7588c2ecf20Sopenharmony_ci * Return true if an adapter needs ioport resources
7598c2ecf20Sopenharmony_ci **/
7608c2ecf20Sopenharmony_cistatic int e1000_is_need_ioport(struct pci_dev *pdev)
7618c2ecf20Sopenharmony_ci{
7628c2ecf20Sopenharmony_ci	switch (pdev->device) {
7638c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EM:
7648c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EM_LOM:
7658c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EP:
7668c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EP_LOM:
7678c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82540EP_LP:
7688c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541EI:
7698c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541EI_MOBILE:
7708c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541ER:
7718c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541ER_LOM:
7728c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541GI:
7738c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541GI_LF:
7748c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82541GI_MOBILE:
7758c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82544EI_COPPER:
7768c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82544EI_FIBER:
7778c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82544GC_COPPER:
7788c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82544GC_LOM:
7798c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82545EM_COPPER:
7808c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82545EM_FIBER:
7818c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546EB_COPPER:
7828c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546EB_FIBER:
7838c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546EB_QUAD_COPPER:
7848c2ecf20Sopenharmony_ci		return true;
7858c2ecf20Sopenharmony_ci	default:
7868c2ecf20Sopenharmony_ci		return false;
7878c2ecf20Sopenharmony_ci	}
7888c2ecf20Sopenharmony_ci}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_cistatic netdev_features_t e1000_fix_features(struct net_device *netdev,
7918c2ecf20Sopenharmony_ci	netdev_features_t features)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	/* Since there is no support for separate Rx/Tx vlan accel
7948c2ecf20Sopenharmony_ci	 * enable/disable make sure Tx flag is always in same state as Rx.
7958c2ecf20Sopenharmony_ci	 */
7968c2ecf20Sopenharmony_ci	if (features & NETIF_F_HW_VLAN_CTAG_RX)
7978c2ecf20Sopenharmony_ci		features |= NETIF_F_HW_VLAN_CTAG_TX;
7988c2ecf20Sopenharmony_ci	else
7998c2ecf20Sopenharmony_ci		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	return features;
8028c2ecf20Sopenharmony_ci}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_cistatic int e1000_set_features(struct net_device *netdev,
8058c2ecf20Sopenharmony_ci	netdev_features_t features)
8068c2ecf20Sopenharmony_ci{
8078c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
8088c2ecf20Sopenharmony_ci	netdev_features_t changed = features ^ netdev->features;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
8118c2ecf20Sopenharmony_ci		e1000_vlan_mode(netdev, features);
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	if (!(changed & (NETIF_F_RXCSUM | NETIF_F_RXALL)))
8148c2ecf20Sopenharmony_ci		return 0;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	netdev->features = features;
8178c2ecf20Sopenharmony_ci	adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	if (netif_running(netdev))
8208c2ecf20Sopenharmony_ci		e1000_reinit_locked(adapter);
8218c2ecf20Sopenharmony_ci	else
8228c2ecf20Sopenharmony_ci		e1000_reset(adapter);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	return 1;
8258c2ecf20Sopenharmony_ci}
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_cistatic const struct net_device_ops e1000_netdev_ops = {
8288c2ecf20Sopenharmony_ci	.ndo_open		= e1000_open,
8298c2ecf20Sopenharmony_ci	.ndo_stop		= e1000_close,
8308c2ecf20Sopenharmony_ci	.ndo_start_xmit		= e1000_xmit_frame,
8318c2ecf20Sopenharmony_ci	.ndo_set_rx_mode	= e1000_set_rx_mode,
8328c2ecf20Sopenharmony_ci	.ndo_set_mac_address	= e1000_set_mac,
8338c2ecf20Sopenharmony_ci	.ndo_tx_timeout		= e1000_tx_timeout,
8348c2ecf20Sopenharmony_ci	.ndo_change_mtu		= e1000_change_mtu,
8358c2ecf20Sopenharmony_ci	.ndo_do_ioctl		= e1000_ioctl,
8368c2ecf20Sopenharmony_ci	.ndo_validate_addr	= eth_validate_addr,
8378c2ecf20Sopenharmony_ci	.ndo_vlan_rx_add_vid	= e1000_vlan_rx_add_vid,
8388c2ecf20Sopenharmony_ci	.ndo_vlan_rx_kill_vid	= e1000_vlan_rx_kill_vid,
8398c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
8408c2ecf20Sopenharmony_ci	.ndo_poll_controller	= e1000_netpoll,
8418c2ecf20Sopenharmony_ci#endif
8428c2ecf20Sopenharmony_ci	.ndo_fix_features	= e1000_fix_features,
8438c2ecf20Sopenharmony_ci	.ndo_set_features	= e1000_set_features,
8448c2ecf20Sopenharmony_ci};
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci/**
8478c2ecf20Sopenharmony_ci * e1000_init_hw_struct - initialize members of hw struct
8488c2ecf20Sopenharmony_ci * @adapter: board private struct
8498c2ecf20Sopenharmony_ci * @hw: structure used by e1000_hw.c
8508c2ecf20Sopenharmony_ci *
8518c2ecf20Sopenharmony_ci * Factors out initialization of the e1000_hw struct to its own function
8528c2ecf20Sopenharmony_ci * that can be called very early at init (just after struct allocation).
8538c2ecf20Sopenharmony_ci * Fields are initialized based on PCI device information and
8548c2ecf20Sopenharmony_ci * OS network device settings (MTU size).
8558c2ecf20Sopenharmony_ci * Returns negative error codes if MAC type setup fails.
8568c2ecf20Sopenharmony_ci */
8578c2ecf20Sopenharmony_cistatic int e1000_init_hw_struct(struct e1000_adapter *adapter,
8588c2ecf20Sopenharmony_ci				struct e1000_hw *hw)
8598c2ecf20Sopenharmony_ci{
8608c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	/* PCI config space info */
8638c2ecf20Sopenharmony_ci	hw->vendor_id = pdev->vendor;
8648c2ecf20Sopenharmony_ci	hw->device_id = pdev->device;
8658c2ecf20Sopenharmony_ci	hw->subsystem_vendor_id = pdev->subsystem_vendor;
8668c2ecf20Sopenharmony_ci	hw->subsystem_id = pdev->subsystem_device;
8678c2ecf20Sopenharmony_ci	hw->revision_id = pdev->revision;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	hw->max_frame_size = adapter->netdev->mtu +
8728c2ecf20Sopenharmony_ci			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
8738c2ecf20Sopenharmony_ci	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	/* identify the MAC */
8768c2ecf20Sopenharmony_ci	if (e1000_set_mac_type(hw)) {
8778c2ecf20Sopenharmony_ci		e_err(probe, "Unknown MAC Type\n");
8788c2ecf20Sopenharmony_ci		return -EIO;
8798c2ecf20Sopenharmony_ci	}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
8828c2ecf20Sopenharmony_ci	default:
8838c2ecf20Sopenharmony_ci		break;
8848c2ecf20Sopenharmony_ci	case e1000_82541:
8858c2ecf20Sopenharmony_ci	case e1000_82547:
8868c2ecf20Sopenharmony_ci	case e1000_82541_rev_2:
8878c2ecf20Sopenharmony_ci	case e1000_82547_rev_2:
8888c2ecf20Sopenharmony_ci		hw->phy_init_script = 1;
8898c2ecf20Sopenharmony_ci		break;
8908c2ecf20Sopenharmony_ci	}
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	e1000_set_media_type(hw);
8938c2ecf20Sopenharmony_ci	e1000_get_bus_info(hw);
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	hw->wait_autoneg_complete = false;
8968c2ecf20Sopenharmony_ci	hw->tbi_compatibility_en = true;
8978c2ecf20Sopenharmony_ci	hw->adaptive_ifs = true;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	/* Copper options */
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	if (hw->media_type == e1000_media_type_copper) {
9028c2ecf20Sopenharmony_ci		hw->mdix = AUTO_ALL_MODES;
9038c2ecf20Sopenharmony_ci		hw->disable_polarity_correction = false;
9048c2ecf20Sopenharmony_ci		hw->master_slave = E1000_MASTER_SLAVE;
9058c2ecf20Sopenharmony_ci	}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	return 0;
9088c2ecf20Sopenharmony_ci}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci/**
9118c2ecf20Sopenharmony_ci * e1000_probe - Device Initialization Routine
9128c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
9138c2ecf20Sopenharmony_ci * @ent: entry in e1000_pci_tbl
9148c2ecf20Sopenharmony_ci *
9158c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
9168c2ecf20Sopenharmony_ci *
9178c2ecf20Sopenharmony_ci * e1000_probe initializes an adapter identified by a pci_dev structure.
9188c2ecf20Sopenharmony_ci * The OS initialization, configuring of the adapter private structure,
9198c2ecf20Sopenharmony_ci * and a hardware reset occur.
9208c2ecf20Sopenharmony_ci **/
9218c2ecf20Sopenharmony_cistatic int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
9228c2ecf20Sopenharmony_ci{
9238c2ecf20Sopenharmony_ci	struct net_device *netdev;
9248c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = NULL;
9258c2ecf20Sopenharmony_ci	struct e1000_hw *hw;
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	static int cards_found;
9288c2ecf20Sopenharmony_ci	static int global_quad_port_a; /* global ksp3 port a indication */
9298c2ecf20Sopenharmony_ci	int i, err, pci_using_dac;
9308c2ecf20Sopenharmony_ci	u16 eeprom_data = 0;
9318c2ecf20Sopenharmony_ci	u16 tmp = 0;
9328c2ecf20Sopenharmony_ci	u16 eeprom_apme_mask = E1000_EEPROM_APME;
9338c2ecf20Sopenharmony_ci	int bars, need_ioport;
9348c2ecf20Sopenharmony_ci	bool disable_dev = false;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	/* do not allocate ioport bars when not needed */
9378c2ecf20Sopenharmony_ci	need_ioport = e1000_is_need_ioport(pdev);
9388c2ecf20Sopenharmony_ci	if (need_ioport) {
9398c2ecf20Sopenharmony_ci		bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
9408c2ecf20Sopenharmony_ci		err = pci_enable_device(pdev);
9418c2ecf20Sopenharmony_ci	} else {
9428c2ecf20Sopenharmony_ci		bars = pci_select_bars(pdev, IORESOURCE_MEM);
9438c2ecf20Sopenharmony_ci		err = pci_enable_device_mem(pdev);
9448c2ecf20Sopenharmony_ci	}
9458c2ecf20Sopenharmony_ci	if (err)
9468c2ecf20Sopenharmony_ci		return err;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
9498c2ecf20Sopenharmony_ci	if (err)
9508c2ecf20Sopenharmony_ci		goto err_pci_reg;
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	pci_set_master(pdev);
9538c2ecf20Sopenharmony_ci	err = pci_save_state(pdev);
9548c2ecf20Sopenharmony_ci	if (err)
9558c2ecf20Sopenharmony_ci		goto err_alloc_etherdev;
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci	err = -ENOMEM;
9588c2ecf20Sopenharmony_ci	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
9598c2ecf20Sopenharmony_ci	if (!netdev)
9608c2ecf20Sopenharmony_ci		goto err_alloc_etherdev;
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	SET_NETDEV_DEV(netdev, &pdev->dev);
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, netdev);
9658c2ecf20Sopenharmony_ci	adapter = netdev_priv(netdev);
9668c2ecf20Sopenharmony_ci	adapter->netdev = netdev;
9678c2ecf20Sopenharmony_ci	adapter->pdev = pdev;
9688c2ecf20Sopenharmony_ci	adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
9698c2ecf20Sopenharmony_ci	adapter->bars = bars;
9708c2ecf20Sopenharmony_ci	adapter->need_ioport = need_ioport;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	hw = &adapter->hw;
9738c2ecf20Sopenharmony_ci	hw->back = adapter;
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	err = -EIO;
9768c2ecf20Sopenharmony_ci	hw->hw_addr = pci_ioremap_bar(pdev, BAR_0);
9778c2ecf20Sopenharmony_ci	if (!hw->hw_addr)
9788c2ecf20Sopenharmony_ci		goto err_ioremap;
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci	if (adapter->need_ioport) {
9818c2ecf20Sopenharmony_ci		for (i = BAR_1; i < PCI_STD_NUM_BARS; i++) {
9828c2ecf20Sopenharmony_ci			if (pci_resource_len(pdev, i) == 0)
9838c2ecf20Sopenharmony_ci				continue;
9848c2ecf20Sopenharmony_ci			if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
9858c2ecf20Sopenharmony_ci				hw->io_base = pci_resource_start(pdev, i);
9868c2ecf20Sopenharmony_ci				break;
9878c2ecf20Sopenharmony_ci			}
9888c2ecf20Sopenharmony_ci		}
9898c2ecf20Sopenharmony_ci	}
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	/* make ready for any if (hw->...) below */
9928c2ecf20Sopenharmony_ci	err = e1000_init_hw_struct(adapter, hw);
9938c2ecf20Sopenharmony_ci	if (err)
9948c2ecf20Sopenharmony_ci		goto err_sw_init;
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	/* there is a workaround being applied below that limits
9978c2ecf20Sopenharmony_ci	 * 64-bit DMA addresses to 64-bit hardware.  There are some
9988c2ecf20Sopenharmony_ci	 * 32-bit adapters that Tx hang when given 64-bit DMA addresses
9998c2ecf20Sopenharmony_ci	 */
10008c2ecf20Sopenharmony_ci	pci_using_dac = 0;
10018c2ecf20Sopenharmony_ci	if ((hw->bus_type == e1000_bus_type_pcix) &&
10028c2ecf20Sopenharmony_ci	    !dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
10038c2ecf20Sopenharmony_ci		pci_using_dac = 1;
10048c2ecf20Sopenharmony_ci	} else {
10058c2ecf20Sopenharmony_ci		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
10068c2ecf20Sopenharmony_ci		if (err) {
10078c2ecf20Sopenharmony_ci			pr_err("No usable DMA config, aborting\n");
10088c2ecf20Sopenharmony_ci			goto err_dma;
10098c2ecf20Sopenharmony_ci		}
10108c2ecf20Sopenharmony_ci	}
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	netdev->netdev_ops = &e1000_netdev_ops;
10138c2ecf20Sopenharmony_ci	e1000_set_ethtool_ops(netdev);
10148c2ecf20Sopenharmony_ci	netdev->watchdog_timeo = 5 * HZ;
10158c2ecf20Sopenharmony_ci	netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	adapter->bd_number = cards_found;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	/* setup the private structure */
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	err = e1000_sw_init(adapter);
10248c2ecf20Sopenharmony_ci	if (err)
10258c2ecf20Sopenharmony_ci		goto err_sw_init;
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	err = -EIO;
10288c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_ce4100) {
10298c2ecf20Sopenharmony_ci		hw->ce4100_gbe_mdio_base_virt =
10308c2ecf20Sopenharmony_ci					ioremap(pci_resource_start(pdev, BAR_1),
10318c2ecf20Sopenharmony_ci						pci_resource_len(pdev, BAR_1));
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci		if (!hw->ce4100_gbe_mdio_base_virt)
10348c2ecf20Sopenharmony_ci			goto err_mdio_ioremap;
10358c2ecf20Sopenharmony_ci	}
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82543) {
10388c2ecf20Sopenharmony_ci		netdev->hw_features = NETIF_F_SG |
10398c2ecf20Sopenharmony_ci				   NETIF_F_HW_CSUM |
10408c2ecf20Sopenharmony_ci				   NETIF_F_HW_VLAN_CTAG_RX;
10418c2ecf20Sopenharmony_ci		netdev->features = NETIF_F_HW_VLAN_CTAG_TX |
10428c2ecf20Sopenharmony_ci				   NETIF_F_HW_VLAN_CTAG_FILTER;
10438c2ecf20Sopenharmony_ci	}
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	if ((hw->mac_type >= e1000_82544) &&
10468c2ecf20Sopenharmony_ci	   (hw->mac_type != e1000_82547))
10478c2ecf20Sopenharmony_ci		netdev->hw_features |= NETIF_F_TSO;
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	netdev->priv_flags |= IFF_SUPP_NOFCS;
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	netdev->features |= netdev->hw_features;
10528c2ecf20Sopenharmony_ci	netdev->hw_features |= (NETIF_F_RXCSUM |
10538c2ecf20Sopenharmony_ci				NETIF_F_RXALL |
10548c2ecf20Sopenharmony_ci				NETIF_F_RXFCS);
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	if (pci_using_dac) {
10578c2ecf20Sopenharmony_ci		netdev->features |= NETIF_F_HIGHDMA;
10588c2ecf20Sopenharmony_ci		netdev->vlan_features |= NETIF_F_HIGHDMA;
10598c2ecf20Sopenharmony_ci	}
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	netdev->vlan_features |= (NETIF_F_TSO |
10628c2ecf20Sopenharmony_ci				  NETIF_F_HW_CSUM |
10638c2ecf20Sopenharmony_ci				  NETIF_F_SG);
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	/* Do not set IFF_UNICAST_FLT for VMWare's 82545EM */
10668c2ecf20Sopenharmony_ci	if (hw->device_id != E1000_DEV_ID_82545EM_COPPER ||
10678c2ecf20Sopenharmony_ci	    hw->subsystem_vendor_id != PCI_VENDOR_ID_VMWARE)
10688c2ecf20Sopenharmony_ci		netdev->priv_flags |= IFF_UNICAST_FLT;
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	/* MTU range: 46 - 16110 */
10718c2ecf20Sopenharmony_ci	netdev->min_mtu = ETH_ZLEN - ETH_HLEN;
10728c2ecf20Sopenharmony_ci	netdev->max_mtu = MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	/* initialize eeprom parameters */
10778c2ecf20Sopenharmony_ci	if (e1000_init_eeprom_params(hw)) {
10788c2ecf20Sopenharmony_ci		e_err(probe, "EEPROM initialization failed\n");
10798c2ecf20Sopenharmony_ci		goto err_eeprom;
10808c2ecf20Sopenharmony_ci	}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	/* before reading the EEPROM, reset the controller to
10838c2ecf20Sopenharmony_ci	 * put the device in a known good starting state
10848c2ecf20Sopenharmony_ci	 */
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	e1000_reset_hw(hw);
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	/* make sure the EEPROM is good */
10898c2ecf20Sopenharmony_ci	if (e1000_validate_eeprom_checksum(hw) < 0) {
10908c2ecf20Sopenharmony_ci		e_err(probe, "The EEPROM Checksum Is Not Valid\n");
10918c2ecf20Sopenharmony_ci		e1000_dump_eeprom(adapter);
10928c2ecf20Sopenharmony_ci		/* set MAC address to all zeroes to invalidate and temporary
10938c2ecf20Sopenharmony_ci		 * disable this device for the user. This blocks regular
10948c2ecf20Sopenharmony_ci		 * traffic while still permitting ethtool ioctls from reaching
10958c2ecf20Sopenharmony_ci		 * the hardware as well as allowing the user to run the
10968c2ecf20Sopenharmony_ci		 * interface after manually setting a hw addr using
10978c2ecf20Sopenharmony_ci		 * `ip set address`
10988c2ecf20Sopenharmony_ci		 */
10998c2ecf20Sopenharmony_ci		memset(hw->mac_addr, 0, netdev->addr_len);
11008c2ecf20Sopenharmony_ci	} else {
11018c2ecf20Sopenharmony_ci		/* copy the MAC address out of the EEPROM */
11028c2ecf20Sopenharmony_ci		if (e1000_read_mac_addr(hw))
11038c2ecf20Sopenharmony_ci			e_err(probe, "EEPROM Read Error\n");
11048c2ecf20Sopenharmony_ci	}
11058c2ecf20Sopenharmony_ci	/* don't block initialization here due to bad MAC address */
11068c2ecf20Sopenharmony_ci	memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci	if (!is_valid_ether_addr(netdev->dev_addr))
11098c2ecf20Sopenharmony_ci		e_err(probe, "Invalid MAC Address\n");
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog);
11138c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&adapter->fifo_stall_task,
11148c2ecf20Sopenharmony_ci			  e1000_82547_tx_fifo_stall_task);
11158c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&adapter->phy_info_task, e1000_update_phy_info_task);
11168c2ecf20Sopenharmony_ci	INIT_WORK(&adapter->reset_task, e1000_reset_task);
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	e1000_check_options(adapter);
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	/* Initial Wake on LAN setting
11218c2ecf20Sopenharmony_ci	 * If APM wake is enabled in the EEPROM,
11228c2ecf20Sopenharmony_ci	 * enable the ACPI Magic Packet filter
11238c2ecf20Sopenharmony_ci	 */
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
11268c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
11278c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
11288c2ecf20Sopenharmony_ci	case e1000_82543:
11298c2ecf20Sopenharmony_ci		break;
11308c2ecf20Sopenharmony_ci	case e1000_82544:
11318c2ecf20Sopenharmony_ci		e1000_read_eeprom(hw,
11328c2ecf20Sopenharmony_ci			EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
11338c2ecf20Sopenharmony_ci		eeprom_apme_mask = E1000_EEPROM_82544_APM;
11348c2ecf20Sopenharmony_ci		break;
11358c2ecf20Sopenharmony_ci	case e1000_82546:
11368c2ecf20Sopenharmony_ci	case e1000_82546_rev_3:
11378c2ecf20Sopenharmony_ci		if (er32(STATUS) & E1000_STATUS_FUNC_1) {
11388c2ecf20Sopenharmony_ci			e1000_read_eeprom(hw,
11398c2ecf20Sopenharmony_ci				EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
11408c2ecf20Sopenharmony_ci			break;
11418c2ecf20Sopenharmony_ci		}
11428c2ecf20Sopenharmony_ci		fallthrough;
11438c2ecf20Sopenharmony_ci	default:
11448c2ecf20Sopenharmony_ci		e1000_read_eeprom(hw,
11458c2ecf20Sopenharmony_ci			EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
11468c2ecf20Sopenharmony_ci		break;
11478c2ecf20Sopenharmony_ci	}
11488c2ecf20Sopenharmony_ci	if (eeprom_data & eeprom_apme_mask)
11498c2ecf20Sopenharmony_ci		adapter->eeprom_wol |= E1000_WUFC_MAG;
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	/* now that we have the eeprom settings, apply the special cases
11528c2ecf20Sopenharmony_ci	 * where the eeprom may be wrong or the board simply won't support
11538c2ecf20Sopenharmony_ci	 * wake on lan on a particular port
11548c2ecf20Sopenharmony_ci	 */
11558c2ecf20Sopenharmony_ci	switch (pdev->device) {
11568c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_PCIE:
11578c2ecf20Sopenharmony_ci		adapter->eeprom_wol = 0;
11588c2ecf20Sopenharmony_ci		break;
11598c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546EB_FIBER:
11608c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_FIBER:
11618c2ecf20Sopenharmony_ci		/* Wake events only supported on port A for dual fiber
11628c2ecf20Sopenharmony_ci		 * regardless of eeprom setting
11638c2ecf20Sopenharmony_ci		 */
11648c2ecf20Sopenharmony_ci		if (er32(STATUS) & E1000_STATUS_FUNC_1)
11658c2ecf20Sopenharmony_ci			adapter->eeprom_wol = 0;
11668c2ecf20Sopenharmony_ci		break;
11678c2ecf20Sopenharmony_ci	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
11688c2ecf20Sopenharmony_ci		/* if quad port adapter, disable WoL on all but port A */
11698c2ecf20Sopenharmony_ci		if (global_quad_port_a != 0)
11708c2ecf20Sopenharmony_ci			adapter->eeprom_wol = 0;
11718c2ecf20Sopenharmony_ci		else
11728c2ecf20Sopenharmony_ci			adapter->quad_port_a = true;
11738c2ecf20Sopenharmony_ci		/* Reset for multiple quad port adapters */
11748c2ecf20Sopenharmony_ci		if (++global_quad_port_a == 4)
11758c2ecf20Sopenharmony_ci			global_quad_port_a = 0;
11768c2ecf20Sopenharmony_ci		break;
11778c2ecf20Sopenharmony_ci	}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	/* initialize the wol settings based on the eeprom settings */
11808c2ecf20Sopenharmony_ci	adapter->wol = adapter->eeprom_wol;
11818c2ecf20Sopenharmony_ci	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	/* Auto detect PHY address */
11848c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_ce4100) {
11858c2ecf20Sopenharmony_ci		for (i = 0; i < 32; i++) {
11868c2ecf20Sopenharmony_ci			hw->phy_addr = i;
11878c2ecf20Sopenharmony_ci			e1000_read_phy_reg(hw, PHY_ID2, &tmp);
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci			if (tmp != 0 && tmp != 0xFF)
11908c2ecf20Sopenharmony_ci				break;
11918c2ecf20Sopenharmony_ci		}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci		if (i >= 32)
11948c2ecf20Sopenharmony_ci			goto err_eeprom;
11958c2ecf20Sopenharmony_ci	}
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	/* reset the hardware with the new settings */
11988c2ecf20Sopenharmony_ci	e1000_reset(adapter);
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	strcpy(netdev->name, "eth%d");
12018c2ecf20Sopenharmony_ci	err = register_netdev(netdev);
12028c2ecf20Sopenharmony_ci	if (err)
12038c2ecf20Sopenharmony_ci		goto err_register;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	e1000_vlan_filter_on_off(adapter, false);
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	/* print bus type/speed/width info */
12088c2ecf20Sopenharmony_ci	e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n",
12098c2ecf20Sopenharmony_ci	       ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
12108c2ecf20Sopenharmony_ci	       ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
12118c2ecf20Sopenharmony_ci		(hw->bus_speed == e1000_bus_speed_120) ? 120 :
12128c2ecf20Sopenharmony_ci		(hw->bus_speed == e1000_bus_speed_100) ? 100 :
12138c2ecf20Sopenharmony_ci		(hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
12148c2ecf20Sopenharmony_ci	       ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
12158c2ecf20Sopenharmony_ci	       netdev->dev_addr);
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	/* carrier off reporting is important to ethtool even BEFORE open */
12188c2ecf20Sopenharmony_ci	netif_carrier_off(netdev);
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	e_info(probe, "Intel(R) PRO/1000 Network Connection\n");
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	cards_found++;
12238c2ecf20Sopenharmony_ci	return 0;
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_cierr_register:
12268c2ecf20Sopenharmony_cierr_eeprom:
12278c2ecf20Sopenharmony_ci	e1000_phy_hw_reset(hw);
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	if (hw->flash_address)
12308c2ecf20Sopenharmony_ci		iounmap(hw->flash_address);
12318c2ecf20Sopenharmony_ci	kfree(adapter->tx_ring);
12328c2ecf20Sopenharmony_ci	kfree(adapter->rx_ring);
12338c2ecf20Sopenharmony_cierr_dma:
12348c2ecf20Sopenharmony_cierr_sw_init:
12358c2ecf20Sopenharmony_cierr_mdio_ioremap:
12368c2ecf20Sopenharmony_ci	iounmap(hw->ce4100_gbe_mdio_base_virt);
12378c2ecf20Sopenharmony_ci	iounmap(hw->hw_addr);
12388c2ecf20Sopenharmony_cierr_ioremap:
12398c2ecf20Sopenharmony_ci	disable_dev = !test_and_set_bit(__E1000_DISABLED, &adapter->flags);
12408c2ecf20Sopenharmony_ci	free_netdev(netdev);
12418c2ecf20Sopenharmony_cierr_alloc_etherdev:
12428c2ecf20Sopenharmony_ci	pci_release_selected_regions(pdev, bars);
12438c2ecf20Sopenharmony_cierr_pci_reg:
12448c2ecf20Sopenharmony_ci	if (!adapter || disable_dev)
12458c2ecf20Sopenharmony_ci		pci_disable_device(pdev);
12468c2ecf20Sopenharmony_ci	return err;
12478c2ecf20Sopenharmony_ci}
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci/**
12508c2ecf20Sopenharmony_ci * e1000_remove - Device Removal Routine
12518c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
12528c2ecf20Sopenharmony_ci *
12538c2ecf20Sopenharmony_ci * e1000_remove is called by the PCI subsystem to alert the driver
12548c2ecf20Sopenharmony_ci * that it should release a PCI device. That could be caused by a
12558c2ecf20Sopenharmony_ci * Hot-Plug event, or because the driver is going to be removed from
12568c2ecf20Sopenharmony_ci * memory.
12578c2ecf20Sopenharmony_ci **/
12588c2ecf20Sopenharmony_cistatic void e1000_remove(struct pci_dev *pdev)
12598c2ecf20Sopenharmony_ci{
12608c2ecf20Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
12618c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
12628c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
12638c2ecf20Sopenharmony_ci	bool disable_dev;
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	e1000_down_and_stop(adapter);
12668c2ecf20Sopenharmony_ci	e1000_release_manageability(adapter);
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	unregister_netdev(netdev);
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	e1000_phy_hw_reset(hw);
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	kfree(adapter->tx_ring);
12738c2ecf20Sopenharmony_ci	kfree(adapter->rx_ring);
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_ce4100)
12768c2ecf20Sopenharmony_ci		iounmap(hw->ce4100_gbe_mdio_base_virt);
12778c2ecf20Sopenharmony_ci	iounmap(hw->hw_addr);
12788c2ecf20Sopenharmony_ci	if (hw->flash_address)
12798c2ecf20Sopenharmony_ci		iounmap(hw->flash_address);
12808c2ecf20Sopenharmony_ci	pci_release_selected_regions(pdev, adapter->bars);
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	disable_dev = !test_and_set_bit(__E1000_DISABLED, &adapter->flags);
12838c2ecf20Sopenharmony_ci	free_netdev(netdev);
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	if (disable_dev)
12868c2ecf20Sopenharmony_ci		pci_disable_device(pdev);
12878c2ecf20Sopenharmony_ci}
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci/**
12908c2ecf20Sopenharmony_ci * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
12918c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize
12928c2ecf20Sopenharmony_ci *
12938c2ecf20Sopenharmony_ci * e1000_sw_init initializes the Adapter private data structure.
12948c2ecf20Sopenharmony_ci * e1000_init_hw_struct MUST be called before this function
12958c2ecf20Sopenharmony_ci **/
12968c2ecf20Sopenharmony_cistatic int e1000_sw_init(struct e1000_adapter *adapter)
12978c2ecf20Sopenharmony_ci{
12988c2ecf20Sopenharmony_ci	adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	adapter->num_tx_queues = 1;
13018c2ecf20Sopenharmony_ci	adapter->num_rx_queues = 1;
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	if (e1000_alloc_queues(adapter)) {
13048c2ecf20Sopenharmony_ci		e_err(probe, "Unable to allocate memory for queues\n");
13058c2ecf20Sopenharmony_ci		return -ENOMEM;
13068c2ecf20Sopenharmony_ci	}
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	/* Explicitly disable IRQ since the NIC can be in any state. */
13098c2ecf20Sopenharmony_ci	e1000_irq_disable(adapter);
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	spin_lock_init(&adapter->stats_lock);
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	set_bit(__E1000_DOWN, &adapter->flags);
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	return 0;
13168c2ecf20Sopenharmony_ci}
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_ci/**
13198c2ecf20Sopenharmony_ci * e1000_alloc_queues - Allocate memory for all rings
13208c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize
13218c2ecf20Sopenharmony_ci *
13228c2ecf20Sopenharmony_ci * We allocate one ring per queue at run-time since we don't know the
13238c2ecf20Sopenharmony_ci * number of queues at compile-time.
13248c2ecf20Sopenharmony_ci **/
13258c2ecf20Sopenharmony_cistatic int e1000_alloc_queues(struct e1000_adapter *adapter)
13268c2ecf20Sopenharmony_ci{
13278c2ecf20Sopenharmony_ci	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
13288c2ecf20Sopenharmony_ci				   sizeof(struct e1000_tx_ring), GFP_KERNEL);
13298c2ecf20Sopenharmony_ci	if (!adapter->tx_ring)
13308c2ecf20Sopenharmony_ci		return -ENOMEM;
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	adapter->rx_ring = kcalloc(adapter->num_rx_queues,
13338c2ecf20Sopenharmony_ci				   sizeof(struct e1000_rx_ring), GFP_KERNEL);
13348c2ecf20Sopenharmony_ci	if (!adapter->rx_ring) {
13358c2ecf20Sopenharmony_ci		kfree(adapter->tx_ring);
13368c2ecf20Sopenharmony_ci		return -ENOMEM;
13378c2ecf20Sopenharmony_ci	}
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
13408c2ecf20Sopenharmony_ci}
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci/**
13438c2ecf20Sopenharmony_ci * e1000_open - Called when a network interface is made active
13448c2ecf20Sopenharmony_ci * @netdev: network interface device structure
13458c2ecf20Sopenharmony_ci *
13468c2ecf20Sopenharmony_ci * Returns 0 on success, negative value on failure
13478c2ecf20Sopenharmony_ci *
13488c2ecf20Sopenharmony_ci * The open entry point is called when a network interface is made
13498c2ecf20Sopenharmony_ci * active by the system (IFF_UP).  At this point all resources needed
13508c2ecf20Sopenharmony_ci * for transmit and receive operations are allocated, the interrupt
13518c2ecf20Sopenharmony_ci * handler is registered with the OS, the watchdog task is started,
13528c2ecf20Sopenharmony_ci * and the stack is notified that the interface is ready.
13538c2ecf20Sopenharmony_ci **/
13548c2ecf20Sopenharmony_ciint e1000_open(struct net_device *netdev)
13558c2ecf20Sopenharmony_ci{
13568c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
13578c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
13588c2ecf20Sopenharmony_ci	int err;
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	/* disallow open during test */
13618c2ecf20Sopenharmony_ci	if (test_bit(__E1000_TESTING, &adapter->flags))
13628c2ecf20Sopenharmony_ci		return -EBUSY;
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	netif_carrier_off(netdev);
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	/* allocate transmit descriptors */
13678c2ecf20Sopenharmony_ci	err = e1000_setup_all_tx_resources(adapter);
13688c2ecf20Sopenharmony_ci	if (err)
13698c2ecf20Sopenharmony_ci		goto err_setup_tx;
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	/* allocate receive descriptors */
13728c2ecf20Sopenharmony_ci	err = e1000_setup_all_rx_resources(adapter);
13738c2ecf20Sopenharmony_ci	if (err)
13748c2ecf20Sopenharmony_ci		goto err_setup_rx;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	e1000_power_up_phy(adapter);
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci	adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
13798c2ecf20Sopenharmony_ci	if ((hw->mng_cookie.status &
13808c2ecf20Sopenharmony_ci			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
13818c2ecf20Sopenharmony_ci		e1000_update_mng_vlan(adapter);
13828c2ecf20Sopenharmony_ci	}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	/* before we allocate an interrupt, we must be ready to handle it.
13858c2ecf20Sopenharmony_ci	 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
13868c2ecf20Sopenharmony_ci	 * as soon as we call pci_request_irq, so we have to setup our
13878c2ecf20Sopenharmony_ci	 * clean_rx handler before we do so.
13888c2ecf20Sopenharmony_ci	 */
13898c2ecf20Sopenharmony_ci	e1000_configure(adapter);
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	err = e1000_request_irq(adapter);
13928c2ecf20Sopenharmony_ci	if (err)
13938c2ecf20Sopenharmony_ci		goto err_req_irq;
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	/* From here on the code is the same as e1000_up() */
13968c2ecf20Sopenharmony_ci	clear_bit(__E1000_DOWN, &adapter->flags);
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	napi_enable(&adapter->napi);
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci	e1000_irq_enable(adapter);
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci	netif_start_queue(netdev);
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	/* fire a link status change interrupt to start the watchdog */
14058c2ecf20Sopenharmony_ci	ew32(ICS, E1000_ICS_LSC);
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_cierr_req_irq:
14108c2ecf20Sopenharmony_ci	e1000_power_down_phy(adapter);
14118c2ecf20Sopenharmony_ci	e1000_free_all_rx_resources(adapter);
14128c2ecf20Sopenharmony_cierr_setup_rx:
14138c2ecf20Sopenharmony_ci	e1000_free_all_tx_resources(adapter);
14148c2ecf20Sopenharmony_cierr_setup_tx:
14158c2ecf20Sopenharmony_ci	e1000_reset(adapter);
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_ci	return err;
14188c2ecf20Sopenharmony_ci}
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci/**
14218c2ecf20Sopenharmony_ci * e1000_close - Disables a network interface
14228c2ecf20Sopenharmony_ci * @netdev: network interface device structure
14238c2ecf20Sopenharmony_ci *
14248c2ecf20Sopenharmony_ci * Returns 0, this is not allowed to fail
14258c2ecf20Sopenharmony_ci *
14268c2ecf20Sopenharmony_ci * The close entry point is called when an interface is de-activated
14278c2ecf20Sopenharmony_ci * by the OS.  The hardware is still under the drivers control, but
14288c2ecf20Sopenharmony_ci * needs to be disabled.  A global MAC reset is issued to stop the
14298c2ecf20Sopenharmony_ci * hardware, and all transmit and receive resources are freed.
14308c2ecf20Sopenharmony_ci **/
14318c2ecf20Sopenharmony_ciint e1000_close(struct net_device *netdev)
14328c2ecf20Sopenharmony_ci{
14338c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
14348c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
14358c2ecf20Sopenharmony_ci	int count = E1000_CHECK_RESET_COUNT;
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags) && count--)
14388c2ecf20Sopenharmony_ci		usleep_range(10000, 20000);
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	WARN_ON(count < 0);
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	/* signal that we're down so that the reset task will no longer run */
14438c2ecf20Sopenharmony_ci	set_bit(__E1000_DOWN, &adapter->flags);
14448c2ecf20Sopenharmony_ci	clear_bit(__E1000_RESETTING, &adapter->flags);
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci	e1000_down(adapter);
14478c2ecf20Sopenharmony_ci	e1000_power_down_phy(adapter);
14488c2ecf20Sopenharmony_ci	e1000_free_irq(adapter);
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	e1000_free_all_tx_resources(adapter);
14518c2ecf20Sopenharmony_ci	e1000_free_all_rx_resources(adapter);
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	/* kill manageability vlan ID if supported, but not if a vlan with
14548c2ecf20Sopenharmony_ci	 * the same ID is registered on the host OS (let 8021q kill it)
14558c2ecf20Sopenharmony_ci	 */
14568c2ecf20Sopenharmony_ci	if ((hw->mng_cookie.status &
14578c2ecf20Sopenharmony_ci	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
14588c2ecf20Sopenharmony_ci	    !test_bit(adapter->mng_vlan_id, adapter->active_vlans)) {
14598c2ecf20Sopenharmony_ci		e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q),
14608c2ecf20Sopenharmony_ci				       adapter->mng_vlan_id);
14618c2ecf20Sopenharmony_ci	}
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci	return 0;
14648c2ecf20Sopenharmony_ci}
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci/**
14678c2ecf20Sopenharmony_ci * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary
14688c2ecf20Sopenharmony_ci * @adapter: address of board private structure
14698c2ecf20Sopenharmony_ci * @start: address of beginning of memory
14708c2ecf20Sopenharmony_ci * @len: length of memory
14718c2ecf20Sopenharmony_ci **/
14728c2ecf20Sopenharmony_cistatic bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start,
14738c2ecf20Sopenharmony_ci				  unsigned long len)
14748c2ecf20Sopenharmony_ci{
14758c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
14768c2ecf20Sopenharmony_ci	unsigned long begin = (unsigned long)start;
14778c2ecf20Sopenharmony_ci	unsigned long end = begin + len;
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	/* First rev 82545 and 82546 need to not allow any memory
14808c2ecf20Sopenharmony_ci	 * write location to cross 64k boundary due to errata 23
14818c2ecf20Sopenharmony_ci	 */
14828c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82545 ||
14838c2ecf20Sopenharmony_ci	    hw->mac_type == e1000_ce4100 ||
14848c2ecf20Sopenharmony_ci	    hw->mac_type == e1000_82546) {
14858c2ecf20Sopenharmony_ci		return ((begin ^ (end - 1)) >> 16) == 0;
14868c2ecf20Sopenharmony_ci	}
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	return true;
14898c2ecf20Sopenharmony_ci}
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci/**
14928c2ecf20Sopenharmony_ci * e1000_setup_tx_resources - allocate Tx resources (Descriptors)
14938c2ecf20Sopenharmony_ci * @adapter: board private structure
14948c2ecf20Sopenharmony_ci * @txdr:    tx descriptor ring (for a specific queue) to setup
14958c2ecf20Sopenharmony_ci *
14968c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure
14978c2ecf20Sopenharmony_ci **/
14988c2ecf20Sopenharmony_cistatic int e1000_setup_tx_resources(struct e1000_adapter *adapter,
14998c2ecf20Sopenharmony_ci				    struct e1000_tx_ring *txdr)
15008c2ecf20Sopenharmony_ci{
15018c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
15028c2ecf20Sopenharmony_ci	int size;
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	size = sizeof(struct e1000_tx_buffer) * txdr->count;
15058c2ecf20Sopenharmony_ci	txdr->buffer_info = vzalloc(size);
15068c2ecf20Sopenharmony_ci	if (!txdr->buffer_info)
15078c2ecf20Sopenharmony_ci		return -ENOMEM;
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	/* round up to nearest 4K */
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
15128c2ecf20Sopenharmony_ci	txdr->size = ALIGN(txdr->size, 4096);
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
15158c2ecf20Sopenharmony_ci					GFP_KERNEL);
15168c2ecf20Sopenharmony_ci	if (!txdr->desc) {
15178c2ecf20Sopenharmony_cisetup_tx_desc_die:
15188c2ecf20Sopenharmony_ci		vfree(txdr->buffer_info);
15198c2ecf20Sopenharmony_ci		return -ENOMEM;
15208c2ecf20Sopenharmony_ci	}
15218c2ecf20Sopenharmony_ci
15228c2ecf20Sopenharmony_ci	/* Fix for errata 23, can't cross 64kB boundary */
15238c2ecf20Sopenharmony_ci	if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
15248c2ecf20Sopenharmony_ci		void *olddesc = txdr->desc;
15258c2ecf20Sopenharmony_ci		dma_addr_t olddma = txdr->dma;
15268c2ecf20Sopenharmony_ci		e_err(tx_err, "txdr align check failed: %u bytes at %p\n",
15278c2ecf20Sopenharmony_ci		      txdr->size, txdr->desc);
15288c2ecf20Sopenharmony_ci		/* Try again, without freeing the previous */
15298c2ecf20Sopenharmony_ci		txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size,
15308c2ecf20Sopenharmony_ci						&txdr->dma, GFP_KERNEL);
15318c2ecf20Sopenharmony_ci		/* Failed allocation, critical failure */
15328c2ecf20Sopenharmony_ci		if (!txdr->desc) {
15338c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
15348c2ecf20Sopenharmony_ci					  olddma);
15358c2ecf20Sopenharmony_ci			goto setup_tx_desc_die;
15368c2ecf20Sopenharmony_ci		}
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci		if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
15398c2ecf20Sopenharmony_ci			/* give up */
15408c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, txdr->size, txdr->desc,
15418c2ecf20Sopenharmony_ci					  txdr->dma);
15428c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
15438c2ecf20Sopenharmony_ci					  olddma);
15448c2ecf20Sopenharmony_ci			e_err(probe, "Unable to allocate aligned memory "
15458c2ecf20Sopenharmony_ci			      "for the transmit descriptor ring\n");
15468c2ecf20Sopenharmony_ci			vfree(txdr->buffer_info);
15478c2ecf20Sopenharmony_ci			return -ENOMEM;
15488c2ecf20Sopenharmony_ci		} else {
15498c2ecf20Sopenharmony_ci			/* Free old allocation, new allocation was successful */
15508c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
15518c2ecf20Sopenharmony_ci					  olddma);
15528c2ecf20Sopenharmony_ci		}
15538c2ecf20Sopenharmony_ci	}
15548c2ecf20Sopenharmony_ci	memset(txdr->desc, 0, txdr->size);
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	txdr->next_to_use = 0;
15578c2ecf20Sopenharmony_ci	txdr->next_to_clean = 0;
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci	return 0;
15608c2ecf20Sopenharmony_ci}
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci/**
15638c2ecf20Sopenharmony_ci * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
15648c2ecf20Sopenharmony_ci * 				  (Descriptors) for all queues
15658c2ecf20Sopenharmony_ci * @adapter: board private structure
15668c2ecf20Sopenharmony_ci *
15678c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure
15688c2ecf20Sopenharmony_ci **/
15698c2ecf20Sopenharmony_ciint e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
15708c2ecf20Sopenharmony_ci{
15718c2ecf20Sopenharmony_ci	int i, err = 0;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	for (i = 0; i < adapter->num_tx_queues; i++) {
15748c2ecf20Sopenharmony_ci		err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
15758c2ecf20Sopenharmony_ci		if (err) {
15768c2ecf20Sopenharmony_ci			e_err(probe, "Allocation for Tx Queue %u failed\n", i);
15778c2ecf20Sopenharmony_ci			for (i-- ; i >= 0; i--)
15788c2ecf20Sopenharmony_ci				e1000_free_tx_resources(adapter,
15798c2ecf20Sopenharmony_ci							&adapter->tx_ring[i]);
15808c2ecf20Sopenharmony_ci			break;
15818c2ecf20Sopenharmony_ci		}
15828c2ecf20Sopenharmony_ci	}
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci	return err;
15858c2ecf20Sopenharmony_ci}
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci/**
15888c2ecf20Sopenharmony_ci * e1000_configure_tx - Configure 8254x Transmit Unit after Reset
15898c2ecf20Sopenharmony_ci * @adapter: board private structure
15908c2ecf20Sopenharmony_ci *
15918c2ecf20Sopenharmony_ci * Configure the Tx unit of the MAC after a reset.
15928c2ecf20Sopenharmony_ci **/
15938c2ecf20Sopenharmony_cistatic void e1000_configure_tx(struct e1000_adapter *adapter)
15948c2ecf20Sopenharmony_ci{
15958c2ecf20Sopenharmony_ci	u64 tdba;
15968c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
15978c2ecf20Sopenharmony_ci	u32 tdlen, tctl, tipg;
15988c2ecf20Sopenharmony_ci	u32 ipgr1, ipgr2;
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci	/* Setup the HW Tx Head and Tail descriptor pointers */
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci	switch (adapter->num_tx_queues) {
16038c2ecf20Sopenharmony_ci	case 1:
16048c2ecf20Sopenharmony_ci	default:
16058c2ecf20Sopenharmony_ci		tdba = adapter->tx_ring[0].dma;
16068c2ecf20Sopenharmony_ci		tdlen = adapter->tx_ring[0].count *
16078c2ecf20Sopenharmony_ci			sizeof(struct e1000_tx_desc);
16088c2ecf20Sopenharmony_ci		ew32(TDLEN, tdlen);
16098c2ecf20Sopenharmony_ci		ew32(TDBAH, (tdba >> 32));
16108c2ecf20Sopenharmony_ci		ew32(TDBAL, (tdba & 0x00000000ffffffffULL));
16118c2ecf20Sopenharmony_ci		ew32(TDT, 0);
16128c2ecf20Sopenharmony_ci		ew32(TDH, 0);
16138c2ecf20Sopenharmony_ci		adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ?
16148c2ecf20Sopenharmony_ci					   E1000_TDH : E1000_82542_TDH);
16158c2ecf20Sopenharmony_ci		adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ?
16168c2ecf20Sopenharmony_ci					   E1000_TDT : E1000_82542_TDT);
16178c2ecf20Sopenharmony_ci		break;
16188c2ecf20Sopenharmony_ci	}
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_ci	/* Set the default values for the Tx Inter Packet Gap timer */
16218c2ecf20Sopenharmony_ci	if ((hw->media_type == e1000_media_type_fiber ||
16228c2ecf20Sopenharmony_ci	     hw->media_type == e1000_media_type_internal_serdes))
16238c2ecf20Sopenharmony_ci		tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
16248c2ecf20Sopenharmony_ci	else
16258c2ecf20Sopenharmony_ci		tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
16288c2ecf20Sopenharmony_ci	case e1000_82542_rev2_0:
16298c2ecf20Sopenharmony_ci	case e1000_82542_rev2_1:
16308c2ecf20Sopenharmony_ci		tipg = DEFAULT_82542_TIPG_IPGT;
16318c2ecf20Sopenharmony_ci		ipgr1 = DEFAULT_82542_TIPG_IPGR1;
16328c2ecf20Sopenharmony_ci		ipgr2 = DEFAULT_82542_TIPG_IPGR2;
16338c2ecf20Sopenharmony_ci		break;
16348c2ecf20Sopenharmony_ci	default:
16358c2ecf20Sopenharmony_ci		ipgr1 = DEFAULT_82543_TIPG_IPGR1;
16368c2ecf20Sopenharmony_ci		ipgr2 = DEFAULT_82543_TIPG_IPGR2;
16378c2ecf20Sopenharmony_ci		break;
16388c2ecf20Sopenharmony_ci	}
16398c2ecf20Sopenharmony_ci	tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
16408c2ecf20Sopenharmony_ci	tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
16418c2ecf20Sopenharmony_ci	ew32(TIPG, tipg);
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci	/* Set the Tx Interrupt Delay register */
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci	ew32(TIDV, adapter->tx_int_delay);
16468c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82540)
16478c2ecf20Sopenharmony_ci		ew32(TADV, adapter->tx_abs_int_delay);
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	/* Program the Transmit Control Register */
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	tctl = er32(TCTL);
16528c2ecf20Sopenharmony_ci	tctl &= ~E1000_TCTL_CT;
16538c2ecf20Sopenharmony_ci	tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
16548c2ecf20Sopenharmony_ci		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	e1000_config_collision_dist(hw);
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	/* Setup Transmit Descriptor Settings for eop descriptor */
16598c2ecf20Sopenharmony_ci	adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS;
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	/* only set IDE if we are delaying interrupts using the timers */
16628c2ecf20Sopenharmony_ci	if (adapter->tx_int_delay)
16638c2ecf20Sopenharmony_ci		adapter->txd_cmd |= E1000_TXD_CMD_IDE;
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	if (hw->mac_type < e1000_82543)
16668c2ecf20Sopenharmony_ci		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
16678c2ecf20Sopenharmony_ci	else
16688c2ecf20Sopenharmony_ci		adapter->txd_cmd |= E1000_TXD_CMD_RS;
16698c2ecf20Sopenharmony_ci
16708c2ecf20Sopenharmony_ci	/* Cache if we're 82544 running in PCI-X because we'll
16718c2ecf20Sopenharmony_ci	 * need this to apply a workaround later in the send path.
16728c2ecf20Sopenharmony_ci	 */
16738c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82544 &&
16748c2ecf20Sopenharmony_ci	    hw->bus_type == e1000_bus_type_pcix)
16758c2ecf20Sopenharmony_ci		adapter->pcix_82544 = true;
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci	ew32(TCTL, tctl);
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci}
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci/**
16828c2ecf20Sopenharmony_ci * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
16838c2ecf20Sopenharmony_ci * @adapter: board private structure
16848c2ecf20Sopenharmony_ci * @rxdr:    rx descriptor ring (for a specific queue) to setup
16858c2ecf20Sopenharmony_ci *
16868c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
16878c2ecf20Sopenharmony_ci **/
16888c2ecf20Sopenharmony_cistatic int e1000_setup_rx_resources(struct e1000_adapter *adapter,
16898c2ecf20Sopenharmony_ci				    struct e1000_rx_ring *rxdr)
16908c2ecf20Sopenharmony_ci{
16918c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
16928c2ecf20Sopenharmony_ci	int size, desc_len;
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	size = sizeof(struct e1000_rx_buffer) * rxdr->count;
16958c2ecf20Sopenharmony_ci	rxdr->buffer_info = vzalloc(size);
16968c2ecf20Sopenharmony_ci	if (!rxdr->buffer_info)
16978c2ecf20Sopenharmony_ci		return -ENOMEM;
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	desc_len = sizeof(struct e1000_rx_desc);
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci	/* Round up to nearest 4K */
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci	rxdr->size = rxdr->count * desc_len;
17048c2ecf20Sopenharmony_ci	rxdr->size = ALIGN(rxdr->size, 4096);
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
17078c2ecf20Sopenharmony_ci					GFP_KERNEL);
17088c2ecf20Sopenharmony_ci	if (!rxdr->desc) {
17098c2ecf20Sopenharmony_cisetup_rx_desc_die:
17108c2ecf20Sopenharmony_ci		vfree(rxdr->buffer_info);
17118c2ecf20Sopenharmony_ci		return -ENOMEM;
17128c2ecf20Sopenharmony_ci	}
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci	/* Fix for errata 23, can't cross 64kB boundary */
17158c2ecf20Sopenharmony_ci	if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
17168c2ecf20Sopenharmony_ci		void *olddesc = rxdr->desc;
17178c2ecf20Sopenharmony_ci		dma_addr_t olddma = rxdr->dma;
17188c2ecf20Sopenharmony_ci		e_err(rx_err, "rxdr align check failed: %u bytes at %p\n",
17198c2ecf20Sopenharmony_ci		      rxdr->size, rxdr->desc);
17208c2ecf20Sopenharmony_ci		/* Try again, without freeing the previous */
17218c2ecf20Sopenharmony_ci		rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size,
17228c2ecf20Sopenharmony_ci						&rxdr->dma, GFP_KERNEL);
17238c2ecf20Sopenharmony_ci		/* Failed allocation, critical failure */
17248c2ecf20Sopenharmony_ci		if (!rxdr->desc) {
17258c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
17268c2ecf20Sopenharmony_ci					  olddma);
17278c2ecf20Sopenharmony_ci			goto setup_rx_desc_die;
17288c2ecf20Sopenharmony_ci		}
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci		if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
17318c2ecf20Sopenharmony_ci			/* give up */
17328c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc,
17338c2ecf20Sopenharmony_ci					  rxdr->dma);
17348c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
17358c2ecf20Sopenharmony_ci					  olddma);
17368c2ecf20Sopenharmony_ci			e_err(probe, "Unable to allocate aligned memory for "
17378c2ecf20Sopenharmony_ci			      "the Rx descriptor ring\n");
17388c2ecf20Sopenharmony_ci			goto setup_rx_desc_die;
17398c2ecf20Sopenharmony_ci		} else {
17408c2ecf20Sopenharmony_ci			/* Free old allocation, new allocation was successful */
17418c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
17428c2ecf20Sopenharmony_ci					  olddma);
17438c2ecf20Sopenharmony_ci		}
17448c2ecf20Sopenharmony_ci	}
17458c2ecf20Sopenharmony_ci	memset(rxdr->desc, 0, rxdr->size);
17468c2ecf20Sopenharmony_ci
17478c2ecf20Sopenharmony_ci	rxdr->next_to_clean = 0;
17488c2ecf20Sopenharmony_ci	rxdr->next_to_use = 0;
17498c2ecf20Sopenharmony_ci	rxdr->rx_skb_top = NULL;
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci	return 0;
17528c2ecf20Sopenharmony_ci}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci/**
17558c2ecf20Sopenharmony_ci * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
17568c2ecf20Sopenharmony_ci * 				  (Descriptors) for all queues
17578c2ecf20Sopenharmony_ci * @adapter: board private structure
17588c2ecf20Sopenharmony_ci *
17598c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure
17608c2ecf20Sopenharmony_ci **/
17618c2ecf20Sopenharmony_ciint e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
17628c2ecf20Sopenharmony_ci{
17638c2ecf20Sopenharmony_ci	int i, err = 0;
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	for (i = 0; i < adapter->num_rx_queues; i++) {
17668c2ecf20Sopenharmony_ci		err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
17678c2ecf20Sopenharmony_ci		if (err) {
17688c2ecf20Sopenharmony_ci			e_err(probe, "Allocation for Rx Queue %u failed\n", i);
17698c2ecf20Sopenharmony_ci			for (i-- ; i >= 0; i--)
17708c2ecf20Sopenharmony_ci				e1000_free_rx_resources(adapter,
17718c2ecf20Sopenharmony_ci							&adapter->rx_ring[i]);
17728c2ecf20Sopenharmony_ci			break;
17738c2ecf20Sopenharmony_ci		}
17748c2ecf20Sopenharmony_ci	}
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci	return err;
17778c2ecf20Sopenharmony_ci}
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci/**
17808c2ecf20Sopenharmony_ci * e1000_setup_rctl - configure the receive control registers
17818c2ecf20Sopenharmony_ci * @adapter: Board private structure
17828c2ecf20Sopenharmony_ci **/
17838c2ecf20Sopenharmony_cistatic void e1000_setup_rctl(struct e1000_adapter *adapter)
17848c2ecf20Sopenharmony_ci{
17858c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
17868c2ecf20Sopenharmony_ci	u32 rctl;
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	rctl = er32(RCTL);
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
17918c2ecf20Sopenharmony_ci
17928c2ecf20Sopenharmony_ci	rctl |= E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
17938c2ecf20Sopenharmony_ci		E1000_RCTL_RDMTS_HALF |
17948c2ecf20Sopenharmony_ci		(hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci	if (hw->tbi_compatibility_on == 1)
17978c2ecf20Sopenharmony_ci		rctl |= E1000_RCTL_SBP;
17988c2ecf20Sopenharmony_ci	else
17998c2ecf20Sopenharmony_ci		rctl &= ~E1000_RCTL_SBP;
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	if (adapter->netdev->mtu <= ETH_DATA_LEN)
18028c2ecf20Sopenharmony_ci		rctl &= ~E1000_RCTL_LPE;
18038c2ecf20Sopenharmony_ci	else
18048c2ecf20Sopenharmony_ci		rctl |= E1000_RCTL_LPE;
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci	/* Setup buffer sizes */
18078c2ecf20Sopenharmony_ci	rctl &= ~E1000_RCTL_SZ_4096;
18088c2ecf20Sopenharmony_ci	rctl |= E1000_RCTL_BSEX;
18098c2ecf20Sopenharmony_ci	switch (adapter->rx_buffer_len) {
18108c2ecf20Sopenharmony_ci	case E1000_RXBUFFER_2048:
18118c2ecf20Sopenharmony_ci	default:
18128c2ecf20Sopenharmony_ci		rctl |= E1000_RCTL_SZ_2048;
18138c2ecf20Sopenharmony_ci		rctl &= ~E1000_RCTL_BSEX;
18148c2ecf20Sopenharmony_ci		break;
18158c2ecf20Sopenharmony_ci	case E1000_RXBUFFER_4096:
18168c2ecf20Sopenharmony_ci		rctl |= E1000_RCTL_SZ_4096;
18178c2ecf20Sopenharmony_ci		break;
18188c2ecf20Sopenharmony_ci	case E1000_RXBUFFER_8192:
18198c2ecf20Sopenharmony_ci		rctl |= E1000_RCTL_SZ_8192;
18208c2ecf20Sopenharmony_ci		break;
18218c2ecf20Sopenharmony_ci	case E1000_RXBUFFER_16384:
18228c2ecf20Sopenharmony_ci		rctl |= E1000_RCTL_SZ_16384;
18238c2ecf20Sopenharmony_ci		break;
18248c2ecf20Sopenharmony_ci	}
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	/* This is useful for sniffing bad packets. */
18278c2ecf20Sopenharmony_ci	if (adapter->netdev->features & NETIF_F_RXALL) {
18288c2ecf20Sopenharmony_ci		/* UPE and MPE will be handled by normal PROMISC logic
18298c2ecf20Sopenharmony_ci		 * in e1000e_set_rx_mode
18308c2ecf20Sopenharmony_ci		 */
18318c2ecf20Sopenharmony_ci		rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
18328c2ecf20Sopenharmony_ci			 E1000_RCTL_BAM | /* RX All Bcast Pkts */
18338c2ecf20Sopenharmony_ci			 E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci		rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */
18368c2ecf20Sopenharmony_ci			  E1000_RCTL_DPF | /* Allow filtered pause */
18378c2ecf20Sopenharmony_ci			  E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */
18388c2ecf20Sopenharmony_ci		/* Do not mess with E1000_CTRL_VME, it affects transmit as well,
18398c2ecf20Sopenharmony_ci		 * and that breaks VLANs.
18408c2ecf20Sopenharmony_ci		 */
18418c2ecf20Sopenharmony_ci	}
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci	ew32(RCTL, rctl);
18448c2ecf20Sopenharmony_ci}
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci/**
18478c2ecf20Sopenharmony_ci * e1000_configure_rx - Configure 8254x Receive Unit after Reset
18488c2ecf20Sopenharmony_ci * @adapter: board private structure
18498c2ecf20Sopenharmony_ci *
18508c2ecf20Sopenharmony_ci * Configure the Rx unit of the MAC after a reset.
18518c2ecf20Sopenharmony_ci **/
18528c2ecf20Sopenharmony_cistatic void e1000_configure_rx(struct e1000_adapter *adapter)
18538c2ecf20Sopenharmony_ci{
18548c2ecf20Sopenharmony_ci	u64 rdba;
18558c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
18568c2ecf20Sopenharmony_ci	u32 rdlen, rctl, rxcsum;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	if (adapter->netdev->mtu > ETH_DATA_LEN) {
18598c2ecf20Sopenharmony_ci		rdlen = adapter->rx_ring[0].count *
18608c2ecf20Sopenharmony_ci			sizeof(struct e1000_rx_desc);
18618c2ecf20Sopenharmony_ci		adapter->clean_rx = e1000_clean_jumbo_rx_irq;
18628c2ecf20Sopenharmony_ci		adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers;
18638c2ecf20Sopenharmony_ci	} else {
18648c2ecf20Sopenharmony_ci		rdlen = adapter->rx_ring[0].count *
18658c2ecf20Sopenharmony_ci			sizeof(struct e1000_rx_desc);
18668c2ecf20Sopenharmony_ci		adapter->clean_rx = e1000_clean_rx_irq;
18678c2ecf20Sopenharmony_ci		adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
18688c2ecf20Sopenharmony_ci	}
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ci	/* disable receives while setting up the descriptors */
18718c2ecf20Sopenharmony_ci	rctl = er32(RCTL);
18728c2ecf20Sopenharmony_ci	ew32(RCTL, rctl & ~E1000_RCTL_EN);
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	/* set the Receive Delay Timer Register */
18758c2ecf20Sopenharmony_ci	ew32(RDTR, adapter->rx_int_delay);
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82540) {
18788c2ecf20Sopenharmony_ci		ew32(RADV, adapter->rx_abs_int_delay);
18798c2ecf20Sopenharmony_ci		if (adapter->itr_setting != 0)
18808c2ecf20Sopenharmony_ci			ew32(ITR, 1000000000 / (adapter->itr * 256));
18818c2ecf20Sopenharmony_ci	}
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	/* Setup the HW Rx Head and Tail Descriptor Pointers and
18848c2ecf20Sopenharmony_ci	 * the Base and Length of the Rx Descriptor Ring
18858c2ecf20Sopenharmony_ci	 */
18868c2ecf20Sopenharmony_ci	switch (adapter->num_rx_queues) {
18878c2ecf20Sopenharmony_ci	case 1:
18888c2ecf20Sopenharmony_ci	default:
18898c2ecf20Sopenharmony_ci		rdba = adapter->rx_ring[0].dma;
18908c2ecf20Sopenharmony_ci		ew32(RDLEN, rdlen);
18918c2ecf20Sopenharmony_ci		ew32(RDBAH, (rdba >> 32));
18928c2ecf20Sopenharmony_ci		ew32(RDBAL, (rdba & 0x00000000ffffffffULL));
18938c2ecf20Sopenharmony_ci		ew32(RDT, 0);
18948c2ecf20Sopenharmony_ci		ew32(RDH, 0);
18958c2ecf20Sopenharmony_ci		adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ?
18968c2ecf20Sopenharmony_ci					   E1000_RDH : E1000_82542_RDH);
18978c2ecf20Sopenharmony_ci		adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ?
18988c2ecf20Sopenharmony_ci					   E1000_RDT : E1000_82542_RDT);
18998c2ecf20Sopenharmony_ci		break;
19008c2ecf20Sopenharmony_ci	}
19018c2ecf20Sopenharmony_ci
19028c2ecf20Sopenharmony_ci	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
19038c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82543) {
19048c2ecf20Sopenharmony_ci		rxcsum = er32(RXCSUM);
19058c2ecf20Sopenharmony_ci		if (adapter->rx_csum)
19068c2ecf20Sopenharmony_ci			rxcsum |= E1000_RXCSUM_TUOFL;
19078c2ecf20Sopenharmony_ci		else
19088c2ecf20Sopenharmony_ci			/* don't need to clear IPPCSE as it defaults to 0 */
19098c2ecf20Sopenharmony_ci			rxcsum &= ~E1000_RXCSUM_TUOFL;
19108c2ecf20Sopenharmony_ci		ew32(RXCSUM, rxcsum);
19118c2ecf20Sopenharmony_ci	}
19128c2ecf20Sopenharmony_ci
19138c2ecf20Sopenharmony_ci	/* Enable Receives */
19148c2ecf20Sopenharmony_ci	ew32(RCTL, rctl | E1000_RCTL_EN);
19158c2ecf20Sopenharmony_ci}
19168c2ecf20Sopenharmony_ci
19178c2ecf20Sopenharmony_ci/**
19188c2ecf20Sopenharmony_ci * e1000_free_tx_resources - Free Tx Resources per Queue
19198c2ecf20Sopenharmony_ci * @adapter: board private structure
19208c2ecf20Sopenharmony_ci * @tx_ring: Tx descriptor ring for a specific queue
19218c2ecf20Sopenharmony_ci *
19228c2ecf20Sopenharmony_ci * Free all transmit software resources
19238c2ecf20Sopenharmony_ci **/
19248c2ecf20Sopenharmony_cistatic void e1000_free_tx_resources(struct e1000_adapter *adapter,
19258c2ecf20Sopenharmony_ci				    struct e1000_tx_ring *tx_ring)
19268c2ecf20Sopenharmony_ci{
19278c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
19288c2ecf20Sopenharmony_ci
19298c2ecf20Sopenharmony_ci	e1000_clean_tx_ring(adapter, tx_ring);
19308c2ecf20Sopenharmony_ci
19318c2ecf20Sopenharmony_ci	vfree(tx_ring->buffer_info);
19328c2ecf20Sopenharmony_ci	tx_ring->buffer_info = NULL;
19338c2ecf20Sopenharmony_ci
19348c2ecf20Sopenharmony_ci	dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
19358c2ecf20Sopenharmony_ci			  tx_ring->dma);
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_ci	tx_ring->desc = NULL;
19388c2ecf20Sopenharmony_ci}
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci/**
19418c2ecf20Sopenharmony_ci * e1000_free_all_tx_resources - Free Tx Resources for All Queues
19428c2ecf20Sopenharmony_ci * @adapter: board private structure
19438c2ecf20Sopenharmony_ci *
19448c2ecf20Sopenharmony_ci * Free all transmit software resources
19458c2ecf20Sopenharmony_ci **/
19468c2ecf20Sopenharmony_civoid e1000_free_all_tx_resources(struct e1000_adapter *adapter)
19478c2ecf20Sopenharmony_ci{
19488c2ecf20Sopenharmony_ci	int i;
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	for (i = 0; i < adapter->num_tx_queues; i++)
19518c2ecf20Sopenharmony_ci		e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
19528c2ecf20Sopenharmony_ci}
19538c2ecf20Sopenharmony_ci
19548c2ecf20Sopenharmony_cistatic void
19558c2ecf20Sopenharmony_cie1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
19568c2ecf20Sopenharmony_ci				 struct e1000_tx_buffer *buffer_info)
19578c2ecf20Sopenharmony_ci{
19588c2ecf20Sopenharmony_ci	if (buffer_info->dma) {
19598c2ecf20Sopenharmony_ci		if (buffer_info->mapped_as_page)
19608c2ecf20Sopenharmony_ci			dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
19618c2ecf20Sopenharmony_ci				       buffer_info->length, DMA_TO_DEVICE);
19628c2ecf20Sopenharmony_ci		else
19638c2ecf20Sopenharmony_ci			dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
19648c2ecf20Sopenharmony_ci					 buffer_info->length,
19658c2ecf20Sopenharmony_ci					 DMA_TO_DEVICE);
19668c2ecf20Sopenharmony_ci		buffer_info->dma = 0;
19678c2ecf20Sopenharmony_ci	}
19688c2ecf20Sopenharmony_ci	if (buffer_info->skb) {
19698c2ecf20Sopenharmony_ci		dev_kfree_skb_any(buffer_info->skb);
19708c2ecf20Sopenharmony_ci		buffer_info->skb = NULL;
19718c2ecf20Sopenharmony_ci	}
19728c2ecf20Sopenharmony_ci	buffer_info->time_stamp = 0;
19738c2ecf20Sopenharmony_ci	/* buffer_info must be completely set up in the transmit path */
19748c2ecf20Sopenharmony_ci}
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci/**
19778c2ecf20Sopenharmony_ci * e1000_clean_tx_ring - Free Tx Buffers
19788c2ecf20Sopenharmony_ci * @adapter: board private structure
19798c2ecf20Sopenharmony_ci * @tx_ring: ring to be cleaned
19808c2ecf20Sopenharmony_ci **/
19818c2ecf20Sopenharmony_cistatic void e1000_clean_tx_ring(struct e1000_adapter *adapter,
19828c2ecf20Sopenharmony_ci				struct e1000_tx_ring *tx_ring)
19838c2ecf20Sopenharmony_ci{
19848c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
19858c2ecf20Sopenharmony_ci	struct e1000_tx_buffer *buffer_info;
19868c2ecf20Sopenharmony_ci	unsigned long size;
19878c2ecf20Sopenharmony_ci	unsigned int i;
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	/* Free all the Tx ring sk_buffs */
19908c2ecf20Sopenharmony_ci
19918c2ecf20Sopenharmony_ci	for (i = 0; i < tx_ring->count; i++) {
19928c2ecf20Sopenharmony_ci		buffer_info = &tx_ring->buffer_info[i];
19938c2ecf20Sopenharmony_ci		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
19948c2ecf20Sopenharmony_ci	}
19958c2ecf20Sopenharmony_ci
19968c2ecf20Sopenharmony_ci	netdev_reset_queue(adapter->netdev);
19978c2ecf20Sopenharmony_ci	size = sizeof(struct e1000_tx_buffer) * tx_ring->count;
19988c2ecf20Sopenharmony_ci	memset(tx_ring->buffer_info, 0, size);
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci	/* Zero out the descriptor ring */
20018c2ecf20Sopenharmony_ci
20028c2ecf20Sopenharmony_ci	memset(tx_ring->desc, 0, tx_ring->size);
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci	tx_ring->next_to_use = 0;
20058c2ecf20Sopenharmony_ci	tx_ring->next_to_clean = 0;
20068c2ecf20Sopenharmony_ci	tx_ring->last_tx_tso = false;
20078c2ecf20Sopenharmony_ci
20088c2ecf20Sopenharmony_ci	writel(0, hw->hw_addr + tx_ring->tdh);
20098c2ecf20Sopenharmony_ci	writel(0, hw->hw_addr + tx_ring->tdt);
20108c2ecf20Sopenharmony_ci}
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci/**
20138c2ecf20Sopenharmony_ci * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
20148c2ecf20Sopenharmony_ci * @adapter: board private structure
20158c2ecf20Sopenharmony_ci **/
20168c2ecf20Sopenharmony_cistatic void e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
20178c2ecf20Sopenharmony_ci{
20188c2ecf20Sopenharmony_ci	int i;
20198c2ecf20Sopenharmony_ci
20208c2ecf20Sopenharmony_ci	for (i = 0; i < adapter->num_tx_queues; i++)
20218c2ecf20Sopenharmony_ci		e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
20228c2ecf20Sopenharmony_ci}
20238c2ecf20Sopenharmony_ci
20248c2ecf20Sopenharmony_ci/**
20258c2ecf20Sopenharmony_ci * e1000_free_rx_resources - Free Rx Resources
20268c2ecf20Sopenharmony_ci * @adapter: board private structure
20278c2ecf20Sopenharmony_ci * @rx_ring: ring to clean the resources from
20288c2ecf20Sopenharmony_ci *
20298c2ecf20Sopenharmony_ci * Free all receive software resources
20308c2ecf20Sopenharmony_ci **/
20318c2ecf20Sopenharmony_cistatic void e1000_free_rx_resources(struct e1000_adapter *adapter,
20328c2ecf20Sopenharmony_ci				    struct e1000_rx_ring *rx_ring)
20338c2ecf20Sopenharmony_ci{
20348c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	e1000_clean_rx_ring(adapter, rx_ring);
20378c2ecf20Sopenharmony_ci
20388c2ecf20Sopenharmony_ci	vfree(rx_ring->buffer_info);
20398c2ecf20Sopenharmony_ci	rx_ring->buffer_info = NULL;
20408c2ecf20Sopenharmony_ci
20418c2ecf20Sopenharmony_ci	dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
20428c2ecf20Sopenharmony_ci			  rx_ring->dma);
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci	rx_ring->desc = NULL;
20458c2ecf20Sopenharmony_ci}
20468c2ecf20Sopenharmony_ci
20478c2ecf20Sopenharmony_ci/**
20488c2ecf20Sopenharmony_ci * e1000_free_all_rx_resources - Free Rx Resources for All Queues
20498c2ecf20Sopenharmony_ci * @adapter: board private structure
20508c2ecf20Sopenharmony_ci *
20518c2ecf20Sopenharmony_ci * Free all receive software resources
20528c2ecf20Sopenharmony_ci **/
20538c2ecf20Sopenharmony_civoid e1000_free_all_rx_resources(struct e1000_adapter *adapter)
20548c2ecf20Sopenharmony_ci{
20558c2ecf20Sopenharmony_ci	int i;
20568c2ecf20Sopenharmony_ci
20578c2ecf20Sopenharmony_ci	for (i = 0; i < adapter->num_rx_queues; i++)
20588c2ecf20Sopenharmony_ci		e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
20598c2ecf20Sopenharmony_ci}
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci#define E1000_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN)
20628c2ecf20Sopenharmony_cistatic unsigned int e1000_frag_len(const struct e1000_adapter *a)
20638c2ecf20Sopenharmony_ci{
20648c2ecf20Sopenharmony_ci	return SKB_DATA_ALIGN(a->rx_buffer_len + E1000_HEADROOM) +
20658c2ecf20Sopenharmony_ci		SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
20668c2ecf20Sopenharmony_ci}
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_cistatic void *e1000_alloc_frag(const struct e1000_adapter *a)
20698c2ecf20Sopenharmony_ci{
20708c2ecf20Sopenharmony_ci	unsigned int len = e1000_frag_len(a);
20718c2ecf20Sopenharmony_ci	u8 *data = netdev_alloc_frag(len);
20728c2ecf20Sopenharmony_ci
20738c2ecf20Sopenharmony_ci	if (likely(data))
20748c2ecf20Sopenharmony_ci		data += E1000_HEADROOM;
20758c2ecf20Sopenharmony_ci	return data;
20768c2ecf20Sopenharmony_ci}
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_ci/**
20798c2ecf20Sopenharmony_ci * e1000_clean_rx_ring - Free Rx Buffers per Queue
20808c2ecf20Sopenharmony_ci * @adapter: board private structure
20818c2ecf20Sopenharmony_ci * @rx_ring: ring to free buffers from
20828c2ecf20Sopenharmony_ci **/
20838c2ecf20Sopenharmony_cistatic void e1000_clean_rx_ring(struct e1000_adapter *adapter,
20848c2ecf20Sopenharmony_ci				struct e1000_rx_ring *rx_ring)
20858c2ecf20Sopenharmony_ci{
20868c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
20878c2ecf20Sopenharmony_ci	struct e1000_rx_buffer *buffer_info;
20888c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
20898c2ecf20Sopenharmony_ci	unsigned long size;
20908c2ecf20Sopenharmony_ci	unsigned int i;
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_ci	/* Free all the Rx netfrags */
20938c2ecf20Sopenharmony_ci	for (i = 0; i < rx_ring->count; i++) {
20948c2ecf20Sopenharmony_ci		buffer_info = &rx_ring->buffer_info[i];
20958c2ecf20Sopenharmony_ci		if (adapter->clean_rx == e1000_clean_rx_irq) {
20968c2ecf20Sopenharmony_ci			if (buffer_info->dma)
20978c2ecf20Sopenharmony_ci				dma_unmap_single(&pdev->dev, buffer_info->dma,
20988c2ecf20Sopenharmony_ci						 adapter->rx_buffer_len,
20998c2ecf20Sopenharmony_ci						 DMA_FROM_DEVICE);
21008c2ecf20Sopenharmony_ci			if (buffer_info->rxbuf.data) {
21018c2ecf20Sopenharmony_ci				skb_free_frag(buffer_info->rxbuf.data);
21028c2ecf20Sopenharmony_ci				buffer_info->rxbuf.data = NULL;
21038c2ecf20Sopenharmony_ci			}
21048c2ecf20Sopenharmony_ci		} else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq) {
21058c2ecf20Sopenharmony_ci			if (buffer_info->dma)
21068c2ecf20Sopenharmony_ci				dma_unmap_page(&pdev->dev, buffer_info->dma,
21078c2ecf20Sopenharmony_ci					       adapter->rx_buffer_len,
21088c2ecf20Sopenharmony_ci					       DMA_FROM_DEVICE);
21098c2ecf20Sopenharmony_ci			if (buffer_info->rxbuf.page) {
21108c2ecf20Sopenharmony_ci				put_page(buffer_info->rxbuf.page);
21118c2ecf20Sopenharmony_ci				buffer_info->rxbuf.page = NULL;
21128c2ecf20Sopenharmony_ci			}
21138c2ecf20Sopenharmony_ci		}
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci		buffer_info->dma = 0;
21168c2ecf20Sopenharmony_ci	}
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_ci	/* there also may be some cached data from a chained receive */
21198c2ecf20Sopenharmony_ci	napi_free_frags(&adapter->napi);
21208c2ecf20Sopenharmony_ci	rx_ring->rx_skb_top = NULL;
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_ci	size = sizeof(struct e1000_rx_buffer) * rx_ring->count;
21238c2ecf20Sopenharmony_ci	memset(rx_ring->buffer_info, 0, size);
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_ci	/* Zero out the descriptor ring */
21268c2ecf20Sopenharmony_ci	memset(rx_ring->desc, 0, rx_ring->size);
21278c2ecf20Sopenharmony_ci
21288c2ecf20Sopenharmony_ci	rx_ring->next_to_clean = 0;
21298c2ecf20Sopenharmony_ci	rx_ring->next_to_use = 0;
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci	writel(0, hw->hw_addr + rx_ring->rdh);
21328c2ecf20Sopenharmony_ci	writel(0, hw->hw_addr + rx_ring->rdt);
21338c2ecf20Sopenharmony_ci}
21348c2ecf20Sopenharmony_ci
21358c2ecf20Sopenharmony_ci/**
21368c2ecf20Sopenharmony_ci * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
21378c2ecf20Sopenharmony_ci * @adapter: board private structure
21388c2ecf20Sopenharmony_ci **/
21398c2ecf20Sopenharmony_cistatic void e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
21408c2ecf20Sopenharmony_ci{
21418c2ecf20Sopenharmony_ci	int i;
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci	for (i = 0; i < adapter->num_rx_queues; i++)
21448c2ecf20Sopenharmony_ci		e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
21458c2ecf20Sopenharmony_ci}
21468c2ecf20Sopenharmony_ci
21478c2ecf20Sopenharmony_ci/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
21488c2ecf20Sopenharmony_ci * and memory write and invalidate disabled for certain operations
21498c2ecf20Sopenharmony_ci */
21508c2ecf20Sopenharmony_cistatic void e1000_enter_82542_rst(struct e1000_adapter *adapter)
21518c2ecf20Sopenharmony_ci{
21528c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
21538c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
21548c2ecf20Sopenharmony_ci	u32 rctl;
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci	e1000_pci_clear_mwi(hw);
21578c2ecf20Sopenharmony_ci
21588c2ecf20Sopenharmony_ci	rctl = er32(RCTL);
21598c2ecf20Sopenharmony_ci	rctl |= E1000_RCTL_RST;
21608c2ecf20Sopenharmony_ci	ew32(RCTL, rctl);
21618c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
21628c2ecf20Sopenharmony_ci	mdelay(5);
21638c2ecf20Sopenharmony_ci
21648c2ecf20Sopenharmony_ci	if (netif_running(netdev))
21658c2ecf20Sopenharmony_ci		e1000_clean_all_rx_rings(adapter);
21668c2ecf20Sopenharmony_ci}
21678c2ecf20Sopenharmony_ci
21688c2ecf20Sopenharmony_cistatic void e1000_leave_82542_rst(struct e1000_adapter *adapter)
21698c2ecf20Sopenharmony_ci{
21708c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
21718c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
21728c2ecf20Sopenharmony_ci	u32 rctl;
21738c2ecf20Sopenharmony_ci
21748c2ecf20Sopenharmony_ci	rctl = er32(RCTL);
21758c2ecf20Sopenharmony_ci	rctl &= ~E1000_RCTL_RST;
21768c2ecf20Sopenharmony_ci	ew32(RCTL, rctl);
21778c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
21788c2ecf20Sopenharmony_ci	mdelay(5);
21798c2ecf20Sopenharmony_ci
21808c2ecf20Sopenharmony_ci	if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
21818c2ecf20Sopenharmony_ci		e1000_pci_set_mwi(hw);
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ci	if (netif_running(netdev)) {
21848c2ecf20Sopenharmony_ci		/* No need to loop, because 82542 supports only 1 queue */
21858c2ecf20Sopenharmony_ci		struct e1000_rx_ring *ring = &adapter->rx_ring[0];
21868c2ecf20Sopenharmony_ci		e1000_configure_rx(adapter);
21878c2ecf20Sopenharmony_ci		adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
21888c2ecf20Sopenharmony_ci	}
21898c2ecf20Sopenharmony_ci}
21908c2ecf20Sopenharmony_ci
21918c2ecf20Sopenharmony_ci/**
21928c2ecf20Sopenharmony_ci * e1000_set_mac - Change the Ethernet Address of the NIC
21938c2ecf20Sopenharmony_ci * @netdev: network interface device structure
21948c2ecf20Sopenharmony_ci * @p: pointer to an address structure
21958c2ecf20Sopenharmony_ci *
21968c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
21978c2ecf20Sopenharmony_ci **/
21988c2ecf20Sopenharmony_cistatic int e1000_set_mac(struct net_device *netdev, void *p)
21998c2ecf20Sopenharmony_ci{
22008c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
22018c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
22028c2ecf20Sopenharmony_ci	struct sockaddr *addr = p;
22038c2ecf20Sopenharmony_ci
22048c2ecf20Sopenharmony_ci	if (!is_valid_ether_addr(addr->sa_data))
22058c2ecf20Sopenharmony_ci		return -EADDRNOTAVAIL;
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci	/* 82542 2.0 needs to be in reset to write receive address registers */
22088c2ecf20Sopenharmony_ci
22098c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0)
22108c2ecf20Sopenharmony_ci		e1000_enter_82542_rst(adapter);
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
22138c2ecf20Sopenharmony_ci	memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len);
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_ci	e1000_rar_set(hw, hw->mac_addr, 0);
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0)
22188c2ecf20Sopenharmony_ci		e1000_leave_82542_rst(adapter);
22198c2ecf20Sopenharmony_ci
22208c2ecf20Sopenharmony_ci	return 0;
22218c2ecf20Sopenharmony_ci}
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_ci/**
22248c2ecf20Sopenharmony_ci * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
22258c2ecf20Sopenharmony_ci * @netdev: network interface device structure
22268c2ecf20Sopenharmony_ci *
22278c2ecf20Sopenharmony_ci * The set_rx_mode entry point is called whenever the unicast or multicast
22288c2ecf20Sopenharmony_ci * address lists or the network interface flags are updated. This routine is
22298c2ecf20Sopenharmony_ci * responsible for configuring the hardware for proper unicast, multicast,
22308c2ecf20Sopenharmony_ci * promiscuous mode, and all-multi behavior.
22318c2ecf20Sopenharmony_ci **/
22328c2ecf20Sopenharmony_cistatic void e1000_set_rx_mode(struct net_device *netdev)
22338c2ecf20Sopenharmony_ci{
22348c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
22358c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
22368c2ecf20Sopenharmony_ci	struct netdev_hw_addr *ha;
22378c2ecf20Sopenharmony_ci	bool use_uc = false;
22388c2ecf20Sopenharmony_ci	u32 rctl;
22398c2ecf20Sopenharmony_ci	u32 hash_value;
22408c2ecf20Sopenharmony_ci	int i, rar_entries = E1000_RAR_ENTRIES;
22418c2ecf20Sopenharmony_ci	int mta_reg_count = E1000_NUM_MTA_REGISTERS;
22428c2ecf20Sopenharmony_ci	u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC);
22438c2ecf20Sopenharmony_ci
22448c2ecf20Sopenharmony_ci	if (!mcarray)
22458c2ecf20Sopenharmony_ci		return;
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_ci	/* Check for Promiscuous and All Multicast modes */
22488c2ecf20Sopenharmony_ci
22498c2ecf20Sopenharmony_ci	rctl = er32(RCTL);
22508c2ecf20Sopenharmony_ci
22518c2ecf20Sopenharmony_ci	if (netdev->flags & IFF_PROMISC) {
22528c2ecf20Sopenharmony_ci		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
22538c2ecf20Sopenharmony_ci		rctl &= ~E1000_RCTL_VFE;
22548c2ecf20Sopenharmony_ci	} else {
22558c2ecf20Sopenharmony_ci		if (netdev->flags & IFF_ALLMULTI)
22568c2ecf20Sopenharmony_ci			rctl |= E1000_RCTL_MPE;
22578c2ecf20Sopenharmony_ci		else
22588c2ecf20Sopenharmony_ci			rctl &= ~E1000_RCTL_MPE;
22598c2ecf20Sopenharmony_ci		/* Enable VLAN filter if there is a VLAN */
22608c2ecf20Sopenharmony_ci		if (e1000_vlan_used(adapter))
22618c2ecf20Sopenharmony_ci			rctl |= E1000_RCTL_VFE;
22628c2ecf20Sopenharmony_ci	}
22638c2ecf20Sopenharmony_ci
22648c2ecf20Sopenharmony_ci	if (netdev_uc_count(netdev) > rar_entries - 1) {
22658c2ecf20Sopenharmony_ci		rctl |= E1000_RCTL_UPE;
22668c2ecf20Sopenharmony_ci	} else if (!(netdev->flags & IFF_PROMISC)) {
22678c2ecf20Sopenharmony_ci		rctl &= ~E1000_RCTL_UPE;
22688c2ecf20Sopenharmony_ci		use_uc = true;
22698c2ecf20Sopenharmony_ci	}
22708c2ecf20Sopenharmony_ci
22718c2ecf20Sopenharmony_ci	ew32(RCTL, rctl);
22728c2ecf20Sopenharmony_ci
22738c2ecf20Sopenharmony_ci	/* 82542 2.0 needs to be in reset to write receive address registers */
22748c2ecf20Sopenharmony_ci
22758c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0)
22768c2ecf20Sopenharmony_ci		e1000_enter_82542_rst(adapter);
22778c2ecf20Sopenharmony_ci
22788c2ecf20Sopenharmony_ci	/* load the first 14 addresses into the exact filters 1-14. Unicast
22798c2ecf20Sopenharmony_ci	 * addresses take precedence to avoid disabling unicast filtering
22808c2ecf20Sopenharmony_ci	 * when possible.
22818c2ecf20Sopenharmony_ci	 *
22828c2ecf20Sopenharmony_ci	 * RAR 0 is used for the station MAC address
22838c2ecf20Sopenharmony_ci	 * if there are not 14 addresses, go ahead and clear the filters
22848c2ecf20Sopenharmony_ci	 */
22858c2ecf20Sopenharmony_ci	i = 1;
22868c2ecf20Sopenharmony_ci	if (use_uc)
22878c2ecf20Sopenharmony_ci		netdev_for_each_uc_addr(ha, netdev) {
22888c2ecf20Sopenharmony_ci			if (i == rar_entries)
22898c2ecf20Sopenharmony_ci				break;
22908c2ecf20Sopenharmony_ci			e1000_rar_set(hw, ha->addr, i++);
22918c2ecf20Sopenharmony_ci		}
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_ci	netdev_for_each_mc_addr(ha, netdev) {
22948c2ecf20Sopenharmony_ci		if (i == rar_entries) {
22958c2ecf20Sopenharmony_ci			/* load any remaining addresses into the hash table */
22968c2ecf20Sopenharmony_ci			u32 hash_reg, hash_bit, mta;
22978c2ecf20Sopenharmony_ci			hash_value = e1000_hash_mc_addr(hw, ha->addr);
22988c2ecf20Sopenharmony_ci			hash_reg = (hash_value >> 5) & 0x7F;
22998c2ecf20Sopenharmony_ci			hash_bit = hash_value & 0x1F;
23008c2ecf20Sopenharmony_ci			mta = (1 << hash_bit);
23018c2ecf20Sopenharmony_ci			mcarray[hash_reg] |= mta;
23028c2ecf20Sopenharmony_ci		} else {
23038c2ecf20Sopenharmony_ci			e1000_rar_set(hw, ha->addr, i++);
23048c2ecf20Sopenharmony_ci		}
23058c2ecf20Sopenharmony_ci	}
23068c2ecf20Sopenharmony_ci
23078c2ecf20Sopenharmony_ci	for (; i < rar_entries; i++) {
23088c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
23098c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
23108c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
23118c2ecf20Sopenharmony_ci		E1000_WRITE_FLUSH();
23128c2ecf20Sopenharmony_ci	}
23138c2ecf20Sopenharmony_ci
23148c2ecf20Sopenharmony_ci	/* write the hash table completely, write from bottom to avoid
23158c2ecf20Sopenharmony_ci	 * both stupid write combining chipsets, and flushing each write
23168c2ecf20Sopenharmony_ci	 */
23178c2ecf20Sopenharmony_ci	for (i = mta_reg_count - 1; i >= 0 ; i--) {
23188c2ecf20Sopenharmony_ci		/* If we are on an 82544 has an errata where writing odd
23198c2ecf20Sopenharmony_ci		 * offsets overwrites the previous even offset, but writing
23208c2ecf20Sopenharmony_ci		 * backwards over the range solves the issue by always
23218c2ecf20Sopenharmony_ci		 * writing the odd offset first
23228c2ecf20Sopenharmony_ci		 */
23238c2ecf20Sopenharmony_ci		E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]);
23248c2ecf20Sopenharmony_ci	}
23258c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci	if (hw->mac_type == e1000_82542_rev2_0)
23288c2ecf20Sopenharmony_ci		e1000_leave_82542_rst(adapter);
23298c2ecf20Sopenharmony_ci
23308c2ecf20Sopenharmony_ci	kfree(mcarray);
23318c2ecf20Sopenharmony_ci}
23328c2ecf20Sopenharmony_ci
23338c2ecf20Sopenharmony_ci/**
23348c2ecf20Sopenharmony_ci * e1000_update_phy_info_task - get phy info
23358c2ecf20Sopenharmony_ci * @work: work struct contained inside adapter struct
23368c2ecf20Sopenharmony_ci *
23378c2ecf20Sopenharmony_ci * Need to wait a few seconds after link up to get diagnostic information from
23388c2ecf20Sopenharmony_ci * the phy
23398c2ecf20Sopenharmony_ci */
23408c2ecf20Sopenharmony_cistatic void e1000_update_phy_info_task(struct work_struct *work)
23418c2ecf20Sopenharmony_ci{
23428c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = container_of(work,
23438c2ecf20Sopenharmony_ci						     struct e1000_adapter,
23448c2ecf20Sopenharmony_ci						     phy_info_task.work);
23458c2ecf20Sopenharmony_ci
23468c2ecf20Sopenharmony_ci	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
23478c2ecf20Sopenharmony_ci}
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci/**
23508c2ecf20Sopenharmony_ci * e1000_82547_tx_fifo_stall_task - task to complete work
23518c2ecf20Sopenharmony_ci * @work: work struct contained inside adapter struct
23528c2ecf20Sopenharmony_ci **/
23538c2ecf20Sopenharmony_cistatic void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
23548c2ecf20Sopenharmony_ci{
23558c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = container_of(work,
23568c2ecf20Sopenharmony_ci						     struct e1000_adapter,
23578c2ecf20Sopenharmony_ci						     fifo_stall_task.work);
23588c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
23598c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
23608c2ecf20Sopenharmony_ci	u32 tctl;
23618c2ecf20Sopenharmony_ci
23628c2ecf20Sopenharmony_ci	if (atomic_read(&adapter->tx_fifo_stall)) {
23638c2ecf20Sopenharmony_ci		if ((er32(TDT) == er32(TDH)) &&
23648c2ecf20Sopenharmony_ci		   (er32(TDFT) == er32(TDFH)) &&
23658c2ecf20Sopenharmony_ci		   (er32(TDFTS) == er32(TDFHS))) {
23668c2ecf20Sopenharmony_ci			tctl = er32(TCTL);
23678c2ecf20Sopenharmony_ci			ew32(TCTL, tctl & ~E1000_TCTL_EN);
23688c2ecf20Sopenharmony_ci			ew32(TDFT, adapter->tx_head_addr);
23698c2ecf20Sopenharmony_ci			ew32(TDFH, adapter->tx_head_addr);
23708c2ecf20Sopenharmony_ci			ew32(TDFTS, adapter->tx_head_addr);
23718c2ecf20Sopenharmony_ci			ew32(TDFHS, adapter->tx_head_addr);
23728c2ecf20Sopenharmony_ci			ew32(TCTL, tctl);
23738c2ecf20Sopenharmony_ci			E1000_WRITE_FLUSH();
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci			adapter->tx_fifo_head = 0;
23768c2ecf20Sopenharmony_ci			atomic_set(&adapter->tx_fifo_stall, 0);
23778c2ecf20Sopenharmony_ci			netif_wake_queue(netdev);
23788c2ecf20Sopenharmony_ci		} else if (!test_bit(__E1000_DOWN, &adapter->flags)) {
23798c2ecf20Sopenharmony_ci			schedule_delayed_work(&adapter->fifo_stall_task, 1);
23808c2ecf20Sopenharmony_ci		}
23818c2ecf20Sopenharmony_ci	}
23828c2ecf20Sopenharmony_ci}
23838c2ecf20Sopenharmony_ci
23848c2ecf20Sopenharmony_cibool e1000_has_link(struct e1000_adapter *adapter)
23858c2ecf20Sopenharmony_ci{
23868c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
23878c2ecf20Sopenharmony_ci	bool link_active = false;
23888c2ecf20Sopenharmony_ci
23898c2ecf20Sopenharmony_ci	/* get_link_status is set on LSC (link status) interrupt or rx
23908c2ecf20Sopenharmony_ci	 * sequence error interrupt (except on intel ce4100).
23918c2ecf20Sopenharmony_ci	 * get_link_status will stay false until the
23928c2ecf20Sopenharmony_ci	 * e1000_check_for_link establishes link for copper adapters
23938c2ecf20Sopenharmony_ci	 * ONLY
23948c2ecf20Sopenharmony_ci	 */
23958c2ecf20Sopenharmony_ci	switch (hw->media_type) {
23968c2ecf20Sopenharmony_ci	case e1000_media_type_copper:
23978c2ecf20Sopenharmony_ci		if (hw->mac_type == e1000_ce4100)
23988c2ecf20Sopenharmony_ci			hw->get_link_status = 1;
23998c2ecf20Sopenharmony_ci		if (hw->get_link_status) {
24008c2ecf20Sopenharmony_ci			e1000_check_for_link(hw);
24018c2ecf20Sopenharmony_ci			link_active = !hw->get_link_status;
24028c2ecf20Sopenharmony_ci		} else {
24038c2ecf20Sopenharmony_ci			link_active = true;
24048c2ecf20Sopenharmony_ci		}
24058c2ecf20Sopenharmony_ci		break;
24068c2ecf20Sopenharmony_ci	case e1000_media_type_fiber:
24078c2ecf20Sopenharmony_ci		e1000_check_for_link(hw);
24088c2ecf20Sopenharmony_ci		link_active = !!(er32(STATUS) & E1000_STATUS_LU);
24098c2ecf20Sopenharmony_ci		break;
24108c2ecf20Sopenharmony_ci	case e1000_media_type_internal_serdes:
24118c2ecf20Sopenharmony_ci		e1000_check_for_link(hw);
24128c2ecf20Sopenharmony_ci		link_active = hw->serdes_has_link;
24138c2ecf20Sopenharmony_ci		break;
24148c2ecf20Sopenharmony_ci	default:
24158c2ecf20Sopenharmony_ci		break;
24168c2ecf20Sopenharmony_ci	}
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_ci	return link_active;
24198c2ecf20Sopenharmony_ci}
24208c2ecf20Sopenharmony_ci
24218c2ecf20Sopenharmony_ci/**
24228c2ecf20Sopenharmony_ci * e1000_watchdog - work function
24238c2ecf20Sopenharmony_ci * @work: work struct contained inside adapter struct
24248c2ecf20Sopenharmony_ci **/
24258c2ecf20Sopenharmony_cistatic void e1000_watchdog(struct work_struct *work)
24268c2ecf20Sopenharmony_ci{
24278c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = container_of(work,
24288c2ecf20Sopenharmony_ci						     struct e1000_adapter,
24298c2ecf20Sopenharmony_ci						     watchdog_task.work);
24308c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
24318c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
24328c2ecf20Sopenharmony_ci	struct e1000_tx_ring *txdr = adapter->tx_ring;
24338c2ecf20Sopenharmony_ci	u32 link, tctl;
24348c2ecf20Sopenharmony_ci
24358c2ecf20Sopenharmony_ci	link = e1000_has_link(adapter);
24368c2ecf20Sopenharmony_ci	if ((netif_carrier_ok(netdev)) && link)
24378c2ecf20Sopenharmony_ci		goto link_up;
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ci	if (link) {
24408c2ecf20Sopenharmony_ci		if (!netif_carrier_ok(netdev)) {
24418c2ecf20Sopenharmony_ci			u32 ctrl;
24428c2ecf20Sopenharmony_ci			/* update snapshot of PHY registers on LSC */
24438c2ecf20Sopenharmony_ci			e1000_get_speed_and_duplex(hw,
24448c2ecf20Sopenharmony_ci						   &adapter->link_speed,
24458c2ecf20Sopenharmony_ci						   &adapter->link_duplex);
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci			ctrl = er32(CTRL);
24488c2ecf20Sopenharmony_ci			pr_info("%s NIC Link is Up %d Mbps %s, "
24498c2ecf20Sopenharmony_ci				"Flow Control: %s\n",
24508c2ecf20Sopenharmony_ci				netdev->name,
24518c2ecf20Sopenharmony_ci				adapter->link_speed,
24528c2ecf20Sopenharmony_ci				adapter->link_duplex == FULL_DUPLEX ?
24538c2ecf20Sopenharmony_ci				"Full Duplex" : "Half Duplex",
24548c2ecf20Sopenharmony_ci				((ctrl & E1000_CTRL_TFCE) && (ctrl &
24558c2ecf20Sopenharmony_ci				E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl &
24568c2ecf20Sopenharmony_ci				E1000_CTRL_RFCE) ? "RX" : ((ctrl &
24578c2ecf20Sopenharmony_ci				E1000_CTRL_TFCE) ? "TX" : "None")));
24588c2ecf20Sopenharmony_ci
24598c2ecf20Sopenharmony_ci			/* adjust timeout factor according to speed/duplex */
24608c2ecf20Sopenharmony_ci			adapter->tx_timeout_factor = 1;
24618c2ecf20Sopenharmony_ci			switch (adapter->link_speed) {
24628c2ecf20Sopenharmony_ci			case SPEED_10:
24638c2ecf20Sopenharmony_ci				adapter->tx_timeout_factor = 16;
24648c2ecf20Sopenharmony_ci				break;
24658c2ecf20Sopenharmony_ci			case SPEED_100:
24668c2ecf20Sopenharmony_ci				/* maybe add some timeout factor ? */
24678c2ecf20Sopenharmony_ci				break;
24688c2ecf20Sopenharmony_ci			}
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_ci			/* enable transmits in the hardware */
24718c2ecf20Sopenharmony_ci			tctl = er32(TCTL);
24728c2ecf20Sopenharmony_ci			tctl |= E1000_TCTL_EN;
24738c2ecf20Sopenharmony_ci			ew32(TCTL, tctl);
24748c2ecf20Sopenharmony_ci
24758c2ecf20Sopenharmony_ci			netif_carrier_on(netdev);
24768c2ecf20Sopenharmony_ci			if (!test_bit(__E1000_DOWN, &adapter->flags))
24778c2ecf20Sopenharmony_ci				schedule_delayed_work(&adapter->phy_info_task,
24788c2ecf20Sopenharmony_ci						      2 * HZ);
24798c2ecf20Sopenharmony_ci			adapter->smartspeed = 0;
24808c2ecf20Sopenharmony_ci		}
24818c2ecf20Sopenharmony_ci	} else {
24828c2ecf20Sopenharmony_ci		if (netif_carrier_ok(netdev)) {
24838c2ecf20Sopenharmony_ci			adapter->link_speed = 0;
24848c2ecf20Sopenharmony_ci			adapter->link_duplex = 0;
24858c2ecf20Sopenharmony_ci			pr_info("%s NIC Link is Down\n",
24868c2ecf20Sopenharmony_ci				netdev->name);
24878c2ecf20Sopenharmony_ci			netif_carrier_off(netdev);
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_ci			if (!test_bit(__E1000_DOWN, &adapter->flags))
24908c2ecf20Sopenharmony_ci				schedule_delayed_work(&adapter->phy_info_task,
24918c2ecf20Sopenharmony_ci						      2 * HZ);
24928c2ecf20Sopenharmony_ci		}
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci		e1000_smartspeed(adapter);
24958c2ecf20Sopenharmony_ci	}
24968c2ecf20Sopenharmony_ci
24978c2ecf20Sopenharmony_cilink_up:
24988c2ecf20Sopenharmony_ci	e1000_update_stats(adapter);
24998c2ecf20Sopenharmony_ci
25008c2ecf20Sopenharmony_ci	hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
25018c2ecf20Sopenharmony_ci	adapter->tpt_old = adapter->stats.tpt;
25028c2ecf20Sopenharmony_ci	hw->collision_delta = adapter->stats.colc - adapter->colc_old;
25038c2ecf20Sopenharmony_ci	adapter->colc_old = adapter->stats.colc;
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ci	adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
25068c2ecf20Sopenharmony_ci	adapter->gorcl_old = adapter->stats.gorcl;
25078c2ecf20Sopenharmony_ci	adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
25088c2ecf20Sopenharmony_ci	adapter->gotcl_old = adapter->stats.gotcl;
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci	e1000_update_adaptive(hw);
25118c2ecf20Sopenharmony_ci
25128c2ecf20Sopenharmony_ci	if (!netif_carrier_ok(netdev)) {
25138c2ecf20Sopenharmony_ci		if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
25148c2ecf20Sopenharmony_ci			/* We've lost link, so the controller stops DMA,
25158c2ecf20Sopenharmony_ci			 * but we've got queued Tx work that's never going
25168c2ecf20Sopenharmony_ci			 * to get done, so reset controller to flush Tx.
25178c2ecf20Sopenharmony_ci			 * (Do the reset outside of interrupt context).
25188c2ecf20Sopenharmony_ci			 */
25198c2ecf20Sopenharmony_ci			adapter->tx_timeout_count++;
25208c2ecf20Sopenharmony_ci			schedule_work(&adapter->reset_task);
25218c2ecf20Sopenharmony_ci			/* exit immediately since reset is imminent */
25228c2ecf20Sopenharmony_ci			return;
25238c2ecf20Sopenharmony_ci		}
25248c2ecf20Sopenharmony_ci	}
25258c2ecf20Sopenharmony_ci
25268c2ecf20Sopenharmony_ci	/* Simple mode for Interrupt Throttle Rate (ITR) */
25278c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82540 && adapter->itr_setting == 4) {
25288c2ecf20Sopenharmony_ci		/* Symmetric Tx/Rx gets a reduced ITR=2000;
25298c2ecf20Sopenharmony_ci		 * Total asymmetrical Tx or Rx gets ITR=8000;
25308c2ecf20Sopenharmony_ci		 * everyone else is between 2000-8000.
25318c2ecf20Sopenharmony_ci		 */
25328c2ecf20Sopenharmony_ci		u32 goc = (adapter->gotcl + adapter->gorcl) / 10000;
25338c2ecf20Sopenharmony_ci		u32 dif = (adapter->gotcl > adapter->gorcl ?
25348c2ecf20Sopenharmony_ci			    adapter->gotcl - adapter->gorcl :
25358c2ecf20Sopenharmony_ci			    adapter->gorcl - adapter->gotcl) / 10000;
25368c2ecf20Sopenharmony_ci		u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
25378c2ecf20Sopenharmony_ci
25388c2ecf20Sopenharmony_ci		ew32(ITR, 1000000000 / (itr * 256));
25398c2ecf20Sopenharmony_ci	}
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci	/* Cause software interrupt to ensure rx ring is cleaned */
25428c2ecf20Sopenharmony_ci	ew32(ICS, E1000_ICS_RXDMT0);
25438c2ecf20Sopenharmony_ci
25448c2ecf20Sopenharmony_ci	/* Force detection of hung controller every watchdog period */
25458c2ecf20Sopenharmony_ci	adapter->detect_tx_hung = true;
25468c2ecf20Sopenharmony_ci
25478c2ecf20Sopenharmony_ci	/* Reschedule the task */
25488c2ecf20Sopenharmony_ci	if (!test_bit(__E1000_DOWN, &adapter->flags))
25498c2ecf20Sopenharmony_ci		schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
25508c2ecf20Sopenharmony_ci}
25518c2ecf20Sopenharmony_ci
25528c2ecf20Sopenharmony_cienum latency_range {
25538c2ecf20Sopenharmony_ci	lowest_latency = 0,
25548c2ecf20Sopenharmony_ci	low_latency = 1,
25558c2ecf20Sopenharmony_ci	bulk_latency = 2,
25568c2ecf20Sopenharmony_ci	latency_invalid = 255
25578c2ecf20Sopenharmony_ci};
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci/**
25608c2ecf20Sopenharmony_ci * e1000_update_itr - update the dynamic ITR value based on statistics
25618c2ecf20Sopenharmony_ci * @adapter: pointer to adapter
25628c2ecf20Sopenharmony_ci * @itr_setting: current adapter->itr
25638c2ecf20Sopenharmony_ci * @packets: the number of packets during this measurement interval
25648c2ecf20Sopenharmony_ci * @bytes: the number of bytes during this measurement interval
25658c2ecf20Sopenharmony_ci *
25668c2ecf20Sopenharmony_ci *      Stores a new ITR value based on packets and byte
25678c2ecf20Sopenharmony_ci *      counts during the last interrupt.  The advantage of per interrupt
25688c2ecf20Sopenharmony_ci *      computation is faster updates and more accurate ITR for the current
25698c2ecf20Sopenharmony_ci *      traffic pattern.  Constants in this function were computed
25708c2ecf20Sopenharmony_ci *      based on theoretical maximum wire speed and thresholds were set based
25718c2ecf20Sopenharmony_ci *      on testing data as well as attempting to minimize response time
25728c2ecf20Sopenharmony_ci *      while increasing bulk throughput.
25738c2ecf20Sopenharmony_ci *      this functionality is controlled by the InterruptThrottleRate module
25748c2ecf20Sopenharmony_ci *      parameter (see e1000_param.c)
25758c2ecf20Sopenharmony_ci **/
25768c2ecf20Sopenharmony_cistatic unsigned int e1000_update_itr(struct e1000_adapter *adapter,
25778c2ecf20Sopenharmony_ci				     u16 itr_setting, int packets, int bytes)
25788c2ecf20Sopenharmony_ci{
25798c2ecf20Sopenharmony_ci	unsigned int retval = itr_setting;
25808c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
25818c2ecf20Sopenharmony_ci
25828c2ecf20Sopenharmony_ci	if (unlikely(hw->mac_type < e1000_82540))
25838c2ecf20Sopenharmony_ci		goto update_itr_done;
25848c2ecf20Sopenharmony_ci
25858c2ecf20Sopenharmony_ci	if (packets == 0)
25868c2ecf20Sopenharmony_ci		goto update_itr_done;
25878c2ecf20Sopenharmony_ci
25888c2ecf20Sopenharmony_ci	switch (itr_setting) {
25898c2ecf20Sopenharmony_ci	case lowest_latency:
25908c2ecf20Sopenharmony_ci		/* jumbo frames get bulk treatment*/
25918c2ecf20Sopenharmony_ci		if (bytes/packets > 8000)
25928c2ecf20Sopenharmony_ci			retval = bulk_latency;
25938c2ecf20Sopenharmony_ci		else if ((packets < 5) && (bytes > 512))
25948c2ecf20Sopenharmony_ci			retval = low_latency;
25958c2ecf20Sopenharmony_ci		break;
25968c2ecf20Sopenharmony_ci	case low_latency:  /* 50 usec aka 20000 ints/s */
25978c2ecf20Sopenharmony_ci		if (bytes > 10000) {
25988c2ecf20Sopenharmony_ci			/* jumbo frames need bulk latency setting */
25998c2ecf20Sopenharmony_ci			if (bytes/packets > 8000)
26008c2ecf20Sopenharmony_ci				retval = bulk_latency;
26018c2ecf20Sopenharmony_ci			else if ((packets < 10) || ((bytes/packets) > 1200))
26028c2ecf20Sopenharmony_ci				retval = bulk_latency;
26038c2ecf20Sopenharmony_ci			else if ((packets > 35))
26048c2ecf20Sopenharmony_ci				retval = lowest_latency;
26058c2ecf20Sopenharmony_ci		} else if (bytes/packets > 2000)
26068c2ecf20Sopenharmony_ci			retval = bulk_latency;
26078c2ecf20Sopenharmony_ci		else if (packets <= 2 && bytes < 512)
26088c2ecf20Sopenharmony_ci			retval = lowest_latency;
26098c2ecf20Sopenharmony_ci		break;
26108c2ecf20Sopenharmony_ci	case bulk_latency: /* 250 usec aka 4000 ints/s */
26118c2ecf20Sopenharmony_ci		if (bytes > 25000) {
26128c2ecf20Sopenharmony_ci			if (packets > 35)
26138c2ecf20Sopenharmony_ci				retval = low_latency;
26148c2ecf20Sopenharmony_ci		} else if (bytes < 6000) {
26158c2ecf20Sopenharmony_ci			retval = low_latency;
26168c2ecf20Sopenharmony_ci		}
26178c2ecf20Sopenharmony_ci		break;
26188c2ecf20Sopenharmony_ci	}
26198c2ecf20Sopenharmony_ci
26208c2ecf20Sopenharmony_ciupdate_itr_done:
26218c2ecf20Sopenharmony_ci	return retval;
26228c2ecf20Sopenharmony_ci}
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_cistatic void e1000_set_itr(struct e1000_adapter *adapter)
26258c2ecf20Sopenharmony_ci{
26268c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
26278c2ecf20Sopenharmony_ci	u16 current_itr;
26288c2ecf20Sopenharmony_ci	u32 new_itr = adapter->itr;
26298c2ecf20Sopenharmony_ci
26308c2ecf20Sopenharmony_ci	if (unlikely(hw->mac_type < e1000_82540))
26318c2ecf20Sopenharmony_ci		return;
26328c2ecf20Sopenharmony_ci
26338c2ecf20Sopenharmony_ci	/* for non-gigabit speeds, just fix the interrupt rate at 4000 */
26348c2ecf20Sopenharmony_ci	if (unlikely(adapter->link_speed != SPEED_1000)) {
26358c2ecf20Sopenharmony_ci		current_itr = 0;
26368c2ecf20Sopenharmony_ci		new_itr = 4000;
26378c2ecf20Sopenharmony_ci		goto set_itr_now;
26388c2ecf20Sopenharmony_ci	}
26398c2ecf20Sopenharmony_ci
26408c2ecf20Sopenharmony_ci	adapter->tx_itr = e1000_update_itr(adapter, adapter->tx_itr,
26418c2ecf20Sopenharmony_ci					   adapter->total_tx_packets,
26428c2ecf20Sopenharmony_ci					   adapter->total_tx_bytes);
26438c2ecf20Sopenharmony_ci	/* conservative mode (itr 3) eliminates the lowest_latency setting */
26448c2ecf20Sopenharmony_ci	if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency)
26458c2ecf20Sopenharmony_ci		adapter->tx_itr = low_latency;
26468c2ecf20Sopenharmony_ci
26478c2ecf20Sopenharmony_ci	adapter->rx_itr = e1000_update_itr(adapter, adapter->rx_itr,
26488c2ecf20Sopenharmony_ci					   adapter->total_rx_packets,
26498c2ecf20Sopenharmony_ci					   adapter->total_rx_bytes);
26508c2ecf20Sopenharmony_ci	/* conservative mode (itr 3) eliminates the lowest_latency setting */
26518c2ecf20Sopenharmony_ci	if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency)
26528c2ecf20Sopenharmony_ci		adapter->rx_itr = low_latency;
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_ci	current_itr = max(adapter->rx_itr, adapter->tx_itr);
26558c2ecf20Sopenharmony_ci
26568c2ecf20Sopenharmony_ci	switch (current_itr) {
26578c2ecf20Sopenharmony_ci	/* counts and packets in update_itr are dependent on these numbers */
26588c2ecf20Sopenharmony_ci	case lowest_latency:
26598c2ecf20Sopenharmony_ci		new_itr = 70000;
26608c2ecf20Sopenharmony_ci		break;
26618c2ecf20Sopenharmony_ci	case low_latency:
26628c2ecf20Sopenharmony_ci		new_itr = 20000; /* aka hwitr = ~200 */
26638c2ecf20Sopenharmony_ci		break;
26648c2ecf20Sopenharmony_ci	case bulk_latency:
26658c2ecf20Sopenharmony_ci		new_itr = 4000;
26668c2ecf20Sopenharmony_ci		break;
26678c2ecf20Sopenharmony_ci	default:
26688c2ecf20Sopenharmony_ci		break;
26698c2ecf20Sopenharmony_ci	}
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_ciset_itr_now:
26728c2ecf20Sopenharmony_ci	if (new_itr != adapter->itr) {
26738c2ecf20Sopenharmony_ci		/* this attempts to bias the interrupt rate towards Bulk
26748c2ecf20Sopenharmony_ci		 * by adding intermediate steps when interrupt rate is
26758c2ecf20Sopenharmony_ci		 * increasing
26768c2ecf20Sopenharmony_ci		 */
26778c2ecf20Sopenharmony_ci		new_itr = new_itr > adapter->itr ?
26788c2ecf20Sopenharmony_ci			  min(adapter->itr + (new_itr >> 2), new_itr) :
26798c2ecf20Sopenharmony_ci			  new_itr;
26808c2ecf20Sopenharmony_ci		adapter->itr = new_itr;
26818c2ecf20Sopenharmony_ci		ew32(ITR, 1000000000 / (new_itr * 256));
26828c2ecf20Sopenharmony_ci	}
26838c2ecf20Sopenharmony_ci}
26848c2ecf20Sopenharmony_ci
26858c2ecf20Sopenharmony_ci#define E1000_TX_FLAGS_CSUM		0x00000001
26868c2ecf20Sopenharmony_ci#define E1000_TX_FLAGS_VLAN		0x00000002
26878c2ecf20Sopenharmony_ci#define E1000_TX_FLAGS_TSO		0x00000004
26888c2ecf20Sopenharmony_ci#define E1000_TX_FLAGS_IPV4		0x00000008
26898c2ecf20Sopenharmony_ci#define E1000_TX_FLAGS_NO_FCS		0x00000010
26908c2ecf20Sopenharmony_ci#define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
26918c2ecf20Sopenharmony_ci#define E1000_TX_FLAGS_VLAN_SHIFT	16
26928c2ecf20Sopenharmony_ci
26938c2ecf20Sopenharmony_cistatic int e1000_tso(struct e1000_adapter *adapter,
26948c2ecf20Sopenharmony_ci		     struct e1000_tx_ring *tx_ring, struct sk_buff *skb,
26958c2ecf20Sopenharmony_ci		     __be16 protocol)
26968c2ecf20Sopenharmony_ci{
26978c2ecf20Sopenharmony_ci	struct e1000_context_desc *context_desc;
26988c2ecf20Sopenharmony_ci	struct e1000_tx_buffer *buffer_info;
26998c2ecf20Sopenharmony_ci	unsigned int i;
27008c2ecf20Sopenharmony_ci	u32 cmd_length = 0;
27018c2ecf20Sopenharmony_ci	u16 ipcse = 0, tucse, mss;
27028c2ecf20Sopenharmony_ci	u8 ipcss, ipcso, tucss, tucso, hdr_len;
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_ci	if (skb_is_gso(skb)) {
27058c2ecf20Sopenharmony_ci		int err;
27068c2ecf20Sopenharmony_ci
27078c2ecf20Sopenharmony_ci		err = skb_cow_head(skb, 0);
27088c2ecf20Sopenharmony_ci		if (err < 0)
27098c2ecf20Sopenharmony_ci			return err;
27108c2ecf20Sopenharmony_ci
27118c2ecf20Sopenharmony_ci		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
27128c2ecf20Sopenharmony_ci		mss = skb_shinfo(skb)->gso_size;
27138c2ecf20Sopenharmony_ci		if (protocol == htons(ETH_P_IP)) {
27148c2ecf20Sopenharmony_ci			struct iphdr *iph = ip_hdr(skb);
27158c2ecf20Sopenharmony_ci			iph->tot_len = 0;
27168c2ecf20Sopenharmony_ci			iph->check = 0;
27178c2ecf20Sopenharmony_ci			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
27188c2ecf20Sopenharmony_ci								 iph->daddr, 0,
27198c2ecf20Sopenharmony_ci								 IPPROTO_TCP,
27208c2ecf20Sopenharmony_ci								 0);
27218c2ecf20Sopenharmony_ci			cmd_length = E1000_TXD_CMD_IP;
27228c2ecf20Sopenharmony_ci			ipcse = skb_transport_offset(skb) - 1;
27238c2ecf20Sopenharmony_ci		} else if (skb_is_gso_v6(skb)) {
27248c2ecf20Sopenharmony_ci			tcp_v6_gso_csum_prep(skb);
27258c2ecf20Sopenharmony_ci			ipcse = 0;
27268c2ecf20Sopenharmony_ci		}
27278c2ecf20Sopenharmony_ci		ipcss = skb_network_offset(skb);
27288c2ecf20Sopenharmony_ci		ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data;
27298c2ecf20Sopenharmony_ci		tucss = skb_transport_offset(skb);
27308c2ecf20Sopenharmony_ci		tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
27318c2ecf20Sopenharmony_ci		tucse = 0;
27328c2ecf20Sopenharmony_ci
27338c2ecf20Sopenharmony_ci		cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
27348c2ecf20Sopenharmony_ci			       E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci		i = tx_ring->next_to_use;
27378c2ecf20Sopenharmony_ci		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
27388c2ecf20Sopenharmony_ci		buffer_info = &tx_ring->buffer_info[i];
27398c2ecf20Sopenharmony_ci
27408c2ecf20Sopenharmony_ci		context_desc->lower_setup.ip_fields.ipcss  = ipcss;
27418c2ecf20Sopenharmony_ci		context_desc->lower_setup.ip_fields.ipcso  = ipcso;
27428c2ecf20Sopenharmony_ci		context_desc->lower_setup.ip_fields.ipcse  = cpu_to_le16(ipcse);
27438c2ecf20Sopenharmony_ci		context_desc->upper_setup.tcp_fields.tucss = tucss;
27448c2ecf20Sopenharmony_ci		context_desc->upper_setup.tcp_fields.tucso = tucso;
27458c2ecf20Sopenharmony_ci		context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
27468c2ecf20Sopenharmony_ci		context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
27478c2ecf20Sopenharmony_ci		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
27488c2ecf20Sopenharmony_ci		context_desc->cmd_and_length = cpu_to_le32(cmd_length);
27498c2ecf20Sopenharmony_ci
27508c2ecf20Sopenharmony_ci		buffer_info->time_stamp = jiffies;
27518c2ecf20Sopenharmony_ci		buffer_info->next_to_watch = i;
27528c2ecf20Sopenharmony_ci
27538c2ecf20Sopenharmony_ci		if (++i == tx_ring->count)
27548c2ecf20Sopenharmony_ci			i = 0;
27558c2ecf20Sopenharmony_ci
27568c2ecf20Sopenharmony_ci		tx_ring->next_to_use = i;
27578c2ecf20Sopenharmony_ci
27588c2ecf20Sopenharmony_ci		return true;
27598c2ecf20Sopenharmony_ci	}
27608c2ecf20Sopenharmony_ci	return false;
27618c2ecf20Sopenharmony_ci}
27628c2ecf20Sopenharmony_ci
27638c2ecf20Sopenharmony_cistatic bool e1000_tx_csum(struct e1000_adapter *adapter,
27648c2ecf20Sopenharmony_ci			  struct e1000_tx_ring *tx_ring, struct sk_buff *skb,
27658c2ecf20Sopenharmony_ci			  __be16 protocol)
27668c2ecf20Sopenharmony_ci{
27678c2ecf20Sopenharmony_ci	struct e1000_context_desc *context_desc;
27688c2ecf20Sopenharmony_ci	struct e1000_tx_buffer *buffer_info;
27698c2ecf20Sopenharmony_ci	unsigned int i;
27708c2ecf20Sopenharmony_ci	u8 css;
27718c2ecf20Sopenharmony_ci	u32 cmd_len = E1000_TXD_CMD_DEXT;
27728c2ecf20Sopenharmony_ci
27738c2ecf20Sopenharmony_ci	if (skb->ip_summed != CHECKSUM_PARTIAL)
27748c2ecf20Sopenharmony_ci		return false;
27758c2ecf20Sopenharmony_ci
27768c2ecf20Sopenharmony_ci	switch (protocol) {
27778c2ecf20Sopenharmony_ci	case cpu_to_be16(ETH_P_IP):
27788c2ecf20Sopenharmony_ci		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
27798c2ecf20Sopenharmony_ci			cmd_len |= E1000_TXD_CMD_TCP;
27808c2ecf20Sopenharmony_ci		break;
27818c2ecf20Sopenharmony_ci	case cpu_to_be16(ETH_P_IPV6):
27828c2ecf20Sopenharmony_ci		/* XXX not handling all IPV6 headers */
27838c2ecf20Sopenharmony_ci		if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
27848c2ecf20Sopenharmony_ci			cmd_len |= E1000_TXD_CMD_TCP;
27858c2ecf20Sopenharmony_ci		break;
27868c2ecf20Sopenharmony_ci	default:
27878c2ecf20Sopenharmony_ci		if (unlikely(net_ratelimit()))
27888c2ecf20Sopenharmony_ci			e_warn(drv, "checksum_partial proto=%x!\n",
27898c2ecf20Sopenharmony_ci			       skb->protocol);
27908c2ecf20Sopenharmony_ci		break;
27918c2ecf20Sopenharmony_ci	}
27928c2ecf20Sopenharmony_ci
27938c2ecf20Sopenharmony_ci	css = skb_checksum_start_offset(skb);
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_ci	i = tx_ring->next_to_use;
27968c2ecf20Sopenharmony_ci	buffer_info = &tx_ring->buffer_info[i];
27978c2ecf20Sopenharmony_ci	context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
27988c2ecf20Sopenharmony_ci
27998c2ecf20Sopenharmony_ci	context_desc->lower_setup.ip_config = 0;
28008c2ecf20Sopenharmony_ci	context_desc->upper_setup.tcp_fields.tucss = css;
28018c2ecf20Sopenharmony_ci	context_desc->upper_setup.tcp_fields.tucso =
28028c2ecf20Sopenharmony_ci		css + skb->csum_offset;
28038c2ecf20Sopenharmony_ci	context_desc->upper_setup.tcp_fields.tucse = 0;
28048c2ecf20Sopenharmony_ci	context_desc->tcp_seg_setup.data = 0;
28058c2ecf20Sopenharmony_ci	context_desc->cmd_and_length = cpu_to_le32(cmd_len);
28068c2ecf20Sopenharmony_ci
28078c2ecf20Sopenharmony_ci	buffer_info->time_stamp = jiffies;
28088c2ecf20Sopenharmony_ci	buffer_info->next_to_watch = i;
28098c2ecf20Sopenharmony_ci
28108c2ecf20Sopenharmony_ci	if (unlikely(++i == tx_ring->count))
28118c2ecf20Sopenharmony_ci		i = 0;
28128c2ecf20Sopenharmony_ci
28138c2ecf20Sopenharmony_ci	tx_ring->next_to_use = i;
28148c2ecf20Sopenharmony_ci
28158c2ecf20Sopenharmony_ci	return true;
28168c2ecf20Sopenharmony_ci}
28178c2ecf20Sopenharmony_ci
28188c2ecf20Sopenharmony_ci#define E1000_MAX_TXD_PWR	12
28198c2ecf20Sopenharmony_ci#define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
28208c2ecf20Sopenharmony_ci
28218c2ecf20Sopenharmony_cistatic int e1000_tx_map(struct e1000_adapter *adapter,
28228c2ecf20Sopenharmony_ci			struct e1000_tx_ring *tx_ring,
28238c2ecf20Sopenharmony_ci			struct sk_buff *skb, unsigned int first,
28248c2ecf20Sopenharmony_ci			unsigned int max_per_txd, unsigned int nr_frags,
28258c2ecf20Sopenharmony_ci			unsigned int mss)
28268c2ecf20Sopenharmony_ci{
28278c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
28288c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
28298c2ecf20Sopenharmony_ci	struct e1000_tx_buffer *buffer_info;
28308c2ecf20Sopenharmony_ci	unsigned int len = skb_headlen(skb);
28318c2ecf20Sopenharmony_ci	unsigned int offset = 0, size, count = 0, i;
28328c2ecf20Sopenharmony_ci	unsigned int f, bytecount, segs;
28338c2ecf20Sopenharmony_ci
28348c2ecf20Sopenharmony_ci	i = tx_ring->next_to_use;
28358c2ecf20Sopenharmony_ci
28368c2ecf20Sopenharmony_ci	while (len) {
28378c2ecf20Sopenharmony_ci		buffer_info = &tx_ring->buffer_info[i];
28388c2ecf20Sopenharmony_ci		size = min(len, max_per_txd);
28398c2ecf20Sopenharmony_ci		/* Workaround for Controller erratum --
28408c2ecf20Sopenharmony_ci		 * descriptor for non-tso packet in a linear SKB that follows a
28418c2ecf20Sopenharmony_ci		 * tso gets written back prematurely before the data is fully
28428c2ecf20Sopenharmony_ci		 * DMA'd to the controller
28438c2ecf20Sopenharmony_ci		 */
28448c2ecf20Sopenharmony_ci		if (!skb->data_len && tx_ring->last_tx_tso &&
28458c2ecf20Sopenharmony_ci		    !skb_is_gso(skb)) {
28468c2ecf20Sopenharmony_ci			tx_ring->last_tx_tso = false;
28478c2ecf20Sopenharmony_ci			size -= 4;
28488c2ecf20Sopenharmony_ci		}
28498c2ecf20Sopenharmony_ci
28508c2ecf20Sopenharmony_ci		/* Workaround for premature desc write-backs
28518c2ecf20Sopenharmony_ci		 * in TSO mode.  Append 4-byte sentinel desc
28528c2ecf20Sopenharmony_ci		 */
28538c2ecf20Sopenharmony_ci		if (unlikely(mss && !nr_frags && size == len && size > 8))
28548c2ecf20Sopenharmony_ci			size -= 4;
28558c2ecf20Sopenharmony_ci		/* work-around for errata 10 and it applies
28568c2ecf20Sopenharmony_ci		 * to all controllers in PCI-X mode
28578c2ecf20Sopenharmony_ci		 * The fix is to make sure that the first descriptor of a
28588c2ecf20Sopenharmony_ci		 * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
28598c2ecf20Sopenharmony_ci		 */
28608c2ecf20Sopenharmony_ci		if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
28618c2ecf20Sopenharmony_ci			     (size > 2015) && count == 0))
28628c2ecf20Sopenharmony_ci			size = 2015;
28638c2ecf20Sopenharmony_ci
28648c2ecf20Sopenharmony_ci		/* Workaround for potential 82544 hang in PCI-X.  Avoid
28658c2ecf20Sopenharmony_ci		 * terminating buffers within evenly-aligned dwords.
28668c2ecf20Sopenharmony_ci		 */
28678c2ecf20Sopenharmony_ci		if (unlikely(adapter->pcix_82544 &&
28688c2ecf20Sopenharmony_ci		   !((unsigned long)(skb->data + offset + size - 1) & 4) &&
28698c2ecf20Sopenharmony_ci		   size > 4))
28708c2ecf20Sopenharmony_ci			size -= 4;
28718c2ecf20Sopenharmony_ci
28728c2ecf20Sopenharmony_ci		buffer_info->length = size;
28738c2ecf20Sopenharmony_ci		/* set time_stamp *before* dma to help avoid a possible race */
28748c2ecf20Sopenharmony_ci		buffer_info->time_stamp = jiffies;
28758c2ecf20Sopenharmony_ci		buffer_info->mapped_as_page = false;
28768c2ecf20Sopenharmony_ci		buffer_info->dma = dma_map_single(&pdev->dev,
28778c2ecf20Sopenharmony_ci						  skb->data + offset,
28788c2ecf20Sopenharmony_ci						  size, DMA_TO_DEVICE);
28798c2ecf20Sopenharmony_ci		if (dma_mapping_error(&pdev->dev, buffer_info->dma))
28808c2ecf20Sopenharmony_ci			goto dma_error;
28818c2ecf20Sopenharmony_ci		buffer_info->next_to_watch = i;
28828c2ecf20Sopenharmony_ci
28838c2ecf20Sopenharmony_ci		len -= size;
28848c2ecf20Sopenharmony_ci		offset += size;
28858c2ecf20Sopenharmony_ci		count++;
28868c2ecf20Sopenharmony_ci		if (len) {
28878c2ecf20Sopenharmony_ci			i++;
28888c2ecf20Sopenharmony_ci			if (unlikely(i == tx_ring->count))
28898c2ecf20Sopenharmony_ci				i = 0;
28908c2ecf20Sopenharmony_ci		}
28918c2ecf20Sopenharmony_ci	}
28928c2ecf20Sopenharmony_ci
28938c2ecf20Sopenharmony_ci	for (f = 0; f < nr_frags; f++) {
28948c2ecf20Sopenharmony_ci		const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
28958c2ecf20Sopenharmony_ci
28968c2ecf20Sopenharmony_ci		len = skb_frag_size(frag);
28978c2ecf20Sopenharmony_ci		offset = 0;
28988c2ecf20Sopenharmony_ci
28998c2ecf20Sopenharmony_ci		while (len) {
29008c2ecf20Sopenharmony_ci			unsigned long bufend;
29018c2ecf20Sopenharmony_ci			i++;
29028c2ecf20Sopenharmony_ci			if (unlikely(i == tx_ring->count))
29038c2ecf20Sopenharmony_ci				i = 0;
29048c2ecf20Sopenharmony_ci
29058c2ecf20Sopenharmony_ci			buffer_info = &tx_ring->buffer_info[i];
29068c2ecf20Sopenharmony_ci			size = min(len, max_per_txd);
29078c2ecf20Sopenharmony_ci			/* Workaround for premature desc write-backs
29088c2ecf20Sopenharmony_ci			 * in TSO mode.  Append 4-byte sentinel desc
29098c2ecf20Sopenharmony_ci			 */
29108c2ecf20Sopenharmony_ci			if (unlikely(mss && f == (nr_frags-1) &&
29118c2ecf20Sopenharmony_ci			    size == len && size > 8))
29128c2ecf20Sopenharmony_ci				size -= 4;
29138c2ecf20Sopenharmony_ci			/* Workaround for potential 82544 hang in PCI-X.
29148c2ecf20Sopenharmony_ci			 * Avoid terminating buffers within evenly-aligned
29158c2ecf20Sopenharmony_ci			 * dwords.
29168c2ecf20Sopenharmony_ci			 */
29178c2ecf20Sopenharmony_ci			bufend = (unsigned long)
29188c2ecf20Sopenharmony_ci				page_to_phys(skb_frag_page(frag));
29198c2ecf20Sopenharmony_ci			bufend += offset + size - 1;
29208c2ecf20Sopenharmony_ci			if (unlikely(adapter->pcix_82544 &&
29218c2ecf20Sopenharmony_ci				     !(bufend & 4) &&
29228c2ecf20Sopenharmony_ci				     size > 4))
29238c2ecf20Sopenharmony_ci				size -= 4;
29248c2ecf20Sopenharmony_ci
29258c2ecf20Sopenharmony_ci			buffer_info->length = size;
29268c2ecf20Sopenharmony_ci			buffer_info->time_stamp = jiffies;
29278c2ecf20Sopenharmony_ci			buffer_info->mapped_as_page = true;
29288c2ecf20Sopenharmony_ci			buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag,
29298c2ecf20Sopenharmony_ci						offset, size, DMA_TO_DEVICE);
29308c2ecf20Sopenharmony_ci			if (dma_mapping_error(&pdev->dev, buffer_info->dma))
29318c2ecf20Sopenharmony_ci				goto dma_error;
29328c2ecf20Sopenharmony_ci			buffer_info->next_to_watch = i;
29338c2ecf20Sopenharmony_ci
29348c2ecf20Sopenharmony_ci			len -= size;
29358c2ecf20Sopenharmony_ci			offset += size;
29368c2ecf20Sopenharmony_ci			count++;
29378c2ecf20Sopenharmony_ci		}
29388c2ecf20Sopenharmony_ci	}
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_ci	segs = skb_shinfo(skb)->gso_segs ?: 1;
29418c2ecf20Sopenharmony_ci	/* multiply data chunks by size of headers */
29428c2ecf20Sopenharmony_ci	bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
29438c2ecf20Sopenharmony_ci
29448c2ecf20Sopenharmony_ci	tx_ring->buffer_info[i].skb = skb;
29458c2ecf20Sopenharmony_ci	tx_ring->buffer_info[i].segs = segs;
29468c2ecf20Sopenharmony_ci	tx_ring->buffer_info[i].bytecount = bytecount;
29478c2ecf20Sopenharmony_ci	tx_ring->buffer_info[first].next_to_watch = i;
29488c2ecf20Sopenharmony_ci
29498c2ecf20Sopenharmony_ci	return count;
29508c2ecf20Sopenharmony_ci
29518c2ecf20Sopenharmony_cidma_error:
29528c2ecf20Sopenharmony_ci	dev_err(&pdev->dev, "TX DMA map failed\n");
29538c2ecf20Sopenharmony_ci	buffer_info->dma = 0;
29548c2ecf20Sopenharmony_ci	if (count)
29558c2ecf20Sopenharmony_ci		count--;
29568c2ecf20Sopenharmony_ci
29578c2ecf20Sopenharmony_ci	while (count--) {
29588c2ecf20Sopenharmony_ci		if (i == 0)
29598c2ecf20Sopenharmony_ci			i += tx_ring->count;
29608c2ecf20Sopenharmony_ci		i--;
29618c2ecf20Sopenharmony_ci		buffer_info = &tx_ring->buffer_info[i];
29628c2ecf20Sopenharmony_ci		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
29638c2ecf20Sopenharmony_ci	}
29648c2ecf20Sopenharmony_ci
29658c2ecf20Sopenharmony_ci	return 0;
29668c2ecf20Sopenharmony_ci}
29678c2ecf20Sopenharmony_ci
29688c2ecf20Sopenharmony_cistatic void e1000_tx_queue(struct e1000_adapter *adapter,
29698c2ecf20Sopenharmony_ci			   struct e1000_tx_ring *tx_ring, int tx_flags,
29708c2ecf20Sopenharmony_ci			   int count)
29718c2ecf20Sopenharmony_ci{
29728c2ecf20Sopenharmony_ci	struct e1000_tx_desc *tx_desc = NULL;
29738c2ecf20Sopenharmony_ci	struct e1000_tx_buffer *buffer_info;
29748c2ecf20Sopenharmony_ci	u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
29758c2ecf20Sopenharmony_ci	unsigned int i;
29768c2ecf20Sopenharmony_ci
29778c2ecf20Sopenharmony_ci	if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
29788c2ecf20Sopenharmony_ci		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
29798c2ecf20Sopenharmony_ci			     E1000_TXD_CMD_TSE;
29808c2ecf20Sopenharmony_ci		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
29818c2ecf20Sopenharmony_ci
29828c2ecf20Sopenharmony_ci		if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
29838c2ecf20Sopenharmony_ci			txd_upper |= E1000_TXD_POPTS_IXSM << 8;
29848c2ecf20Sopenharmony_ci	}
29858c2ecf20Sopenharmony_ci
29868c2ecf20Sopenharmony_ci	if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
29878c2ecf20Sopenharmony_ci		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
29888c2ecf20Sopenharmony_ci		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
29898c2ecf20Sopenharmony_ci	}
29908c2ecf20Sopenharmony_ci
29918c2ecf20Sopenharmony_ci	if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
29928c2ecf20Sopenharmony_ci		txd_lower |= E1000_TXD_CMD_VLE;
29938c2ecf20Sopenharmony_ci		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
29948c2ecf20Sopenharmony_ci	}
29958c2ecf20Sopenharmony_ci
29968c2ecf20Sopenharmony_ci	if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS))
29978c2ecf20Sopenharmony_ci		txd_lower &= ~(E1000_TXD_CMD_IFCS);
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_ci	i = tx_ring->next_to_use;
30008c2ecf20Sopenharmony_ci
30018c2ecf20Sopenharmony_ci	while (count--) {
30028c2ecf20Sopenharmony_ci		buffer_info = &tx_ring->buffer_info[i];
30038c2ecf20Sopenharmony_ci		tx_desc = E1000_TX_DESC(*tx_ring, i);
30048c2ecf20Sopenharmony_ci		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
30058c2ecf20Sopenharmony_ci		tx_desc->lower.data =
30068c2ecf20Sopenharmony_ci			cpu_to_le32(txd_lower | buffer_info->length);
30078c2ecf20Sopenharmony_ci		tx_desc->upper.data = cpu_to_le32(txd_upper);
30088c2ecf20Sopenharmony_ci		if (unlikely(++i == tx_ring->count))
30098c2ecf20Sopenharmony_ci			i = 0;
30108c2ecf20Sopenharmony_ci	}
30118c2ecf20Sopenharmony_ci
30128c2ecf20Sopenharmony_ci	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
30138c2ecf20Sopenharmony_ci
30148c2ecf20Sopenharmony_ci	/* txd_cmd re-enables FCS, so we'll re-disable it here as desired. */
30158c2ecf20Sopenharmony_ci	if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS))
30168c2ecf20Sopenharmony_ci		tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS));
30178c2ecf20Sopenharmony_ci
30188c2ecf20Sopenharmony_ci	/* Force memory writes to complete before letting h/w
30198c2ecf20Sopenharmony_ci	 * know there are new descriptors to fetch.  (Only
30208c2ecf20Sopenharmony_ci	 * applicable for weak-ordered memory model archs,
30218c2ecf20Sopenharmony_ci	 * such as IA-64).
30228c2ecf20Sopenharmony_ci	 */
30238c2ecf20Sopenharmony_ci	dma_wmb();
30248c2ecf20Sopenharmony_ci
30258c2ecf20Sopenharmony_ci	tx_ring->next_to_use = i;
30268c2ecf20Sopenharmony_ci}
30278c2ecf20Sopenharmony_ci
30288c2ecf20Sopenharmony_ci/* 82547 workaround to avoid controller hang in half-duplex environment.
30298c2ecf20Sopenharmony_ci * The workaround is to avoid queuing a large packet that would span
30308c2ecf20Sopenharmony_ci * the internal Tx FIFO ring boundary by notifying the stack to resend
30318c2ecf20Sopenharmony_ci * the packet at a later time.  This gives the Tx FIFO an opportunity to
30328c2ecf20Sopenharmony_ci * flush all packets.  When that occurs, we reset the Tx FIFO pointers
30338c2ecf20Sopenharmony_ci * to the beginning of the Tx FIFO.
30348c2ecf20Sopenharmony_ci */
30358c2ecf20Sopenharmony_ci
30368c2ecf20Sopenharmony_ci#define E1000_FIFO_HDR			0x10
30378c2ecf20Sopenharmony_ci#define E1000_82547_PAD_LEN		0x3E0
30388c2ecf20Sopenharmony_ci
30398c2ecf20Sopenharmony_cistatic int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
30408c2ecf20Sopenharmony_ci				       struct sk_buff *skb)
30418c2ecf20Sopenharmony_ci{
30428c2ecf20Sopenharmony_ci	u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
30438c2ecf20Sopenharmony_ci	u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
30448c2ecf20Sopenharmony_ci
30458c2ecf20Sopenharmony_ci	skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR);
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_ci	if (adapter->link_duplex != HALF_DUPLEX)
30488c2ecf20Sopenharmony_ci		goto no_fifo_stall_required;
30498c2ecf20Sopenharmony_ci
30508c2ecf20Sopenharmony_ci	if (atomic_read(&adapter->tx_fifo_stall))
30518c2ecf20Sopenharmony_ci		return 1;
30528c2ecf20Sopenharmony_ci
30538c2ecf20Sopenharmony_ci	if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
30548c2ecf20Sopenharmony_ci		atomic_set(&adapter->tx_fifo_stall, 1);
30558c2ecf20Sopenharmony_ci		return 1;
30568c2ecf20Sopenharmony_ci	}
30578c2ecf20Sopenharmony_ci
30588c2ecf20Sopenharmony_cino_fifo_stall_required:
30598c2ecf20Sopenharmony_ci	adapter->tx_fifo_head += skb_fifo_len;
30608c2ecf20Sopenharmony_ci	if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
30618c2ecf20Sopenharmony_ci		adapter->tx_fifo_head -= adapter->tx_fifo_size;
30628c2ecf20Sopenharmony_ci	return 0;
30638c2ecf20Sopenharmony_ci}
30648c2ecf20Sopenharmony_ci
30658c2ecf20Sopenharmony_cistatic int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
30668c2ecf20Sopenharmony_ci{
30678c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
30688c2ecf20Sopenharmony_ci	struct e1000_tx_ring *tx_ring = adapter->tx_ring;
30698c2ecf20Sopenharmony_ci
30708c2ecf20Sopenharmony_ci	netif_stop_queue(netdev);
30718c2ecf20Sopenharmony_ci	/* Herbert's original patch had:
30728c2ecf20Sopenharmony_ci	 *  smp_mb__after_netif_stop_queue();
30738c2ecf20Sopenharmony_ci	 * but since that doesn't exist yet, just open code it.
30748c2ecf20Sopenharmony_ci	 */
30758c2ecf20Sopenharmony_ci	smp_mb();
30768c2ecf20Sopenharmony_ci
30778c2ecf20Sopenharmony_ci	/* We need to check again in a case another CPU has just
30788c2ecf20Sopenharmony_ci	 * made room available.
30798c2ecf20Sopenharmony_ci	 */
30808c2ecf20Sopenharmony_ci	if (likely(E1000_DESC_UNUSED(tx_ring) < size))
30818c2ecf20Sopenharmony_ci		return -EBUSY;
30828c2ecf20Sopenharmony_ci
30838c2ecf20Sopenharmony_ci	/* A reprieve! */
30848c2ecf20Sopenharmony_ci	netif_start_queue(netdev);
30858c2ecf20Sopenharmony_ci	++adapter->restart_queue;
30868c2ecf20Sopenharmony_ci	return 0;
30878c2ecf20Sopenharmony_ci}
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_cistatic int e1000_maybe_stop_tx(struct net_device *netdev,
30908c2ecf20Sopenharmony_ci			       struct e1000_tx_ring *tx_ring, int size)
30918c2ecf20Sopenharmony_ci{
30928c2ecf20Sopenharmony_ci	if (likely(E1000_DESC_UNUSED(tx_ring) >= size))
30938c2ecf20Sopenharmony_ci		return 0;
30948c2ecf20Sopenharmony_ci	return __e1000_maybe_stop_tx(netdev, size);
30958c2ecf20Sopenharmony_ci}
30968c2ecf20Sopenharmony_ci
30978c2ecf20Sopenharmony_ci#define TXD_USE_COUNT(S, X) (((S) + ((1 << (X)) - 1)) >> (X))
30988c2ecf20Sopenharmony_cistatic netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
30998c2ecf20Sopenharmony_ci				    struct net_device *netdev)
31008c2ecf20Sopenharmony_ci{
31018c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
31028c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
31038c2ecf20Sopenharmony_ci	struct e1000_tx_ring *tx_ring;
31048c2ecf20Sopenharmony_ci	unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
31058c2ecf20Sopenharmony_ci	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
31068c2ecf20Sopenharmony_ci	unsigned int tx_flags = 0;
31078c2ecf20Sopenharmony_ci	unsigned int len = skb_headlen(skb);
31088c2ecf20Sopenharmony_ci	unsigned int nr_frags;
31098c2ecf20Sopenharmony_ci	unsigned int mss;
31108c2ecf20Sopenharmony_ci	int count = 0;
31118c2ecf20Sopenharmony_ci	int tso;
31128c2ecf20Sopenharmony_ci	unsigned int f;
31138c2ecf20Sopenharmony_ci	__be16 protocol = vlan_get_protocol(skb);
31148c2ecf20Sopenharmony_ci
31158c2ecf20Sopenharmony_ci	/* This goes back to the question of how to logically map a Tx queue
31168c2ecf20Sopenharmony_ci	 * to a flow.  Right now, performance is impacted slightly negatively
31178c2ecf20Sopenharmony_ci	 * if using multiple Tx queues.  If the stack breaks away from a
31188c2ecf20Sopenharmony_ci	 * single qdisc implementation, we can look at this again.
31198c2ecf20Sopenharmony_ci	 */
31208c2ecf20Sopenharmony_ci	tx_ring = adapter->tx_ring;
31218c2ecf20Sopenharmony_ci
31228c2ecf20Sopenharmony_ci	/* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
31238c2ecf20Sopenharmony_ci	 * packets may get corrupted during padding by HW.
31248c2ecf20Sopenharmony_ci	 * To WA this issue, pad all small packets manually.
31258c2ecf20Sopenharmony_ci	 */
31268c2ecf20Sopenharmony_ci	if (eth_skb_pad(skb))
31278c2ecf20Sopenharmony_ci		return NETDEV_TX_OK;
31288c2ecf20Sopenharmony_ci
31298c2ecf20Sopenharmony_ci	mss = skb_shinfo(skb)->gso_size;
31308c2ecf20Sopenharmony_ci	/* The controller does a simple calculation to
31318c2ecf20Sopenharmony_ci	 * make sure there is enough room in the FIFO before
31328c2ecf20Sopenharmony_ci	 * initiating the DMA for each buffer.  The calc is:
31338c2ecf20Sopenharmony_ci	 * 4 = ceil(buffer len/mss).  To make sure we don't
31348c2ecf20Sopenharmony_ci	 * overrun the FIFO, adjust the max buffer len if mss
31358c2ecf20Sopenharmony_ci	 * drops.
31368c2ecf20Sopenharmony_ci	 */
31378c2ecf20Sopenharmony_ci	if (mss) {
31388c2ecf20Sopenharmony_ci		u8 hdr_len;
31398c2ecf20Sopenharmony_ci		max_per_txd = min(mss << 2, max_per_txd);
31408c2ecf20Sopenharmony_ci		max_txd_pwr = fls(max_per_txd) - 1;
31418c2ecf20Sopenharmony_ci
31428c2ecf20Sopenharmony_ci		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
31438c2ecf20Sopenharmony_ci		if (skb->data_len && hdr_len == len) {
31448c2ecf20Sopenharmony_ci			switch (hw->mac_type) {
31458c2ecf20Sopenharmony_ci			case e1000_82544: {
31468c2ecf20Sopenharmony_ci				unsigned int pull_size;
31478c2ecf20Sopenharmony_ci
31488c2ecf20Sopenharmony_ci				/* Make sure we have room to chop off 4 bytes,
31498c2ecf20Sopenharmony_ci				 * and that the end alignment will work out to
31508c2ecf20Sopenharmony_ci				 * this hardware's requirements
31518c2ecf20Sopenharmony_ci				 * NOTE: this is a TSO only workaround
31528c2ecf20Sopenharmony_ci				 * if end byte alignment not correct move us
31538c2ecf20Sopenharmony_ci				 * into the next dword
31548c2ecf20Sopenharmony_ci				 */
31558c2ecf20Sopenharmony_ci				if ((unsigned long)(skb_tail_pointer(skb) - 1)
31568c2ecf20Sopenharmony_ci				    & 4)
31578c2ecf20Sopenharmony_ci					break;
31588c2ecf20Sopenharmony_ci				pull_size = min((unsigned int)4, skb->data_len);
31598c2ecf20Sopenharmony_ci				if (!__pskb_pull_tail(skb, pull_size)) {
31608c2ecf20Sopenharmony_ci					e_err(drv, "__pskb_pull_tail "
31618c2ecf20Sopenharmony_ci					      "failed.\n");
31628c2ecf20Sopenharmony_ci					dev_kfree_skb_any(skb);
31638c2ecf20Sopenharmony_ci					return NETDEV_TX_OK;
31648c2ecf20Sopenharmony_ci				}
31658c2ecf20Sopenharmony_ci				len = skb_headlen(skb);
31668c2ecf20Sopenharmony_ci				break;
31678c2ecf20Sopenharmony_ci			}
31688c2ecf20Sopenharmony_ci			default:
31698c2ecf20Sopenharmony_ci				/* do nothing */
31708c2ecf20Sopenharmony_ci				break;
31718c2ecf20Sopenharmony_ci			}
31728c2ecf20Sopenharmony_ci		}
31738c2ecf20Sopenharmony_ci	}
31748c2ecf20Sopenharmony_ci
31758c2ecf20Sopenharmony_ci	/* reserve a descriptor for the offload context */
31768c2ecf20Sopenharmony_ci	if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL))
31778c2ecf20Sopenharmony_ci		count++;
31788c2ecf20Sopenharmony_ci	count++;
31798c2ecf20Sopenharmony_ci
31808c2ecf20Sopenharmony_ci	/* Controller Erratum workaround */
31818c2ecf20Sopenharmony_ci	if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
31828c2ecf20Sopenharmony_ci		count++;
31838c2ecf20Sopenharmony_ci
31848c2ecf20Sopenharmony_ci	count += TXD_USE_COUNT(len, max_txd_pwr);
31858c2ecf20Sopenharmony_ci
31868c2ecf20Sopenharmony_ci	if (adapter->pcix_82544)
31878c2ecf20Sopenharmony_ci		count++;
31888c2ecf20Sopenharmony_ci
31898c2ecf20Sopenharmony_ci	/* work-around for errata 10 and it applies to all controllers
31908c2ecf20Sopenharmony_ci	 * in PCI-X mode, so add one more descriptor to the count
31918c2ecf20Sopenharmony_ci	 */
31928c2ecf20Sopenharmony_ci	if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
31938c2ecf20Sopenharmony_ci			(len > 2015)))
31948c2ecf20Sopenharmony_ci		count++;
31958c2ecf20Sopenharmony_ci
31968c2ecf20Sopenharmony_ci	nr_frags = skb_shinfo(skb)->nr_frags;
31978c2ecf20Sopenharmony_ci	for (f = 0; f < nr_frags; f++)
31988c2ecf20Sopenharmony_ci		count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]),
31998c2ecf20Sopenharmony_ci				       max_txd_pwr);
32008c2ecf20Sopenharmony_ci	if (adapter->pcix_82544)
32018c2ecf20Sopenharmony_ci		count += nr_frags;
32028c2ecf20Sopenharmony_ci
32038c2ecf20Sopenharmony_ci	/* need: count + 2 desc gap to keep tail from touching
32048c2ecf20Sopenharmony_ci	 * head, otherwise try next time
32058c2ecf20Sopenharmony_ci	 */
32068c2ecf20Sopenharmony_ci	if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2)))
32078c2ecf20Sopenharmony_ci		return NETDEV_TX_BUSY;
32088c2ecf20Sopenharmony_ci
32098c2ecf20Sopenharmony_ci	if (unlikely((hw->mac_type == e1000_82547) &&
32108c2ecf20Sopenharmony_ci		     (e1000_82547_fifo_workaround(adapter, skb)))) {
32118c2ecf20Sopenharmony_ci		netif_stop_queue(netdev);
32128c2ecf20Sopenharmony_ci		if (!test_bit(__E1000_DOWN, &adapter->flags))
32138c2ecf20Sopenharmony_ci			schedule_delayed_work(&adapter->fifo_stall_task, 1);
32148c2ecf20Sopenharmony_ci		return NETDEV_TX_BUSY;
32158c2ecf20Sopenharmony_ci	}
32168c2ecf20Sopenharmony_ci
32178c2ecf20Sopenharmony_ci	if (skb_vlan_tag_present(skb)) {
32188c2ecf20Sopenharmony_ci		tx_flags |= E1000_TX_FLAGS_VLAN;
32198c2ecf20Sopenharmony_ci		tx_flags |= (skb_vlan_tag_get(skb) <<
32208c2ecf20Sopenharmony_ci			     E1000_TX_FLAGS_VLAN_SHIFT);
32218c2ecf20Sopenharmony_ci	}
32228c2ecf20Sopenharmony_ci
32238c2ecf20Sopenharmony_ci	first = tx_ring->next_to_use;
32248c2ecf20Sopenharmony_ci
32258c2ecf20Sopenharmony_ci	tso = e1000_tso(adapter, tx_ring, skb, protocol);
32268c2ecf20Sopenharmony_ci	if (tso < 0) {
32278c2ecf20Sopenharmony_ci		dev_kfree_skb_any(skb);
32288c2ecf20Sopenharmony_ci		return NETDEV_TX_OK;
32298c2ecf20Sopenharmony_ci	}
32308c2ecf20Sopenharmony_ci
32318c2ecf20Sopenharmony_ci	if (likely(tso)) {
32328c2ecf20Sopenharmony_ci		if (likely(hw->mac_type != e1000_82544))
32338c2ecf20Sopenharmony_ci			tx_ring->last_tx_tso = true;
32348c2ecf20Sopenharmony_ci		tx_flags |= E1000_TX_FLAGS_TSO;
32358c2ecf20Sopenharmony_ci	} else if (likely(e1000_tx_csum(adapter, tx_ring, skb, protocol)))
32368c2ecf20Sopenharmony_ci		tx_flags |= E1000_TX_FLAGS_CSUM;
32378c2ecf20Sopenharmony_ci
32388c2ecf20Sopenharmony_ci	if (protocol == htons(ETH_P_IP))
32398c2ecf20Sopenharmony_ci		tx_flags |= E1000_TX_FLAGS_IPV4;
32408c2ecf20Sopenharmony_ci
32418c2ecf20Sopenharmony_ci	if (unlikely(skb->no_fcs))
32428c2ecf20Sopenharmony_ci		tx_flags |= E1000_TX_FLAGS_NO_FCS;
32438c2ecf20Sopenharmony_ci
32448c2ecf20Sopenharmony_ci	count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd,
32458c2ecf20Sopenharmony_ci			     nr_frags, mss);
32468c2ecf20Sopenharmony_ci
32478c2ecf20Sopenharmony_ci	if (count) {
32488c2ecf20Sopenharmony_ci		/* The descriptors needed is higher than other Intel drivers
32498c2ecf20Sopenharmony_ci		 * due to a number of workarounds.  The breakdown is below:
32508c2ecf20Sopenharmony_ci		 * Data descriptors: MAX_SKB_FRAGS + 1
32518c2ecf20Sopenharmony_ci		 * Context Descriptor: 1
32528c2ecf20Sopenharmony_ci		 * Keep head from touching tail: 2
32538c2ecf20Sopenharmony_ci		 * Workarounds: 3
32548c2ecf20Sopenharmony_ci		 */
32558c2ecf20Sopenharmony_ci		int desc_needed = MAX_SKB_FRAGS + 7;
32568c2ecf20Sopenharmony_ci
32578c2ecf20Sopenharmony_ci		netdev_sent_queue(netdev, skb->len);
32588c2ecf20Sopenharmony_ci		skb_tx_timestamp(skb);
32598c2ecf20Sopenharmony_ci
32608c2ecf20Sopenharmony_ci		e1000_tx_queue(adapter, tx_ring, tx_flags, count);
32618c2ecf20Sopenharmony_ci
32628c2ecf20Sopenharmony_ci		/* 82544 potentially requires twice as many data descriptors
32638c2ecf20Sopenharmony_ci		 * in order to guarantee buffers don't end on evenly-aligned
32648c2ecf20Sopenharmony_ci		 * dwords
32658c2ecf20Sopenharmony_ci		 */
32668c2ecf20Sopenharmony_ci		if (adapter->pcix_82544)
32678c2ecf20Sopenharmony_ci			desc_needed += MAX_SKB_FRAGS + 1;
32688c2ecf20Sopenharmony_ci
32698c2ecf20Sopenharmony_ci		/* Make sure there is space in the ring for the next send. */
32708c2ecf20Sopenharmony_ci		e1000_maybe_stop_tx(netdev, tx_ring, desc_needed);
32718c2ecf20Sopenharmony_ci
32728c2ecf20Sopenharmony_ci		if (!netdev_xmit_more() ||
32738c2ecf20Sopenharmony_ci		    netif_xmit_stopped(netdev_get_tx_queue(netdev, 0))) {
32748c2ecf20Sopenharmony_ci			writel(tx_ring->next_to_use, hw->hw_addr + tx_ring->tdt);
32758c2ecf20Sopenharmony_ci		}
32768c2ecf20Sopenharmony_ci	} else {
32778c2ecf20Sopenharmony_ci		dev_kfree_skb_any(skb);
32788c2ecf20Sopenharmony_ci		tx_ring->buffer_info[first].time_stamp = 0;
32798c2ecf20Sopenharmony_ci		tx_ring->next_to_use = first;
32808c2ecf20Sopenharmony_ci	}
32818c2ecf20Sopenharmony_ci
32828c2ecf20Sopenharmony_ci	return NETDEV_TX_OK;
32838c2ecf20Sopenharmony_ci}
32848c2ecf20Sopenharmony_ci
32858c2ecf20Sopenharmony_ci#define NUM_REGS 38 /* 1 based count */
32868c2ecf20Sopenharmony_cistatic void e1000_regdump(struct e1000_adapter *adapter)
32878c2ecf20Sopenharmony_ci{
32888c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
32898c2ecf20Sopenharmony_ci	u32 regs[NUM_REGS];
32908c2ecf20Sopenharmony_ci	u32 *regs_buff = regs;
32918c2ecf20Sopenharmony_ci	int i = 0;
32928c2ecf20Sopenharmony_ci
32938c2ecf20Sopenharmony_ci	static const char * const reg_name[] = {
32948c2ecf20Sopenharmony_ci		"CTRL",  "STATUS",
32958c2ecf20Sopenharmony_ci		"RCTL", "RDLEN", "RDH", "RDT", "RDTR",
32968c2ecf20Sopenharmony_ci		"TCTL", "TDBAL", "TDBAH", "TDLEN", "TDH", "TDT",
32978c2ecf20Sopenharmony_ci		"TIDV", "TXDCTL", "TADV", "TARC0",
32988c2ecf20Sopenharmony_ci		"TDBAL1", "TDBAH1", "TDLEN1", "TDH1", "TDT1",
32998c2ecf20Sopenharmony_ci		"TXDCTL1", "TARC1",
33008c2ecf20Sopenharmony_ci		"CTRL_EXT", "ERT", "RDBAL", "RDBAH",
33018c2ecf20Sopenharmony_ci		"TDFH", "TDFT", "TDFHS", "TDFTS", "TDFPC",
33028c2ecf20Sopenharmony_ci		"RDFH", "RDFT", "RDFHS", "RDFTS", "RDFPC"
33038c2ecf20Sopenharmony_ci	};
33048c2ecf20Sopenharmony_ci
33058c2ecf20Sopenharmony_ci	regs_buff[0]  = er32(CTRL);
33068c2ecf20Sopenharmony_ci	regs_buff[1]  = er32(STATUS);
33078c2ecf20Sopenharmony_ci
33088c2ecf20Sopenharmony_ci	regs_buff[2]  = er32(RCTL);
33098c2ecf20Sopenharmony_ci	regs_buff[3]  = er32(RDLEN);
33108c2ecf20Sopenharmony_ci	regs_buff[4]  = er32(RDH);
33118c2ecf20Sopenharmony_ci	regs_buff[5]  = er32(RDT);
33128c2ecf20Sopenharmony_ci	regs_buff[6]  = er32(RDTR);
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_ci	regs_buff[7]  = er32(TCTL);
33158c2ecf20Sopenharmony_ci	regs_buff[8]  = er32(TDBAL);
33168c2ecf20Sopenharmony_ci	regs_buff[9]  = er32(TDBAH);
33178c2ecf20Sopenharmony_ci	regs_buff[10] = er32(TDLEN);
33188c2ecf20Sopenharmony_ci	regs_buff[11] = er32(TDH);
33198c2ecf20Sopenharmony_ci	regs_buff[12] = er32(TDT);
33208c2ecf20Sopenharmony_ci	regs_buff[13] = er32(TIDV);
33218c2ecf20Sopenharmony_ci	regs_buff[14] = er32(TXDCTL);
33228c2ecf20Sopenharmony_ci	regs_buff[15] = er32(TADV);
33238c2ecf20Sopenharmony_ci	regs_buff[16] = er32(TARC0);
33248c2ecf20Sopenharmony_ci
33258c2ecf20Sopenharmony_ci	regs_buff[17] = er32(TDBAL1);
33268c2ecf20Sopenharmony_ci	regs_buff[18] = er32(TDBAH1);
33278c2ecf20Sopenharmony_ci	regs_buff[19] = er32(TDLEN1);
33288c2ecf20Sopenharmony_ci	regs_buff[20] = er32(TDH1);
33298c2ecf20Sopenharmony_ci	regs_buff[21] = er32(TDT1);
33308c2ecf20Sopenharmony_ci	regs_buff[22] = er32(TXDCTL1);
33318c2ecf20Sopenharmony_ci	regs_buff[23] = er32(TARC1);
33328c2ecf20Sopenharmony_ci	regs_buff[24] = er32(CTRL_EXT);
33338c2ecf20Sopenharmony_ci	regs_buff[25] = er32(ERT);
33348c2ecf20Sopenharmony_ci	regs_buff[26] = er32(RDBAL0);
33358c2ecf20Sopenharmony_ci	regs_buff[27] = er32(RDBAH0);
33368c2ecf20Sopenharmony_ci	regs_buff[28] = er32(TDFH);
33378c2ecf20Sopenharmony_ci	regs_buff[29] = er32(TDFT);
33388c2ecf20Sopenharmony_ci	regs_buff[30] = er32(TDFHS);
33398c2ecf20Sopenharmony_ci	regs_buff[31] = er32(TDFTS);
33408c2ecf20Sopenharmony_ci	regs_buff[32] = er32(TDFPC);
33418c2ecf20Sopenharmony_ci	regs_buff[33] = er32(RDFH);
33428c2ecf20Sopenharmony_ci	regs_buff[34] = er32(RDFT);
33438c2ecf20Sopenharmony_ci	regs_buff[35] = er32(RDFHS);
33448c2ecf20Sopenharmony_ci	regs_buff[36] = er32(RDFTS);
33458c2ecf20Sopenharmony_ci	regs_buff[37] = er32(RDFPC);
33468c2ecf20Sopenharmony_ci
33478c2ecf20Sopenharmony_ci	pr_info("Register dump\n");
33488c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_REGS; i++)
33498c2ecf20Sopenharmony_ci		pr_info("%-15s  %08x\n", reg_name[i], regs_buff[i]);
33508c2ecf20Sopenharmony_ci}
33518c2ecf20Sopenharmony_ci
33528c2ecf20Sopenharmony_ci/*
33538c2ecf20Sopenharmony_ci * e1000_dump: Print registers, tx ring and rx ring
33548c2ecf20Sopenharmony_ci */
33558c2ecf20Sopenharmony_cistatic void e1000_dump(struct e1000_adapter *adapter)
33568c2ecf20Sopenharmony_ci{
33578c2ecf20Sopenharmony_ci	/* this code doesn't handle multiple rings */
33588c2ecf20Sopenharmony_ci	struct e1000_tx_ring *tx_ring = adapter->tx_ring;
33598c2ecf20Sopenharmony_ci	struct e1000_rx_ring *rx_ring = adapter->rx_ring;
33608c2ecf20Sopenharmony_ci	int i;
33618c2ecf20Sopenharmony_ci
33628c2ecf20Sopenharmony_ci	if (!netif_msg_hw(adapter))
33638c2ecf20Sopenharmony_ci		return;
33648c2ecf20Sopenharmony_ci
33658c2ecf20Sopenharmony_ci	/* Print Registers */
33668c2ecf20Sopenharmony_ci	e1000_regdump(adapter);
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci	/* transmit dump */
33698c2ecf20Sopenharmony_ci	pr_info("TX Desc ring0 dump\n");
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci	/* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
33728c2ecf20Sopenharmony_ci	 *
33738c2ecf20Sopenharmony_ci	 * Legacy Transmit Descriptor
33748c2ecf20Sopenharmony_ci	 *   +--------------------------------------------------------------+
33758c2ecf20Sopenharmony_ci	 * 0 |         Buffer Address [63:0] (Reserved on Write Back)       |
33768c2ecf20Sopenharmony_ci	 *   +--------------------------------------------------------------+
33778c2ecf20Sopenharmony_ci	 * 8 | Special  |    CSS     | Status |  CMD    |  CSO   |  Length  |
33788c2ecf20Sopenharmony_ci	 *   +--------------------------------------------------------------+
33798c2ecf20Sopenharmony_ci	 *   63       48 47        36 35    32 31     24 23    16 15        0
33808c2ecf20Sopenharmony_ci	 *
33818c2ecf20Sopenharmony_ci	 * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
33828c2ecf20Sopenharmony_ci	 *   63      48 47    40 39       32 31             16 15    8 7      0
33838c2ecf20Sopenharmony_ci	 *   +----------------------------------------------------------------+
33848c2ecf20Sopenharmony_ci	 * 0 |  TUCSE  | TUCS0  |   TUCSS   |     IPCSE       | IPCS0 | IPCSS |
33858c2ecf20Sopenharmony_ci	 *   +----------------------------------------------------------------+
33868c2ecf20Sopenharmony_ci	 * 8 |   MSS   | HDRLEN | RSV | STA | TUCMD | DTYP |      PAYLEN      |
33878c2ecf20Sopenharmony_ci	 *   +----------------------------------------------------------------+
33888c2ecf20Sopenharmony_ci	 *   63      48 47    40 39 36 35 32 31   24 23  20 19                0
33898c2ecf20Sopenharmony_ci	 *
33908c2ecf20Sopenharmony_ci	 * Extended Data Descriptor (DTYP=0x1)
33918c2ecf20Sopenharmony_ci	 *   +----------------------------------------------------------------+
33928c2ecf20Sopenharmony_ci	 * 0 |                     Buffer Address [63:0]                      |
33938c2ecf20Sopenharmony_ci	 *   +----------------------------------------------------------------+
33948c2ecf20Sopenharmony_ci	 * 8 | VLAN tag |  POPTS  | Rsvd | Status | Command | DTYP |  DTALEN  |
33958c2ecf20Sopenharmony_ci	 *   +----------------------------------------------------------------+
33968c2ecf20Sopenharmony_ci	 *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
33978c2ecf20Sopenharmony_ci	 */
33988c2ecf20Sopenharmony_ci	pr_info("Tc[desc]     [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [bi->dma       ] leng  ntw timestmp         bi->skb\n");
33998c2ecf20Sopenharmony_ci	pr_info("Td[desc]     [address 63:0  ] [VlaPoRSCm1Dlen] [bi->dma       ] leng  ntw timestmp         bi->skb\n");
34008c2ecf20Sopenharmony_ci
34018c2ecf20Sopenharmony_ci	if (!netif_msg_tx_done(adapter))
34028c2ecf20Sopenharmony_ci		goto rx_ring_summary;
34038c2ecf20Sopenharmony_ci
34048c2ecf20Sopenharmony_ci	for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
34058c2ecf20Sopenharmony_ci		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
34068c2ecf20Sopenharmony_ci		struct e1000_tx_buffer *buffer_info = &tx_ring->buffer_info[i];
34078c2ecf20Sopenharmony_ci		struct my_u { __le64 a; __le64 b; };
34088c2ecf20Sopenharmony_ci		struct my_u *u = (struct my_u *)tx_desc;
34098c2ecf20Sopenharmony_ci		const char *type;
34108c2ecf20Sopenharmony_ci
34118c2ecf20Sopenharmony_ci		if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean)
34128c2ecf20Sopenharmony_ci			type = "NTC/U";
34138c2ecf20Sopenharmony_ci		else if (i == tx_ring->next_to_use)
34148c2ecf20Sopenharmony_ci			type = "NTU";
34158c2ecf20Sopenharmony_ci		else if (i == tx_ring->next_to_clean)
34168c2ecf20Sopenharmony_ci			type = "NTC";
34178c2ecf20Sopenharmony_ci		else
34188c2ecf20Sopenharmony_ci			type = "";
34198c2ecf20Sopenharmony_ci
34208c2ecf20Sopenharmony_ci		pr_info("T%c[0x%03X]    %016llX %016llX %016llX %04X  %3X %016llX %p %s\n",
34218c2ecf20Sopenharmony_ci			((le64_to_cpu(u->b) & (1<<20)) ? 'd' : 'c'), i,
34228c2ecf20Sopenharmony_ci			le64_to_cpu(u->a), le64_to_cpu(u->b),
34238c2ecf20Sopenharmony_ci			(u64)buffer_info->dma, buffer_info->length,
34248c2ecf20Sopenharmony_ci			buffer_info->next_to_watch,
34258c2ecf20Sopenharmony_ci			(u64)buffer_info->time_stamp, buffer_info->skb, type);
34268c2ecf20Sopenharmony_ci	}
34278c2ecf20Sopenharmony_ci
34288c2ecf20Sopenharmony_cirx_ring_summary:
34298c2ecf20Sopenharmony_ci	/* receive dump */
34308c2ecf20Sopenharmony_ci	pr_info("\nRX Desc ring dump\n");
34318c2ecf20Sopenharmony_ci
34328c2ecf20Sopenharmony_ci	/* Legacy Receive Descriptor Format
34338c2ecf20Sopenharmony_ci	 *
34348c2ecf20Sopenharmony_ci	 * +-----------------------------------------------------+
34358c2ecf20Sopenharmony_ci	 * |                Buffer Address [63:0]                |
34368c2ecf20Sopenharmony_ci	 * +-----------------------------------------------------+
34378c2ecf20Sopenharmony_ci	 * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
34388c2ecf20Sopenharmony_ci	 * +-----------------------------------------------------+
34398c2ecf20Sopenharmony_ci	 * 63       48 47    40 39      32 31         16 15      0
34408c2ecf20Sopenharmony_ci	 */
34418c2ecf20Sopenharmony_ci	pr_info("R[desc]      [address 63:0  ] [vl er S cks ln] [bi->dma       ] [bi->skb]\n");
34428c2ecf20Sopenharmony_ci
34438c2ecf20Sopenharmony_ci	if (!netif_msg_rx_status(adapter))
34448c2ecf20Sopenharmony_ci		goto exit;
34458c2ecf20Sopenharmony_ci
34468c2ecf20Sopenharmony_ci	for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
34478c2ecf20Sopenharmony_ci		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i);
34488c2ecf20Sopenharmony_ci		struct e1000_rx_buffer *buffer_info = &rx_ring->buffer_info[i];
34498c2ecf20Sopenharmony_ci		struct my_u { __le64 a; __le64 b; };
34508c2ecf20Sopenharmony_ci		struct my_u *u = (struct my_u *)rx_desc;
34518c2ecf20Sopenharmony_ci		const char *type;
34528c2ecf20Sopenharmony_ci
34538c2ecf20Sopenharmony_ci		if (i == rx_ring->next_to_use)
34548c2ecf20Sopenharmony_ci			type = "NTU";
34558c2ecf20Sopenharmony_ci		else if (i == rx_ring->next_to_clean)
34568c2ecf20Sopenharmony_ci			type = "NTC";
34578c2ecf20Sopenharmony_ci		else
34588c2ecf20Sopenharmony_ci			type = "";
34598c2ecf20Sopenharmony_ci
34608c2ecf20Sopenharmony_ci		pr_info("R[0x%03X]     %016llX %016llX %016llX %p %s\n",
34618c2ecf20Sopenharmony_ci			i, le64_to_cpu(u->a), le64_to_cpu(u->b),
34628c2ecf20Sopenharmony_ci			(u64)buffer_info->dma, buffer_info->rxbuf.data, type);
34638c2ecf20Sopenharmony_ci	} /* for */
34648c2ecf20Sopenharmony_ci
34658c2ecf20Sopenharmony_ci	/* dump the descriptor caches */
34668c2ecf20Sopenharmony_ci	/* rx */
34678c2ecf20Sopenharmony_ci	pr_info("Rx descriptor cache in 64bit format\n");
34688c2ecf20Sopenharmony_ci	for (i = 0x6000; i <= 0x63FF ; i += 0x10) {
34698c2ecf20Sopenharmony_ci		pr_info("R%04X: %08X|%08X %08X|%08X\n",
34708c2ecf20Sopenharmony_ci			i,
34718c2ecf20Sopenharmony_ci			readl(adapter->hw.hw_addr + i+4),
34728c2ecf20Sopenharmony_ci			readl(adapter->hw.hw_addr + i),
34738c2ecf20Sopenharmony_ci			readl(adapter->hw.hw_addr + i+12),
34748c2ecf20Sopenharmony_ci			readl(adapter->hw.hw_addr + i+8));
34758c2ecf20Sopenharmony_ci	}
34768c2ecf20Sopenharmony_ci	/* tx */
34778c2ecf20Sopenharmony_ci	pr_info("Tx descriptor cache in 64bit format\n");
34788c2ecf20Sopenharmony_ci	for (i = 0x7000; i <= 0x73FF ; i += 0x10) {
34798c2ecf20Sopenharmony_ci		pr_info("T%04X: %08X|%08X %08X|%08X\n",
34808c2ecf20Sopenharmony_ci			i,
34818c2ecf20Sopenharmony_ci			readl(adapter->hw.hw_addr + i+4),
34828c2ecf20Sopenharmony_ci			readl(adapter->hw.hw_addr + i),
34838c2ecf20Sopenharmony_ci			readl(adapter->hw.hw_addr + i+12),
34848c2ecf20Sopenharmony_ci			readl(adapter->hw.hw_addr + i+8));
34858c2ecf20Sopenharmony_ci	}
34868c2ecf20Sopenharmony_ciexit:
34878c2ecf20Sopenharmony_ci	return;
34888c2ecf20Sopenharmony_ci}
34898c2ecf20Sopenharmony_ci
34908c2ecf20Sopenharmony_ci/**
34918c2ecf20Sopenharmony_ci * e1000_tx_timeout - Respond to a Tx Hang
34928c2ecf20Sopenharmony_ci * @netdev: network interface device structure
34938c2ecf20Sopenharmony_ci * @txqueue: number of the Tx queue that hung (unused)
34948c2ecf20Sopenharmony_ci **/
34958c2ecf20Sopenharmony_cistatic void e1000_tx_timeout(struct net_device *netdev, unsigned int __always_unused txqueue)
34968c2ecf20Sopenharmony_ci{
34978c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
34988c2ecf20Sopenharmony_ci
34998c2ecf20Sopenharmony_ci	/* Do the reset outside of interrupt context */
35008c2ecf20Sopenharmony_ci	adapter->tx_timeout_count++;
35018c2ecf20Sopenharmony_ci	schedule_work(&adapter->reset_task);
35028c2ecf20Sopenharmony_ci}
35038c2ecf20Sopenharmony_ci
35048c2ecf20Sopenharmony_cistatic void e1000_reset_task(struct work_struct *work)
35058c2ecf20Sopenharmony_ci{
35068c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter =
35078c2ecf20Sopenharmony_ci		container_of(work, struct e1000_adapter, reset_task);
35088c2ecf20Sopenharmony_ci
35098c2ecf20Sopenharmony_ci	e_err(drv, "Reset adapter\n");
35108c2ecf20Sopenharmony_ci	e1000_reinit_locked(adapter);
35118c2ecf20Sopenharmony_ci}
35128c2ecf20Sopenharmony_ci
35138c2ecf20Sopenharmony_ci/**
35148c2ecf20Sopenharmony_ci * e1000_change_mtu - Change the Maximum Transfer Unit
35158c2ecf20Sopenharmony_ci * @netdev: network interface device structure
35168c2ecf20Sopenharmony_ci * @new_mtu: new value for maximum frame size
35178c2ecf20Sopenharmony_ci *
35188c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
35198c2ecf20Sopenharmony_ci **/
35208c2ecf20Sopenharmony_cistatic int e1000_change_mtu(struct net_device *netdev, int new_mtu)
35218c2ecf20Sopenharmony_ci{
35228c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
35238c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
35248c2ecf20Sopenharmony_ci	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
35258c2ecf20Sopenharmony_ci
35268c2ecf20Sopenharmony_ci	/* Adapter-specific max frame size limits. */
35278c2ecf20Sopenharmony_ci	switch (hw->mac_type) {
35288c2ecf20Sopenharmony_ci	case e1000_undefined ... e1000_82542_rev2_1:
35298c2ecf20Sopenharmony_ci		if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
35308c2ecf20Sopenharmony_ci			e_err(probe, "Jumbo Frames not supported.\n");
35318c2ecf20Sopenharmony_ci			return -EINVAL;
35328c2ecf20Sopenharmony_ci		}
35338c2ecf20Sopenharmony_ci		break;
35348c2ecf20Sopenharmony_ci	default:
35358c2ecf20Sopenharmony_ci		/* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
35368c2ecf20Sopenharmony_ci		break;
35378c2ecf20Sopenharmony_ci	}
35388c2ecf20Sopenharmony_ci
35398c2ecf20Sopenharmony_ci	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
35408c2ecf20Sopenharmony_ci		msleep(1);
35418c2ecf20Sopenharmony_ci	/* e1000_down has a dependency on max_frame_size */
35428c2ecf20Sopenharmony_ci	hw->max_frame_size = max_frame;
35438c2ecf20Sopenharmony_ci	if (netif_running(netdev)) {
35448c2ecf20Sopenharmony_ci		/* prevent buffers from being reallocated */
35458c2ecf20Sopenharmony_ci		adapter->alloc_rx_buf = e1000_alloc_dummy_rx_buffers;
35468c2ecf20Sopenharmony_ci		e1000_down(adapter);
35478c2ecf20Sopenharmony_ci	}
35488c2ecf20Sopenharmony_ci
35498c2ecf20Sopenharmony_ci	/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
35508c2ecf20Sopenharmony_ci	 * means we reserve 2 more, this pushes us to allocate from the next
35518c2ecf20Sopenharmony_ci	 * larger slab size.
35528c2ecf20Sopenharmony_ci	 * i.e. RXBUFFER_2048 --> size-4096 slab
35538c2ecf20Sopenharmony_ci	 * however with the new *_jumbo_rx* routines, jumbo receives will use
35548c2ecf20Sopenharmony_ci	 * fragmented skbs
35558c2ecf20Sopenharmony_ci	 */
35568c2ecf20Sopenharmony_ci
35578c2ecf20Sopenharmony_ci	if (max_frame <= E1000_RXBUFFER_2048)
35588c2ecf20Sopenharmony_ci		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
35598c2ecf20Sopenharmony_ci	else
35608c2ecf20Sopenharmony_ci#if (PAGE_SIZE >= E1000_RXBUFFER_16384)
35618c2ecf20Sopenharmony_ci		adapter->rx_buffer_len = E1000_RXBUFFER_16384;
35628c2ecf20Sopenharmony_ci#elif (PAGE_SIZE >= E1000_RXBUFFER_4096)
35638c2ecf20Sopenharmony_ci		adapter->rx_buffer_len = PAGE_SIZE;
35648c2ecf20Sopenharmony_ci#endif
35658c2ecf20Sopenharmony_ci
35668c2ecf20Sopenharmony_ci	/* adjust allocation if LPE protects us, and we aren't using SBP */
35678c2ecf20Sopenharmony_ci	if (!hw->tbi_compatibility_on &&
35688c2ecf20Sopenharmony_ci	    ((max_frame == (ETH_FRAME_LEN + ETH_FCS_LEN)) ||
35698c2ecf20Sopenharmony_ci	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
35708c2ecf20Sopenharmony_ci		adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
35718c2ecf20Sopenharmony_ci
35728c2ecf20Sopenharmony_ci	netdev_dbg(netdev, "changing MTU from %d to %d\n",
35738c2ecf20Sopenharmony_ci		   netdev->mtu, new_mtu);
35748c2ecf20Sopenharmony_ci	netdev->mtu = new_mtu;
35758c2ecf20Sopenharmony_ci
35768c2ecf20Sopenharmony_ci	if (netif_running(netdev))
35778c2ecf20Sopenharmony_ci		e1000_up(adapter);
35788c2ecf20Sopenharmony_ci	else
35798c2ecf20Sopenharmony_ci		e1000_reset(adapter);
35808c2ecf20Sopenharmony_ci
35818c2ecf20Sopenharmony_ci	clear_bit(__E1000_RESETTING, &adapter->flags);
35828c2ecf20Sopenharmony_ci
35838c2ecf20Sopenharmony_ci	return 0;
35848c2ecf20Sopenharmony_ci}
35858c2ecf20Sopenharmony_ci
35868c2ecf20Sopenharmony_ci/**
35878c2ecf20Sopenharmony_ci * e1000_update_stats - Update the board statistics counters
35888c2ecf20Sopenharmony_ci * @adapter: board private structure
35898c2ecf20Sopenharmony_ci **/
35908c2ecf20Sopenharmony_civoid e1000_update_stats(struct e1000_adapter *adapter)
35918c2ecf20Sopenharmony_ci{
35928c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
35938c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
35948c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
35958c2ecf20Sopenharmony_ci	unsigned long flags;
35968c2ecf20Sopenharmony_ci	u16 phy_tmp;
35978c2ecf20Sopenharmony_ci
35988c2ecf20Sopenharmony_ci#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
35998c2ecf20Sopenharmony_ci
36008c2ecf20Sopenharmony_ci	/* Prevent stats update while adapter is being reset, or if the pci
36018c2ecf20Sopenharmony_ci	 * connection is down.
36028c2ecf20Sopenharmony_ci	 */
36038c2ecf20Sopenharmony_ci	if (adapter->link_speed == 0)
36048c2ecf20Sopenharmony_ci		return;
36058c2ecf20Sopenharmony_ci	if (pci_channel_offline(pdev))
36068c2ecf20Sopenharmony_ci		return;
36078c2ecf20Sopenharmony_ci
36088c2ecf20Sopenharmony_ci	spin_lock_irqsave(&adapter->stats_lock, flags);
36098c2ecf20Sopenharmony_ci
36108c2ecf20Sopenharmony_ci	/* these counters are modified from e1000_tbi_adjust_stats,
36118c2ecf20Sopenharmony_ci	 * called from the interrupt context, so they must only
36128c2ecf20Sopenharmony_ci	 * be written while holding adapter->stats_lock
36138c2ecf20Sopenharmony_ci	 */
36148c2ecf20Sopenharmony_ci
36158c2ecf20Sopenharmony_ci	adapter->stats.crcerrs += er32(CRCERRS);
36168c2ecf20Sopenharmony_ci	adapter->stats.gprc += er32(GPRC);
36178c2ecf20Sopenharmony_ci	adapter->stats.gorcl += er32(GORCL);
36188c2ecf20Sopenharmony_ci	adapter->stats.gorch += er32(GORCH);
36198c2ecf20Sopenharmony_ci	adapter->stats.bprc += er32(BPRC);
36208c2ecf20Sopenharmony_ci	adapter->stats.mprc += er32(MPRC);
36218c2ecf20Sopenharmony_ci	adapter->stats.roc += er32(ROC);
36228c2ecf20Sopenharmony_ci
36238c2ecf20Sopenharmony_ci	adapter->stats.prc64 += er32(PRC64);
36248c2ecf20Sopenharmony_ci	adapter->stats.prc127 += er32(PRC127);
36258c2ecf20Sopenharmony_ci	adapter->stats.prc255 += er32(PRC255);
36268c2ecf20Sopenharmony_ci	adapter->stats.prc511 += er32(PRC511);
36278c2ecf20Sopenharmony_ci	adapter->stats.prc1023 += er32(PRC1023);
36288c2ecf20Sopenharmony_ci	adapter->stats.prc1522 += er32(PRC1522);
36298c2ecf20Sopenharmony_ci
36308c2ecf20Sopenharmony_ci	adapter->stats.symerrs += er32(SYMERRS);
36318c2ecf20Sopenharmony_ci	adapter->stats.mpc += er32(MPC);
36328c2ecf20Sopenharmony_ci	adapter->stats.scc += er32(SCC);
36338c2ecf20Sopenharmony_ci	adapter->stats.ecol += er32(ECOL);
36348c2ecf20Sopenharmony_ci	adapter->stats.mcc += er32(MCC);
36358c2ecf20Sopenharmony_ci	adapter->stats.latecol += er32(LATECOL);
36368c2ecf20Sopenharmony_ci	adapter->stats.dc += er32(DC);
36378c2ecf20Sopenharmony_ci	adapter->stats.sec += er32(SEC);
36388c2ecf20Sopenharmony_ci	adapter->stats.rlec += er32(RLEC);
36398c2ecf20Sopenharmony_ci	adapter->stats.xonrxc += er32(XONRXC);
36408c2ecf20Sopenharmony_ci	adapter->stats.xontxc += er32(XONTXC);
36418c2ecf20Sopenharmony_ci	adapter->stats.xoffrxc += er32(XOFFRXC);
36428c2ecf20Sopenharmony_ci	adapter->stats.xofftxc += er32(XOFFTXC);
36438c2ecf20Sopenharmony_ci	adapter->stats.fcruc += er32(FCRUC);
36448c2ecf20Sopenharmony_ci	adapter->stats.gptc += er32(GPTC);
36458c2ecf20Sopenharmony_ci	adapter->stats.gotcl += er32(GOTCL);
36468c2ecf20Sopenharmony_ci	adapter->stats.gotch += er32(GOTCH);
36478c2ecf20Sopenharmony_ci	adapter->stats.rnbc += er32(RNBC);
36488c2ecf20Sopenharmony_ci	adapter->stats.ruc += er32(RUC);
36498c2ecf20Sopenharmony_ci	adapter->stats.rfc += er32(RFC);
36508c2ecf20Sopenharmony_ci	adapter->stats.rjc += er32(RJC);
36518c2ecf20Sopenharmony_ci	adapter->stats.torl += er32(TORL);
36528c2ecf20Sopenharmony_ci	adapter->stats.torh += er32(TORH);
36538c2ecf20Sopenharmony_ci	adapter->stats.totl += er32(TOTL);
36548c2ecf20Sopenharmony_ci	adapter->stats.toth += er32(TOTH);
36558c2ecf20Sopenharmony_ci	adapter->stats.tpr += er32(TPR);
36568c2ecf20Sopenharmony_ci
36578c2ecf20Sopenharmony_ci	adapter->stats.ptc64 += er32(PTC64);
36588c2ecf20Sopenharmony_ci	adapter->stats.ptc127 += er32(PTC127);
36598c2ecf20Sopenharmony_ci	adapter->stats.ptc255 += er32(PTC255);
36608c2ecf20Sopenharmony_ci	adapter->stats.ptc511 += er32(PTC511);
36618c2ecf20Sopenharmony_ci	adapter->stats.ptc1023 += er32(PTC1023);
36628c2ecf20Sopenharmony_ci	adapter->stats.ptc1522 += er32(PTC1522);
36638c2ecf20Sopenharmony_ci
36648c2ecf20Sopenharmony_ci	adapter->stats.mptc += er32(MPTC);
36658c2ecf20Sopenharmony_ci	adapter->stats.bptc += er32(BPTC);
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci	/* used for adaptive IFS */
36688c2ecf20Sopenharmony_ci
36698c2ecf20Sopenharmony_ci	hw->tx_packet_delta = er32(TPT);
36708c2ecf20Sopenharmony_ci	adapter->stats.tpt += hw->tx_packet_delta;
36718c2ecf20Sopenharmony_ci	hw->collision_delta = er32(COLC);
36728c2ecf20Sopenharmony_ci	adapter->stats.colc += hw->collision_delta;
36738c2ecf20Sopenharmony_ci
36748c2ecf20Sopenharmony_ci	if (hw->mac_type >= e1000_82543) {
36758c2ecf20Sopenharmony_ci		adapter->stats.algnerrc += er32(ALGNERRC);
36768c2ecf20Sopenharmony_ci		adapter->stats.rxerrc += er32(RXERRC);
36778c2ecf20Sopenharmony_ci		adapter->stats.tncrs += er32(TNCRS);
36788c2ecf20Sopenharmony_ci		adapter->stats.cexterr += er32(CEXTERR);
36798c2ecf20Sopenharmony_ci		adapter->stats.tsctc += er32(TSCTC);
36808c2ecf20Sopenharmony_ci		adapter->stats.tsctfc += er32(TSCTFC);
36818c2ecf20Sopenharmony_ci	}
36828c2ecf20Sopenharmony_ci
36838c2ecf20Sopenharmony_ci	/* Fill out the OS statistics structure */
36848c2ecf20Sopenharmony_ci	netdev->stats.multicast = adapter->stats.mprc;
36858c2ecf20Sopenharmony_ci	netdev->stats.collisions = adapter->stats.colc;
36868c2ecf20Sopenharmony_ci
36878c2ecf20Sopenharmony_ci	/* Rx Errors */
36888c2ecf20Sopenharmony_ci
36898c2ecf20Sopenharmony_ci	/* RLEC on some newer hardware can be incorrect so build
36908c2ecf20Sopenharmony_ci	 * our own version based on RUC and ROC
36918c2ecf20Sopenharmony_ci	 */
36928c2ecf20Sopenharmony_ci	netdev->stats.rx_errors = adapter->stats.rxerrc +
36938c2ecf20Sopenharmony_ci		adapter->stats.crcerrs + adapter->stats.algnerrc +
36948c2ecf20Sopenharmony_ci		adapter->stats.ruc + adapter->stats.roc +
36958c2ecf20Sopenharmony_ci		adapter->stats.cexterr;
36968c2ecf20Sopenharmony_ci	adapter->stats.rlerrc = adapter->stats.ruc + adapter->stats.roc;
36978c2ecf20Sopenharmony_ci	netdev->stats.rx_length_errors = adapter->stats.rlerrc;
36988c2ecf20Sopenharmony_ci	netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
36998c2ecf20Sopenharmony_ci	netdev->stats.rx_frame_errors = adapter->stats.algnerrc;
37008c2ecf20Sopenharmony_ci	netdev->stats.rx_missed_errors = adapter->stats.mpc;
37018c2ecf20Sopenharmony_ci
37028c2ecf20Sopenharmony_ci	/* Tx Errors */
37038c2ecf20Sopenharmony_ci	adapter->stats.txerrc = adapter->stats.ecol + adapter->stats.latecol;
37048c2ecf20Sopenharmony_ci	netdev->stats.tx_errors = adapter->stats.txerrc;
37058c2ecf20Sopenharmony_ci	netdev->stats.tx_aborted_errors = adapter->stats.ecol;
37068c2ecf20Sopenharmony_ci	netdev->stats.tx_window_errors = adapter->stats.latecol;
37078c2ecf20Sopenharmony_ci	netdev->stats.tx_carrier_errors = adapter->stats.tncrs;
37088c2ecf20Sopenharmony_ci	if (hw->bad_tx_carr_stats_fd &&
37098c2ecf20Sopenharmony_ci	    adapter->link_duplex == FULL_DUPLEX) {
37108c2ecf20Sopenharmony_ci		netdev->stats.tx_carrier_errors = 0;
37118c2ecf20Sopenharmony_ci		adapter->stats.tncrs = 0;
37128c2ecf20Sopenharmony_ci	}
37138c2ecf20Sopenharmony_ci
37148c2ecf20Sopenharmony_ci	/* Tx Dropped needs to be maintained elsewhere */
37158c2ecf20Sopenharmony_ci
37168c2ecf20Sopenharmony_ci	/* Phy Stats */
37178c2ecf20Sopenharmony_ci	if (hw->media_type == e1000_media_type_copper) {
37188c2ecf20Sopenharmony_ci		if ((adapter->link_speed == SPEED_1000) &&
37198c2ecf20Sopenharmony_ci		   (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
37208c2ecf20Sopenharmony_ci			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
37218c2ecf20Sopenharmony_ci			adapter->phy_stats.idle_errors += phy_tmp;
37228c2ecf20Sopenharmony_ci		}
37238c2ecf20Sopenharmony_ci
37248c2ecf20Sopenharmony_ci		if ((hw->mac_type <= e1000_82546) &&
37258c2ecf20Sopenharmony_ci		   (hw->phy_type == e1000_phy_m88) &&
37268c2ecf20Sopenharmony_ci		   !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
37278c2ecf20Sopenharmony_ci			adapter->phy_stats.receive_errors += phy_tmp;
37288c2ecf20Sopenharmony_ci	}
37298c2ecf20Sopenharmony_ci
37308c2ecf20Sopenharmony_ci	/* Management Stats */
37318c2ecf20Sopenharmony_ci	if (hw->has_smbus) {
37328c2ecf20Sopenharmony_ci		adapter->stats.mgptc += er32(MGTPTC);
37338c2ecf20Sopenharmony_ci		adapter->stats.mgprc += er32(MGTPRC);
37348c2ecf20Sopenharmony_ci		adapter->stats.mgpdc += er32(MGTPDC);
37358c2ecf20Sopenharmony_ci	}
37368c2ecf20Sopenharmony_ci
37378c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&adapter->stats_lock, flags);
37388c2ecf20Sopenharmony_ci}
37398c2ecf20Sopenharmony_ci
37408c2ecf20Sopenharmony_ci/**
37418c2ecf20Sopenharmony_ci * e1000_intr - Interrupt Handler
37428c2ecf20Sopenharmony_ci * @irq: interrupt number
37438c2ecf20Sopenharmony_ci * @data: pointer to a network interface device structure
37448c2ecf20Sopenharmony_ci **/
37458c2ecf20Sopenharmony_cistatic irqreturn_t e1000_intr(int irq, void *data)
37468c2ecf20Sopenharmony_ci{
37478c2ecf20Sopenharmony_ci	struct net_device *netdev = data;
37488c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
37498c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
37508c2ecf20Sopenharmony_ci	u32 icr = er32(ICR);
37518c2ecf20Sopenharmony_ci
37528c2ecf20Sopenharmony_ci	if (unlikely((!icr)))
37538c2ecf20Sopenharmony_ci		return IRQ_NONE;  /* Not our interrupt */
37548c2ecf20Sopenharmony_ci
37558c2ecf20Sopenharmony_ci	/* we might have caused the interrupt, but the above
37568c2ecf20Sopenharmony_ci	 * read cleared it, and just in case the driver is
37578c2ecf20Sopenharmony_ci	 * down there is nothing to do so return handled
37588c2ecf20Sopenharmony_ci	 */
37598c2ecf20Sopenharmony_ci	if (unlikely(test_bit(__E1000_DOWN, &adapter->flags)))
37608c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
37618c2ecf20Sopenharmony_ci
37628c2ecf20Sopenharmony_ci	if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
37638c2ecf20Sopenharmony_ci		hw->get_link_status = 1;
37648c2ecf20Sopenharmony_ci		/* guard against interrupt when we're going down */
37658c2ecf20Sopenharmony_ci		if (!test_bit(__E1000_DOWN, &adapter->flags))
37668c2ecf20Sopenharmony_ci			schedule_delayed_work(&adapter->watchdog_task, 1);
37678c2ecf20Sopenharmony_ci	}
37688c2ecf20Sopenharmony_ci
37698c2ecf20Sopenharmony_ci	/* disable interrupts, without the synchronize_irq bit */
37708c2ecf20Sopenharmony_ci	ew32(IMC, ~0);
37718c2ecf20Sopenharmony_ci	E1000_WRITE_FLUSH();
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci	if (likely(napi_schedule_prep(&adapter->napi))) {
37748c2ecf20Sopenharmony_ci		adapter->total_tx_bytes = 0;
37758c2ecf20Sopenharmony_ci		adapter->total_tx_packets = 0;
37768c2ecf20Sopenharmony_ci		adapter->total_rx_bytes = 0;
37778c2ecf20Sopenharmony_ci		adapter->total_rx_packets = 0;
37788c2ecf20Sopenharmony_ci		__napi_schedule(&adapter->napi);
37798c2ecf20Sopenharmony_ci	} else {
37808c2ecf20Sopenharmony_ci		/* this really should not happen! if it does it is basically a
37818c2ecf20Sopenharmony_ci		 * bug, but not a hard error, so enable ints and continue
37828c2ecf20Sopenharmony_ci		 */
37838c2ecf20Sopenharmony_ci		if (!test_bit(__E1000_DOWN, &adapter->flags))
37848c2ecf20Sopenharmony_ci			e1000_irq_enable(adapter);
37858c2ecf20Sopenharmony_ci	}
37868c2ecf20Sopenharmony_ci
37878c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
37888c2ecf20Sopenharmony_ci}
37898c2ecf20Sopenharmony_ci
37908c2ecf20Sopenharmony_ci/**
37918c2ecf20Sopenharmony_ci * e1000_clean - NAPI Rx polling callback
37928c2ecf20Sopenharmony_ci * @napi: napi struct containing references to driver info
37938c2ecf20Sopenharmony_ci * @budget: budget given to driver for receive packets
37948c2ecf20Sopenharmony_ci **/
37958c2ecf20Sopenharmony_cistatic int e1000_clean(struct napi_struct *napi, int budget)
37968c2ecf20Sopenharmony_ci{
37978c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter,
37988c2ecf20Sopenharmony_ci						     napi);
37998c2ecf20Sopenharmony_ci	int tx_clean_complete = 0, work_done = 0;
38008c2ecf20Sopenharmony_ci
38018c2ecf20Sopenharmony_ci	tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]);
38028c2ecf20Sopenharmony_ci
38038c2ecf20Sopenharmony_ci	adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget);
38048c2ecf20Sopenharmony_ci
38058c2ecf20Sopenharmony_ci	if (!tx_clean_complete || work_done == budget)
38068c2ecf20Sopenharmony_ci		return budget;
38078c2ecf20Sopenharmony_ci
38088c2ecf20Sopenharmony_ci	/* Exit the polling mode, but don't re-enable interrupts if stack might
38098c2ecf20Sopenharmony_ci	 * poll us due to busy-polling
38108c2ecf20Sopenharmony_ci	 */
38118c2ecf20Sopenharmony_ci	if (likely(napi_complete_done(napi, work_done))) {
38128c2ecf20Sopenharmony_ci		if (likely(adapter->itr_setting & 3))
38138c2ecf20Sopenharmony_ci			e1000_set_itr(adapter);
38148c2ecf20Sopenharmony_ci		if (!test_bit(__E1000_DOWN, &adapter->flags))
38158c2ecf20Sopenharmony_ci			e1000_irq_enable(adapter);
38168c2ecf20Sopenharmony_ci	}
38178c2ecf20Sopenharmony_ci
38188c2ecf20Sopenharmony_ci	return work_done;
38198c2ecf20Sopenharmony_ci}
38208c2ecf20Sopenharmony_ci
38218c2ecf20Sopenharmony_ci/**
38228c2ecf20Sopenharmony_ci * e1000_clean_tx_irq - Reclaim resources after transmit completes
38238c2ecf20Sopenharmony_ci * @adapter: board private structure
38248c2ecf20Sopenharmony_ci * @tx_ring: ring to clean
38258c2ecf20Sopenharmony_ci **/
38268c2ecf20Sopenharmony_cistatic bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
38278c2ecf20Sopenharmony_ci			       struct e1000_tx_ring *tx_ring)
38288c2ecf20Sopenharmony_ci{
38298c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
38308c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
38318c2ecf20Sopenharmony_ci	struct e1000_tx_desc *tx_desc, *eop_desc;
38328c2ecf20Sopenharmony_ci	struct e1000_tx_buffer *buffer_info;
38338c2ecf20Sopenharmony_ci	unsigned int i, eop;
38348c2ecf20Sopenharmony_ci	unsigned int count = 0;
38358c2ecf20Sopenharmony_ci	unsigned int total_tx_bytes = 0, total_tx_packets = 0;
38368c2ecf20Sopenharmony_ci	unsigned int bytes_compl = 0, pkts_compl = 0;
38378c2ecf20Sopenharmony_ci
38388c2ecf20Sopenharmony_ci	i = tx_ring->next_to_clean;
38398c2ecf20Sopenharmony_ci	eop = tx_ring->buffer_info[i].next_to_watch;
38408c2ecf20Sopenharmony_ci	eop_desc = E1000_TX_DESC(*tx_ring, eop);
38418c2ecf20Sopenharmony_ci
38428c2ecf20Sopenharmony_ci	while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
38438c2ecf20Sopenharmony_ci	       (count < tx_ring->count)) {
38448c2ecf20Sopenharmony_ci		bool cleaned = false;
38458c2ecf20Sopenharmony_ci		dma_rmb();	/* read buffer_info after eop_desc */
38468c2ecf20Sopenharmony_ci		for ( ; !cleaned; count++) {
38478c2ecf20Sopenharmony_ci			tx_desc = E1000_TX_DESC(*tx_ring, i);
38488c2ecf20Sopenharmony_ci			buffer_info = &tx_ring->buffer_info[i];
38498c2ecf20Sopenharmony_ci			cleaned = (i == eop);
38508c2ecf20Sopenharmony_ci
38518c2ecf20Sopenharmony_ci			if (cleaned) {
38528c2ecf20Sopenharmony_ci				total_tx_packets += buffer_info->segs;
38538c2ecf20Sopenharmony_ci				total_tx_bytes += buffer_info->bytecount;
38548c2ecf20Sopenharmony_ci				if (buffer_info->skb) {
38558c2ecf20Sopenharmony_ci					bytes_compl += buffer_info->skb->len;
38568c2ecf20Sopenharmony_ci					pkts_compl++;
38578c2ecf20Sopenharmony_ci				}
38588c2ecf20Sopenharmony_ci
38598c2ecf20Sopenharmony_ci			}
38608c2ecf20Sopenharmony_ci			e1000_unmap_and_free_tx_resource(adapter, buffer_info);
38618c2ecf20Sopenharmony_ci			tx_desc->upper.data = 0;
38628c2ecf20Sopenharmony_ci
38638c2ecf20Sopenharmony_ci			if (unlikely(++i == tx_ring->count))
38648c2ecf20Sopenharmony_ci				i = 0;
38658c2ecf20Sopenharmony_ci		}
38668c2ecf20Sopenharmony_ci
38678c2ecf20Sopenharmony_ci		eop = tx_ring->buffer_info[i].next_to_watch;
38688c2ecf20Sopenharmony_ci		eop_desc = E1000_TX_DESC(*tx_ring, eop);
38698c2ecf20Sopenharmony_ci	}
38708c2ecf20Sopenharmony_ci
38718c2ecf20Sopenharmony_ci	/* Synchronize with E1000_DESC_UNUSED called from e1000_xmit_frame,
38728c2ecf20Sopenharmony_ci	 * which will reuse the cleaned buffers.
38738c2ecf20Sopenharmony_ci	 */
38748c2ecf20Sopenharmony_ci	smp_store_release(&tx_ring->next_to_clean, i);
38758c2ecf20Sopenharmony_ci
38768c2ecf20Sopenharmony_ci	netdev_completed_queue(netdev, pkts_compl, bytes_compl);
38778c2ecf20Sopenharmony_ci
38788c2ecf20Sopenharmony_ci#define TX_WAKE_THRESHOLD 32
38798c2ecf20Sopenharmony_ci	if (unlikely(count && netif_carrier_ok(netdev) &&
38808c2ecf20Sopenharmony_ci		     E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
38818c2ecf20Sopenharmony_ci		/* Make sure that anybody stopping the queue after this
38828c2ecf20Sopenharmony_ci		 * sees the new next_to_clean.
38838c2ecf20Sopenharmony_ci		 */
38848c2ecf20Sopenharmony_ci		smp_mb();
38858c2ecf20Sopenharmony_ci
38868c2ecf20Sopenharmony_ci		if (netif_queue_stopped(netdev) &&
38878c2ecf20Sopenharmony_ci		    !(test_bit(__E1000_DOWN, &adapter->flags))) {
38888c2ecf20Sopenharmony_ci			netif_wake_queue(netdev);
38898c2ecf20Sopenharmony_ci			++adapter->restart_queue;
38908c2ecf20Sopenharmony_ci		}
38918c2ecf20Sopenharmony_ci	}
38928c2ecf20Sopenharmony_ci
38938c2ecf20Sopenharmony_ci	if (adapter->detect_tx_hung) {
38948c2ecf20Sopenharmony_ci		/* Detect a transmit hang in hardware, this serializes the
38958c2ecf20Sopenharmony_ci		 * check with the clearing of time_stamp and movement of i
38968c2ecf20Sopenharmony_ci		 */
38978c2ecf20Sopenharmony_ci		adapter->detect_tx_hung = false;
38988c2ecf20Sopenharmony_ci		if (tx_ring->buffer_info[eop].time_stamp &&
38998c2ecf20Sopenharmony_ci		    time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
39008c2ecf20Sopenharmony_ci			       (adapter->tx_timeout_factor * HZ)) &&
39018c2ecf20Sopenharmony_ci		    !(er32(STATUS) & E1000_STATUS_TXOFF)) {
39028c2ecf20Sopenharmony_ci
39038c2ecf20Sopenharmony_ci			/* detected Tx unit hang */
39048c2ecf20Sopenharmony_ci			e_err(drv, "Detected Tx Unit Hang\n"
39058c2ecf20Sopenharmony_ci			      "  Tx Queue             <%lu>\n"
39068c2ecf20Sopenharmony_ci			      "  TDH                  <%x>\n"
39078c2ecf20Sopenharmony_ci			      "  TDT                  <%x>\n"
39088c2ecf20Sopenharmony_ci			      "  next_to_use          <%x>\n"
39098c2ecf20Sopenharmony_ci			      "  next_to_clean        <%x>\n"
39108c2ecf20Sopenharmony_ci			      "buffer_info[next_to_clean]\n"
39118c2ecf20Sopenharmony_ci			      "  time_stamp           <%lx>\n"
39128c2ecf20Sopenharmony_ci			      "  next_to_watch        <%x>\n"
39138c2ecf20Sopenharmony_ci			      "  jiffies              <%lx>\n"
39148c2ecf20Sopenharmony_ci			      "  next_to_watch.status <%x>\n",
39158c2ecf20Sopenharmony_ci				(unsigned long)(tx_ring - adapter->tx_ring),
39168c2ecf20Sopenharmony_ci				readl(hw->hw_addr + tx_ring->tdh),
39178c2ecf20Sopenharmony_ci				readl(hw->hw_addr + tx_ring->tdt),
39188c2ecf20Sopenharmony_ci				tx_ring->next_to_use,
39198c2ecf20Sopenharmony_ci				tx_ring->next_to_clean,
39208c2ecf20Sopenharmony_ci				tx_ring->buffer_info[eop].time_stamp,
39218c2ecf20Sopenharmony_ci				eop,
39228c2ecf20Sopenharmony_ci				jiffies,
39238c2ecf20Sopenharmony_ci				eop_desc->upper.fields.status);
39248c2ecf20Sopenharmony_ci			e1000_dump(adapter);
39258c2ecf20Sopenharmony_ci			netif_stop_queue(netdev);
39268c2ecf20Sopenharmony_ci		}
39278c2ecf20Sopenharmony_ci	}
39288c2ecf20Sopenharmony_ci	adapter->total_tx_bytes += total_tx_bytes;
39298c2ecf20Sopenharmony_ci	adapter->total_tx_packets += total_tx_packets;
39308c2ecf20Sopenharmony_ci	netdev->stats.tx_bytes += total_tx_bytes;
39318c2ecf20Sopenharmony_ci	netdev->stats.tx_packets += total_tx_packets;
39328c2ecf20Sopenharmony_ci	return count < tx_ring->count;
39338c2ecf20Sopenharmony_ci}
39348c2ecf20Sopenharmony_ci
39358c2ecf20Sopenharmony_ci/**
39368c2ecf20Sopenharmony_ci * e1000_rx_checksum - Receive Checksum Offload for 82543
39378c2ecf20Sopenharmony_ci * @adapter:     board private structure
39388c2ecf20Sopenharmony_ci * @status_err:  receive descriptor status and error fields
39398c2ecf20Sopenharmony_ci * @csum:        receive descriptor csum field
39408c2ecf20Sopenharmony_ci * @skb:         socket buffer with received data
39418c2ecf20Sopenharmony_ci **/
39428c2ecf20Sopenharmony_cistatic void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
39438c2ecf20Sopenharmony_ci			      u32 csum, struct sk_buff *skb)
39448c2ecf20Sopenharmony_ci{
39458c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
39468c2ecf20Sopenharmony_ci	u16 status = (u16)status_err;
39478c2ecf20Sopenharmony_ci	u8 errors = (u8)(status_err >> 24);
39488c2ecf20Sopenharmony_ci
39498c2ecf20Sopenharmony_ci	skb_checksum_none_assert(skb);
39508c2ecf20Sopenharmony_ci
39518c2ecf20Sopenharmony_ci	/* 82543 or newer only */
39528c2ecf20Sopenharmony_ci	if (unlikely(hw->mac_type < e1000_82543))
39538c2ecf20Sopenharmony_ci		return;
39548c2ecf20Sopenharmony_ci	/* Ignore Checksum bit is set */
39558c2ecf20Sopenharmony_ci	if (unlikely(status & E1000_RXD_STAT_IXSM))
39568c2ecf20Sopenharmony_ci		return;
39578c2ecf20Sopenharmony_ci	/* TCP/UDP checksum error bit is set */
39588c2ecf20Sopenharmony_ci	if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
39598c2ecf20Sopenharmony_ci		/* let the stack verify checksum errors */
39608c2ecf20Sopenharmony_ci		adapter->hw_csum_err++;
39618c2ecf20Sopenharmony_ci		return;
39628c2ecf20Sopenharmony_ci	}
39638c2ecf20Sopenharmony_ci	/* TCP/UDP Checksum has not been calculated */
39648c2ecf20Sopenharmony_ci	if (!(status & E1000_RXD_STAT_TCPCS))
39658c2ecf20Sopenharmony_ci		return;
39668c2ecf20Sopenharmony_ci
39678c2ecf20Sopenharmony_ci	/* It must be a TCP or UDP packet with a valid checksum */
39688c2ecf20Sopenharmony_ci	if (likely(status & E1000_RXD_STAT_TCPCS)) {
39698c2ecf20Sopenharmony_ci		/* TCP checksum is good */
39708c2ecf20Sopenharmony_ci		skb->ip_summed = CHECKSUM_UNNECESSARY;
39718c2ecf20Sopenharmony_ci	}
39728c2ecf20Sopenharmony_ci	adapter->hw_csum_good++;
39738c2ecf20Sopenharmony_ci}
39748c2ecf20Sopenharmony_ci
39758c2ecf20Sopenharmony_ci/**
39768c2ecf20Sopenharmony_ci * e1000_consume_page - helper function for jumbo Rx path
39778c2ecf20Sopenharmony_ci * @bi: software descriptor shadow data
39788c2ecf20Sopenharmony_ci * @skb: skb being modified
39798c2ecf20Sopenharmony_ci * @length: length of data being added
39808c2ecf20Sopenharmony_ci **/
39818c2ecf20Sopenharmony_cistatic void e1000_consume_page(struct e1000_rx_buffer *bi, struct sk_buff *skb,
39828c2ecf20Sopenharmony_ci			       u16 length)
39838c2ecf20Sopenharmony_ci{
39848c2ecf20Sopenharmony_ci	bi->rxbuf.page = NULL;
39858c2ecf20Sopenharmony_ci	skb->len += length;
39868c2ecf20Sopenharmony_ci	skb->data_len += length;
39878c2ecf20Sopenharmony_ci	skb->truesize += PAGE_SIZE;
39888c2ecf20Sopenharmony_ci}
39898c2ecf20Sopenharmony_ci
39908c2ecf20Sopenharmony_ci/**
39918c2ecf20Sopenharmony_ci * e1000_receive_skb - helper function to handle rx indications
39928c2ecf20Sopenharmony_ci * @adapter: board private structure
39938c2ecf20Sopenharmony_ci * @status: descriptor status field as written by hardware
39948c2ecf20Sopenharmony_ci * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
39958c2ecf20Sopenharmony_ci * @skb: pointer to sk_buff to be indicated to stack
39968c2ecf20Sopenharmony_ci */
39978c2ecf20Sopenharmony_cistatic void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
39988c2ecf20Sopenharmony_ci			      __le16 vlan, struct sk_buff *skb)
39998c2ecf20Sopenharmony_ci{
40008c2ecf20Sopenharmony_ci	skb->protocol = eth_type_trans(skb, adapter->netdev);
40018c2ecf20Sopenharmony_ci
40028c2ecf20Sopenharmony_ci	if (status & E1000_RXD_STAT_VP) {
40038c2ecf20Sopenharmony_ci		u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
40048c2ecf20Sopenharmony_ci
40058c2ecf20Sopenharmony_ci		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
40068c2ecf20Sopenharmony_ci	}
40078c2ecf20Sopenharmony_ci	napi_gro_receive(&adapter->napi, skb);
40088c2ecf20Sopenharmony_ci}
40098c2ecf20Sopenharmony_ci
40108c2ecf20Sopenharmony_ci/**
40118c2ecf20Sopenharmony_ci * e1000_tbi_adjust_stats
40128c2ecf20Sopenharmony_ci * @hw: Struct containing variables accessed by shared code
40138c2ecf20Sopenharmony_ci * @stats: point to stats struct
40148c2ecf20Sopenharmony_ci * @frame_len: The length of the frame in question
40158c2ecf20Sopenharmony_ci * @mac_addr: The Ethernet destination address of the frame in question
40168c2ecf20Sopenharmony_ci *
40178c2ecf20Sopenharmony_ci * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
40188c2ecf20Sopenharmony_ci */
40198c2ecf20Sopenharmony_cistatic void e1000_tbi_adjust_stats(struct e1000_hw *hw,
40208c2ecf20Sopenharmony_ci				   struct e1000_hw_stats *stats,
40218c2ecf20Sopenharmony_ci				   u32 frame_len, const u8 *mac_addr)
40228c2ecf20Sopenharmony_ci{
40238c2ecf20Sopenharmony_ci	u64 carry_bit;
40248c2ecf20Sopenharmony_ci
40258c2ecf20Sopenharmony_ci	/* First adjust the frame length. */
40268c2ecf20Sopenharmony_ci	frame_len--;
40278c2ecf20Sopenharmony_ci	/* We need to adjust the statistics counters, since the hardware
40288c2ecf20Sopenharmony_ci	 * counters overcount this packet as a CRC error and undercount
40298c2ecf20Sopenharmony_ci	 * the packet as a good packet
40308c2ecf20Sopenharmony_ci	 */
40318c2ecf20Sopenharmony_ci	/* This packet should not be counted as a CRC error. */
40328c2ecf20Sopenharmony_ci	stats->crcerrs--;
40338c2ecf20Sopenharmony_ci	/* This packet does count as a Good Packet Received. */
40348c2ecf20Sopenharmony_ci	stats->gprc++;
40358c2ecf20Sopenharmony_ci
40368c2ecf20Sopenharmony_ci	/* Adjust the Good Octets received counters */
40378c2ecf20Sopenharmony_ci	carry_bit = 0x80000000 & stats->gorcl;
40388c2ecf20Sopenharmony_ci	stats->gorcl += frame_len;
40398c2ecf20Sopenharmony_ci	/* If the high bit of Gorcl (the low 32 bits of the Good Octets
40408c2ecf20Sopenharmony_ci	 * Received Count) was one before the addition,
40418c2ecf20Sopenharmony_ci	 * AND it is zero after, then we lost the carry out,
40428c2ecf20Sopenharmony_ci	 * need to add one to Gorch (Good Octets Received Count High).
40438c2ecf20Sopenharmony_ci	 * This could be simplified if all environments supported
40448c2ecf20Sopenharmony_ci	 * 64-bit integers.
40458c2ecf20Sopenharmony_ci	 */
40468c2ecf20Sopenharmony_ci	if (carry_bit && ((stats->gorcl & 0x80000000) == 0))
40478c2ecf20Sopenharmony_ci		stats->gorch++;
40488c2ecf20Sopenharmony_ci	/* Is this a broadcast or multicast?  Check broadcast first,
40498c2ecf20Sopenharmony_ci	 * since the test for a multicast frame will test positive on
40508c2ecf20Sopenharmony_ci	 * a broadcast frame.
40518c2ecf20Sopenharmony_ci	 */
40528c2ecf20Sopenharmony_ci	if (is_broadcast_ether_addr(mac_addr))
40538c2ecf20Sopenharmony_ci		stats->bprc++;
40548c2ecf20Sopenharmony_ci	else if (is_multicast_ether_addr(mac_addr))
40558c2ecf20Sopenharmony_ci		stats->mprc++;
40568c2ecf20Sopenharmony_ci
40578c2ecf20Sopenharmony_ci	if (frame_len == hw->max_frame_size) {
40588c2ecf20Sopenharmony_ci		/* In this case, the hardware has overcounted the number of
40598c2ecf20Sopenharmony_ci		 * oversize frames.
40608c2ecf20Sopenharmony_ci		 */
40618c2ecf20Sopenharmony_ci		if (stats->roc > 0)
40628c2ecf20Sopenharmony_ci			stats->roc--;
40638c2ecf20Sopenharmony_ci	}
40648c2ecf20Sopenharmony_ci
40658c2ecf20Sopenharmony_ci	/* Adjust the bin counters when the extra byte put the frame in the
40668c2ecf20Sopenharmony_ci	 * wrong bin. Remember that the frame_len was adjusted above.
40678c2ecf20Sopenharmony_ci	 */
40688c2ecf20Sopenharmony_ci	if (frame_len == 64) {
40698c2ecf20Sopenharmony_ci		stats->prc64++;
40708c2ecf20Sopenharmony_ci		stats->prc127--;
40718c2ecf20Sopenharmony_ci	} else if (frame_len == 127) {
40728c2ecf20Sopenharmony_ci		stats->prc127++;
40738c2ecf20Sopenharmony_ci		stats->prc255--;
40748c2ecf20Sopenharmony_ci	} else if (frame_len == 255) {
40758c2ecf20Sopenharmony_ci		stats->prc255++;
40768c2ecf20Sopenharmony_ci		stats->prc511--;
40778c2ecf20Sopenharmony_ci	} else if (frame_len == 511) {
40788c2ecf20Sopenharmony_ci		stats->prc511++;
40798c2ecf20Sopenharmony_ci		stats->prc1023--;
40808c2ecf20Sopenharmony_ci	} else if (frame_len == 1023) {
40818c2ecf20Sopenharmony_ci		stats->prc1023++;
40828c2ecf20Sopenharmony_ci		stats->prc1522--;
40838c2ecf20Sopenharmony_ci	} else if (frame_len == 1522) {
40848c2ecf20Sopenharmony_ci		stats->prc1522++;
40858c2ecf20Sopenharmony_ci	}
40868c2ecf20Sopenharmony_ci}
40878c2ecf20Sopenharmony_ci
40888c2ecf20Sopenharmony_cistatic bool e1000_tbi_should_accept(struct e1000_adapter *adapter,
40898c2ecf20Sopenharmony_ci				    u8 status, u8 errors,
40908c2ecf20Sopenharmony_ci				    u32 length, const u8 *data)
40918c2ecf20Sopenharmony_ci{
40928c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
40938c2ecf20Sopenharmony_ci	u8 last_byte = *(data + length - 1);
40948c2ecf20Sopenharmony_ci
40958c2ecf20Sopenharmony_ci	if (TBI_ACCEPT(hw, status, errors, length, last_byte)) {
40968c2ecf20Sopenharmony_ci		unsigned long irq_flags;
40978c2ecf20Sopenharmony_ci
40988c2ecf20Sopenharmony_ci		spin_lock_irqsave(&adapter->stats_lock, irq_flags);
40998c2ecf20Sopenharmony_ci		e1000_tbi_adjust_stats(hw, &adapter->stats, length, data);
41008c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
41018c2ecf20Sopenharmony_ci
41028c2ecf20Sopenharmony_ci		return true;
41038c2ecf20Sopenharmony_ci	}
41048c2ecf20Sopenharmony_ci
41058c2ecf20Sopenharmony_ci	return false;
41068c2ecf20Sopenharmony_ci}
41078c2ecf20Sopenharmony_ci
41088c2ecf20Sopenharmony_cistatic struct sk_buff *e1000_alloc_rx_skb(struct e1000_adapter *adapter,
41098c2ecf20Sopenharmony_ci					  unsigned int bufsz)
41108c2ecf20Sopenharmony_ci{
41118c2ecf20Sopenharmony_ci	struct sk_buff *skb = napi_alloc_skb(&adapter->napi, bufsz);
41128c2ecf20Sopenharmony_ci
41138c2ecf20Sopenharmony_ci	if (unlikely(!skb))
41148c2ecf20Sopenharmony_ci		adapter->alloc_rx_buff_failed++;
41158c2ecf20Sopenharmony_ci	return skb;
41168c2ecf20Sopenharmony_ci}
41178c2ecf20Sopenharmony_ci
41188c2ecf20Sopenharmony_ci/**
41198c2ecf20Sopenharmony_ci * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy
41208c2ecf20Sopenharmony_ci * @adapter: board private structure
41218c2ecf20Sopenharmony_ci * @rx_ring: ring to clean
41228c2ecf20Sopenharmony_ci * @work_done: amount of napi work completed this call
41238c2ecf20Sopenharmony_ci * @work_to_do: max amount of work allowed for this call to do
41248c2ecf20Sopenharmony_ci *
41258c2ecf20Sopenharmony_ci * the return value indicates whether actual cleaning was done, there
41268c2ecf20Sopenharmony_ci * is no guarantee that everything was cleaned
41278c2ecf20Sopenharmony_ci */
41288c2ecf20Sopenharmony_cistatic bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
41298c2ecf20Sopenharmony_ci				     struct e1000_rx_ring *rx_ring,
41308c2ecf20Sopenharmony_ci				     int *work_done, int work_to_do)
41318c2ecf20Sopenharmony_ci{
41328c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
41338c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
41348c2ecf20Sopenharmony_ci	struct e1000_rx_desc *rx_desc, *next_rxd;
41358c2ecf20Sopenharmony_ci	struct e1000_rx_buffer *buffer_info, *next_buffer;
41368c2ecf20Sopenharmony_ci	u32 length;
41378c2ecf20Sopenharmony_ci	unsigned int i;
41388c2ecf20Sopenharmony_ci	int cleaned_count = 0;
41398c2ecf20Sopenharmony_ci	bool cleaned = false;
41408c2ecf20Sopenharmony_ci	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
41418c2ecf20Sopenharmony_ci
41428c2ecf20Sopenharmony_ci	i = rx_ring->next_to_clean;
41438c2ecf20Sopenharmony_ci	rx_desc = E1000_RX_DESC(*rx_ring, i);
41448c2ecf20Sopenharmony_ci	buffer_info = &rx_ring->buffer_info[i];
41458c2ecf20Sopenharmony_ci
41468c2ecf20Sopenharmony_ci	while (rx_desc->status & E1000_RXD_STAT_DD) {
41478c2ecf20Sopenharmony_ci		struct sk_buff *skb;
41488c2ecf20Sopenharmony_ci		u8 status;
41498c2ecf20Sopenharmony_ci
41508c2ecf20Sopenharmony_ci		if (*work_done >= work_to_do)
41518c2ecf20Sopenharmony_ci			break;
41528c2ecf20Sopenharmony_ci		(*work_done)++;
41538c2ecf20Sopenharmony_ci		dma_rmb(); /* read descriptor and rx_buffer_info after status DD */
41548c2ecf20Sopenharmony_ci
41558c2ecf20Sopenharmony_ci		status = rx_desc->status;
41568c2ecf20Sopenharmony_ci
41578c2ecf20Sopenharmony_ci		if (++i == rx_ring->count)
41588c2ecf20Sopenharmony_ci			i = 0;
41598c2ecf20Sopenharmony_ci
41608c2ecf20Sopenharmony_ci		next_rxd = E1000_RX_DESC(*rx_ring, i);
41618c2ecf20Sopenharmony_ci		prefetch(next_rxd);
41628c2ecf20Sopenharmony_ci
41638c2ecf20Sopenharmony_ci		next_buffer = &rx_ring->buffer_info[i];
41648c2ecf20Sopenharmony_ci
41658c2ecf20Sopenharmony_ci		cleaned = true;
41668c2ecf20Sopenharmony_ci		cleaned_count++;
41678c2ecf20Sopenharmony_ci		dma_unmap_page(&pdev->dev, buffer_info->dma,
41688c2ecf20Sopenharmony_ci			       adapter->rx_buffer_len, DMA_FROM_DEVICE);
41698c2ecf20Sopenharmony_ci		buffer_info->dma = 0;
41708c2ecf20Sopenharmony_ci
41718c2ecf20Sopenharmony_ci		length = le16_to_cpu(rx_desc->length);
41728c2ecf20Sopenharmony_ci
41738c2ecf20Sopenharmony_ci		/* errors is only valid for DD + EOP descriptors */
41748c2ecf20Sopenharmony_ci		if (unlikely((status & E1000_RXD_STAT_EOP) &&
41758c2ecf20Sopenharmony_ci		    (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
41768c2ecf20Sopenharmony_ci			u8 *mapped = page_address(buffer_info->rxbuf.page);
41778c2ecf20Sopenharmony_ci
41788c2ecf20Sopenharmony_ci			if (e1000_tbi_should_accept(adapter, status,
41798c2ecf20Sopenharmony_ci						    rx_desc->errors,
41808c2ecf20Sopenharmony_ci						    length, mapped)) {
41818c2ecf20Sopenharmony_ci				length--;
41828c2ecf20Sopenharmony_ci			} else if (netdev->features & NETIF_F_RXALL) {
41838c2ecf20Sopenharmony_ci				goto process_skb;
41848c2ecf20Sopenharmony_ci			} else {
41858c2ecf20Sopenharmony_ci				/* an error means any chain goes out the window
41868c2ecf20Sopenharmony_ci				 * too
41878c2ecf20Sopenharmony_ci				 */
41888c2ecf20Sopenharmony_ci				dev_kfree_skb(rx_ring->rx_skb_top);
41898c2ecf20Sopenharmony_ci				rx_ring->rx_skb_top = NULL;
41908c2ecf20Sopenharmony_ci				goto next_desc;
41918c2ecf20Sopenharmony_ci			}
41928c2ecf20Sopenharmony_ci		}
41938c2ecf20Sopenharmony_ci
41948c2ecf20Sopenharmony_ci#define rxtop rx_ring->rx_skb_top
41958c2ecf20Sopenharmony_ciprocess_skb:
41968c2ecf20Sopenharmony_ci		if (!(status & E1000_RXD_STAT_EOP)) {
41978c2ecf20Sopenharmony_ci			/* this descriptor is only the beginning (or middle) */
41988c2ecf20Sopenharmony_ci			if (!rxtop) {
41998c2ecf20Sopenharmony_ci				/* this is the beginning of a chain */
42008c2ecf20Sopenharmony_ci				rxtop = napi_get_frags(&adapter->napi);
42018c2ecf20Sopenharmony_ci				if (!rxtop)
42028c2ecf20Sopenharmony_ci					break;
42038c2ecf20Sopenharmony_ci
42048c2ecf20Sopenharmony_ci				skb_fill_page_desc(rxtop, 0,
42058c2ecf20Sopenharmony_ci						   buffer_info->rxbuf.page,
42068c2ecf20Sopenharmony_ci						   0, length);
42078c2ecf20Sopenharmony_ci			} else {
42088c2ecf20Sopenharmony_ci				/* this is the middle of a chain */
42098c2ecf20Sopenharmony_ci				skb_fill_page_desc(rxtop,
42108c2ecf20Sopenharmony_ci				    skb_shinfo(rxtop)->nr_frags,
42118c2ecf20Sopenharmony_ci				    buffer_info->rxbuf.page, 0, length);
42128c2ecf20Sopenharmony_ci			}
42138c2ecf20Sopenharmony_ci			e1000_consume_page(buffer_info, rxtop, length);
42148c2ecf20Sopenharmony_ci			goto next_desc;
42158c2ecf20Sopenharmony_ci		} else {
42168c2ecf20Sopenharmony_ci			if (rxtop) {
42178c2ecf20Sopenharmony_ci				/* end of the chain */
42188c2ecf20Sopenharmony_ci				skb_fill_page_desc(rxtop,
42198c2ecf20Sopenharmony_ci				    skb_shinfo(rxtop)->nr_frags,
42208c2ecf20Sopenharmony_ci				    buffer_info->rxbuf.page, 0, length);
42218c2ecf20Sopenharmony_ci				skb = rxtop;
42228c2ecf20Sopenharmony_ci				rxtop = NULL;
42238c2ecf20Sopenharmony_ci				e1000_consume_page(buffer_info, skb, length);
42248c2ecf20Sopenharmony_ci			} else {
42258c2ecf20Sopenharmony_ci				struct page *p;
42268c2ecf20Sopenharmony_ci				/* no chain, got EOP, this buf is the packet
42278c2ecf20Sopenharmony_ci				 * copybreak to save the put_page/alloc_page
42288c2ecf20Sopenharmony_ci				 */
42298c2ecf20Sopenharmony_ci				p = buffer_info->rxbuf.page;
42308c2ecf20Sopenharmony_ci				if (length <= copybreak) {
42318c2ecf20Sopenharmony_ci					u8 *vaddr;
42328c2ecf20Sopenharmony_ci
42338c2ecf20Sopenharmony_ci					if (likely(!(netdev->features & NETIF_F_RXFCS)))
42348c2ecf20Sopenharmony_ci						length -= 4;
42358c2ecf20Sopenharmony_ci					skb = e1000_alloc_rx_skb(adapter,
42368c2ecf20Sopenharmony_ci								 length);
42378c2ecf20Sopenharmony_ci					if (!skb)
42388c2ecf20Sopenharmony_ci						break;
42398c2ecf20Sopenharmony_ci
42408c2ecf20Sopenharmony_ci					vaddr = kmap_atomic(p);
42418c2ecf20Sopenharmony_ci					memcpy(skb_tail_pointer(skb), vaddr,
42428c2ecf20Sopenharmony_ci					       length);
42438c2ecf20Sopenharmony_ci					kunmap_atomic(vaddr);
42448c2ecf20Sopenharmony_ci					/* re-use the page, so don't erase
42458c2ecf20Sopenharmony_ci					 * buffer_info->rxbuf.page
42468c2ecf20Sopenharmony_ci					 */
42478c2ecf20Sopenharmony_ci					skb_put(skb, length);
42488c2ecf20Sopenharmony_ci					e1000_rx_checksum(adapter,
42498c2ecf20Sopenharmony_ci							  status | rx_desc->errors << 24,
42508c2ecf20Sopenharmony_ci							  le16_to_cpu(rx_desc->csum), skb);
42518c2ecf20Sopenharmony_ci
42528c2ecf20Sopenharmony_ci					total_rx_bytes += skb->len;
42538c2ecf20Sopenharmony_ci					total_rx_packets++;
42548c2ecf20Sopenharmony_ci
42558c2ecf20Sopenharmony_ci					e1000_receive_skb(adapter, status,
42568c2ecf20Sopenharmony_ci							  rx_desc->special, skb);
42578c2ecf20Sopenharmony_ci					goto next_desc;
42588c2ecf20Sopenharmony_ci				} else {
42598c2ecf20Sopenharmony_ci					skb = napi_get_frags(&adapter->napi);
42608c2ecf20Sopenharmony_ci					if (!skb) {
42618c2ecf20Sopenharmony_ci						adapter->alloc_rx_buff_failed++;
42628c2ecf20Sopenharmony_ci						break;
42638c2ecf20Sopenharmony_ci					}
42648c2ecf20Sopenharmony_ci					skb_fill_page_desc(skb, 0, p, 0,
42658c2ecf20Sopenharmony_ci							   length);
42668c2ecf20Sopenharmony_ci					e1000_consume_page(buffer_info, skb,
42678c2ecf20Sopenharmony_ci							   length);
42688c2ecf20Sopenharmony_ci				}
42698c2ecf20Sopenharmony_ci			}
42708c2ecf20Sopenharmony_ci		}
42718c2ecf20Sopenharmony_ci
42728c2ecf20Sopenharmony_ci		/* Receive Checksum Offload XXX recompute due to CRC strip? */
42738c2ecf20Sopenharmony_ci		e1000_rx_checksum(adapter,
42748c2ecf20Sopenharmony_ci				  (u32)(status) |
42758c2ecf20Sopenharmony_ci				  ((u32)(rx_desc->errors) << 24),
42768c2ecf20Sopenharmony_ci				  le16_to_cpu(rx_desc->csum), skb);
42778c2ecf20Sopenharmony_ci
42788c2ecf20Sopenharmony_ci		total_rx_bytes += (skb->len - 4); /* don't count FCS */
42798c2ecf20Sopenharmony_ci		if (likely(!(netdev->features & NETIF_F_RXFCS)))
42808c2ecf20Sopenharmony_ci			pskb_trim(skb, skb->len - 4);
42818c2ecf20Sopenharmony_ci		total_rx_packets++;
42828c2ecf20Sopenharmony_ci
42838c2ecf20Sopenharmony_ci		if (status & E1000_RXD_STAT_VP) {
42848c2ecf20Sopenharmony_ci			__le16 vlan = rx_desc->special;
42858c2ecf20Sopenharmony_ci			u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
42868c2ecf20Sopenharmony_ci
42878c2ecf20Sopenharmony_ci			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
42888c2ecf20Sopenharmony_ci		}
42898c2ecf20Sopenharmony_ci
42908c2ecf20Sopenharmony_ci		napi_gro_frags(&adapter->napi);
42918c2ecf20Sopenharmony_ci
42928c2ecf20Sopenharmony_cinext_desc:
42938c2ecf20Sopenharmony_ci		rx_desc->status = 0;
42948c2ecf20Sopenharmony_ci
42958c2ecf20Sopenharmony_ci		/* return some buffers to hardware, one at a time is too slow */
42968c2ecf20Sopenharmony_ci		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
42978c2ecf20Sopenharmony_ci			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
42988c2ecf20Sopenharmony_ci			cleaned_count = 0;
42998c2ecf20Sopenharmony_ci		}
43008c2ecf20Sopenharmony_ci
43018c2ecf20Sopenharmony_ci		/* use prefetched values */
43028c2ecf20Sopenharmony_ci		rx_desc = next_rxd;
43038c2ecf20Sopenharmony_ci		buffer_info = next_buffer;
43048c2ecf20Sopenharmony_ci	}
43058c2ecf20Sopenharmony_ci	rx_ring->next_to_clean = i;
43068c2ecf20Sopenharmony_ci
43078c2ecf20Sopenharmony_ci	cleaned_count = E1000_DESC_UNUSED(rx_ring);
43088c2ecf20Sopenharmony_ci	if (cleaned_count)
43098c2ecf20Sopenharmony_ci		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
43108c2ecf20Sopenharmony_ci
43118c2ecf20Sopenharmony_ci	adapter->total_rx_packets += total_rx_packets;
43128c2ecf20Sopenharmony_ci	adapter->total_rx_bytes += total_rx_bytes;
43138c2ecf20Sopenharmony_ci	netdev->stats.rx_bytes += total_rx_bytes;
43148c2ecf20Sopenharmony_ci	netdev->stats.rx_packets += total_rx_packets;
43158c2ecf20Sopenharmony_ci	return cleaned;
43168c2ecf20Sopenharmony_ci}
43178c2ecf20Sopenharmony_ci
43188c2ecf20Sopenharmony_ci/* this should improve performance for small packets with large amounts
43198c2ecf20Sopenharmony_ci * of reassembly being done in the stack
43208c2ecf20Sopenharmony_ci */
43218c2ecf20Sopenharmony_cistatic struct sk_buff *e1000_copybreak(struct e1000_adapter *adapter,
43228c2ecf20Sopenharmony_ci				       struct e1000_rx_buffer *buffer_info,
43238c2ecf20Sopenharmony_ci				       u32 length, const void *data)
43248c2ecf20Sopenharmony_ci{
43258c2ecf20Sopenharmony_ci	struct sk_buff *skb;
43268c2ecf20Sopenharmony_ci
43278c2ecf20Sopenharmony_ci	if (length > copybreak)
43288c2ecf20Sopenharmony_ci		return NULL;
43298c2ecf20Sopenharmony_ci
43308c2ecf20Sopenharmony_ci	skb = e1000_alloc_rx_skb(adapter, length);
43318c2ecf20Sopenharmony_ci	if (!skb)
43328c2ecf20Sopenharmony_ci		return NULL;
43338c2ecf20Sopenharmony_ci
43348c2ecf20Sopenharmony_ci	dma_sync_single_for_cpu(&adapter->pdev->dev, buffer_info->dma,
43358c2ecf20Sopenharmony_ci				length, DMA_FROM_DEVICE);
43368c2ecf20Sopenharmony_ci
43378c2ecf20Sopenharmony_ci	skb_put_data(skb, data, length);
43388c2ecf20Sopenharmony_ci
43398c2ecf20Sopenharmony_ci	return skb;
43408c2ecf20Sopenharmony_ci}
43418c2ecf20Sopenharmony_ci
43428c2ecf20Sopenharmony_ci/**
43438c2ecf20Sopenharmony_ci * e1000_clean_rx_irq - Send received data up the network stack; legacy
43448c2ecf20Sopenharmony_ci * @adapter: board private structure
43458c2ecf20Sopenharmony_ci * @rx_ring: ring to clean
43468c2ecf20Sopenharmony_ci * @work_done: amount of napi work completed this call
43478c2ecf20Sopenharmony_ci * @work_to_do: max amount of work allowed for this call to do
43488c2ecf20Sopenharmony_ci */
43498c2ecf20Sopenharmony_cistatic bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
43508c2ecf20Sopenharmony_ci			       struct e1000_rx_ring *rx_ring,
43518c2ecf20Sopenharmony_ci			       int *work_done, int work_to_do)
43528c2ecf20Sopenharmony_ci{
43538c2ecf20Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
43548c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
43558c2ecf20Sopenharmony_ci	struct e1000_rx_desc *rx_desc, *next_rxd;
43568c2ecf20Sopenharmony_ci	struct e1000_rx_buffer *buffer_info, *next_buffer;
43578c2ecf20Sopenharmony_ci	u32 length;
43588c2ecf20Sopenharmony_ci	unsigned int i;
43598c2ecf20Sopenharmony_ci	int cleaned_count = 0;
43608c2ecf20Sopenharmony_ci	bool cleaned = false;
43618c2ecf20Sopenharmony_ci	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
43628c2ecf20Sopenharmony_ci
43638c2ecf20Sopenharmony_ci	i = rx_ring->next_to_clean;
43648c2ecf20Sopenharmony_ci	rx_desc = E1000_RX_DESC(*rx_ring, i);
43658c2ecf20Sopenharmony_ci	buffer_info = &rx_ring->buffer_info[i];
43668c2ecf20Sopenharmony_ci
43678c2ecf20Sopenharmony_ci	while (rx_desc->status & E1000_RXD_STAT_DD) {
43688c2ecf20Sopenharmony_ci		struct sk_buff *skb;
43698c2ecf20Sopenharmony_ci		u8 *data;
43708c2ecf20Sopenharmony_ci		u8 status;
43718c2ecf20Sopenharmony_ci
43728c2ecf20Sopenharmony_ci		if (*work_done >= work_to_do)
43738c2ecf20Sopenharmony_ci			break;
43748c2ecf20Sopenharmony_ci		(*work_done)++;
43758c2ecf20Sopenharmony_ci		dma_rmb(); /* read descriptor and rx_buffer_info after status DD */
43768c2ecf20Sopenharmony_ci
43778c2ecf20Sopenharmony_ci		status = rx_desc->status;
43788c2ecf20Sopenharmony_ci		length = le16_to_cpu(rx_desc->length);
43798c2ecf20Sopenharmony_ci
43808c2ecf20Sopenharmony_ci		data = buffer_info->rxbuf.data;
43818c2ecf20Sopenharmony_ci		prefetch(data);
43828c2ecf20Sopenharmony_ci		skb = e1000_copybreak(adapter, buffer_info, length, data);
43838c2ecf20Sopenharmony_ci		if (!skb) {
43848c2ecf20Sopenharmony_ci			unsigned int frag_len = e1000_frag_len(adapter);
43858c2ecf20Sopenharmony_ci
43868c2ecf20Sopenharmony_ci			skb = build_skb(data - E1000_HEADROOM, frag_len);
43878c2ecf20Sopenharmony_ci			if (!skb) {
43888c2ecf20Sopenharmony_ci				adapter->alloc_rx_buff_failed++;
43898c2ecf20Sopenharmony_ci				break;
43908c2ecf20Sopenharmony_ci			}
43918c2ecf20Sopenharmony_ci
43928c2ecf20Sopenharmony_ci			skb_reserve(skb, E1000_HEADROOM);
43938c2ecf20Sopenharmony_ci			dma_unmap_single(&pdev->dev, buffer_info->dma,
43948c2ecf20Sopenharmony_ci					 adapter->rx_buffer_len,
43958c2ecf20Sopenharmony_ci					 DMA_FROM_DEVICE);
43968c2ecf20Sopenharmony_ci			buffer_info->dma = 0;
43978c2ecf20Sopenharmony_ci			buffer_info->rxbuf.data = NULL;
43988c2ecf20Sopenharmony_ci		}
43998c2ecf20Sopenharmony_ci
44008c2ecf20Sopenharmony_ci		if (++i == rx_ring->count)
44018c2ecf20Sopenharmony_ci			i = 0;
44028c2ecf20Sopenharmony_ci
44038c2ecf20Sopenharmony_ci		next_rxd = E1000_RX_DESC(*rx_ring, i);
44048c2ecf20Sopenharmony_ci		prefetch(next_rxd);
44058c2ecf20Sopenharmony_ci
44068c2ecf20Sopenharmony_ci		next_buffer = &rx_ring->buffer_info[i];
44078c2ecf20Sopenharmony_ci
44088c2ecf20Sopenharmony_ci		cleaned = true;
44098c2ecf20Sopenharmony_ci		cleaned_count++;
44108c2ecf20Sopenharmony_ci
44118c2ecf20Sopenharmony_ci		/* !EOP means multiple descriptors were used to store a single
44128c2ecf20Sopenharmony_ci		 * packet, if thats the case we need to toss it.  In fact, we
44138c2ecf20Sopenharmony_ci		 * to toss every packet with the EOP bit clear and the next
44148c2ecf20Sopenharmony_ci		 * frame that _does_ have the EOP bit set, as it is by
44158c2ecf20Sopenharmony_ci		 * definition only a frame fragment
44168c2ecf20Sopenharmony_ci		 */
44178c2ecf20Sopenharmony_ci		if (unlikely(!(status & E1000_RXD_STAT_EOP)))
44188c2ecf20Sopenharmony_ci			adapter->discarding = true;
44198c2ecf20Sopenharmony_ci
44208c2ecf20Sopenharmony_ci		if (adapter->discarding) {
44218c2ecf20Sopenharmony_ci			/* All receives must fit into a single buffer */
44228c2ecf20Sopenharmony_ci			netdev_dbg(netdev, "Receive packet consumed multiple buffers\n");
44238c2ecf20Sopenharmony_ci			dev_kfree_skb(skb);
44248c2ecf20Sopenharmony_ci			if (status & E1000_RXD_STAT_EOP)
44258c2ecf20Sopenharmony_ci				adapter->discarding = false;
44268c2ecf20Sopenharmony_ci			goto next_desc;
44278c2ecf20Sopenharmony_ci		}
44288c2ecf20Sopenharmony_ci
44298c2ecf20Sopenharmony_ci		if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
44308c2ecf20Sopenharmony_ci			if (e1000_tbi_should_accept(adapter, status,
44318c2ecf20Sopenharmony_ci						    rx_desc->errors,
44328c2ecf20Sopenharmony_ci						    length, data)) {
44338c2ecf20Sopenharmony_ci				length--;
44348c2ecf20Sopenharmony_ci			} else if (netdev->features & NETIF_F_RXALL) {
44358c2ecf20Sopenharmony_ci				goto process_skb;
44368c2ecf20Sopenharmony_ci			} else {
44378c2ecf20Sopenharmony_ci				dev_kfree_skb(skb);
44388c2ecf20Sopenharmony_ci				goto next_desc;
44398c2ecf20Sopenharmony_ci			}
44408c2ecf20Sopenharmony_ci		}
44418c2ecf20Sopenharmony_ci
44428c2ecf20Sopenharmony_ciprocess_skb:
44438c2ecf20Sopenharmony_ci		total_rx_bytes += (length - 4); /* don't count FCS */
44448c2ecf20Sopenharmony_ci		total_rx_packets++;
44458c2ecf20Sopenharmony_ci
44468c2ecf20Sopenharmony_ci		if (likely(!(netdev->features & NETIF_F_RXFCS)))
44478c2ecf20Sopenharmony_ci			/* adjust length to remove Ethernet CRC, this must be
44488c2ecf20Sopenharmony_ci			 * done after the TBI_ACCEPT workaround above
44498c2ecf20Sopenharmony_ci			 */
44508c2ecf20Sopenharmony_ci			length -= 4;
44518c2ecf20Sopenharmony_ci
44528c2ecf20Sopenharmony_ci		if (buffer_info->rxbuf.data == NULL)
44538c2ecf20Sopenharmony_ci			skb_put(skb, length);
44548c2ecf20Sopenharmony_ci		else /* copybreak skb */
44558c2ecf20Sopenharmony_ci			skb_trim(skb, length);
44568c2ecf20Sopenharmony_ci
44578c2ecf20Sopenharmony_ci		/* Receive Checksum Offload */
44588c2ecf20Sopenharmony_ci		e1000_rx_checksum(adapter,
44598c2ecf20Sopenharmony_ci				  (u32)(status) |
44608c2ecf20Sopenharmony_ci				  ((u32)(rx_desc->errors) << 24),
44618c2ecf20Sopenharmony_ci				  le16_to_cpu(rx_desc->csum), skb);
44628c2ecf20Sopenharmony_ci
44638c2ecf20Sopenharmony_ci		e1000_receive_skb(adapter, status, rx_desc->special, skb);
44648c2ecf20Sopenharmony_ci
44658c2ecf20Sopenharmony_cinext_desc:
44668c2ecf20Sopenharmony_ci		rx_desc->status = 0;
44678c2ecf20Sopenharmony_ci
44688c2ecf20Sopenharmony_ci		/* return some buffers to hardware, one at a time is too slow */
44698c2ecf20Sopenharmony_ci		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
44708c2ecf20Sopenharmony_ci			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
44718c2ecf20Sopenharmony_ci			cleaned_count = 0;
44728c2ecf20Sopenharmony_ci		}
44738c2ecf20Sopenharmony_ci
44748c2ecf20Sopenharmony_ci		/* use prefetched values */
44758c2ecf20Sopenharmony_ci		rx_desc = next_rxd;
44768c2ecf20Sopenharmony_ci		buffer_info = next_buffer;
44778c2ecf20Sopenharmony_ci	}
44788c2ecf20Sopenharmony_ci	rx_ring->next_to_clean = i;
44798c2ecf20Sopenharmony_ci
44808c2ecf20Sopenharmony_ci	cleaned_count = E1000_DESC_UNUSED(rx_ring);
44818c2ecf20Sopenharmony_ci	if (cleaned_count)
44828c2ecf20Sopenharmony_ci		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
44838c2ecf20Sopenharmony_ci
44848c2ecf20Sopenharmony_ci	adapter->total_rx_packets += total_rx_packets;
44858c2ecf20Sopenharmony_ci	adapter->total_rx_bytes += total_rx_bytes;
44868c2ecf20Sopenharmony_ci	netdev->stats.rx_bytes += total_rx_bytes;
44878c2ecf20Sopenharmony_ci	netdev->stats.rx_packets += total_rx_packets;
44888c2ecf20Sopenharmony_ci	return cleaned;
44898c2ecf20Sopenharmony_ci}
44908c2ecf20Sopenharmony_ci
44918c2ecf20Sopenharmony_ci/**
44928c2ecf20Sopenharmony_ci * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers
44938c2ecf20Sopenharmony_ci * @adapter: address of board private structure
44948c2ecf20Sopenharmony_ci * @rx_ring: pointer to receive ring structure
44958c2ecf20Sopenharmony_ci * @cleaned_count: number of buffers to allocate this pass
44968c2ecf20Sopenharmony_ci **/
44978c2ecf20Sopenharmony_cistatic void
44988c2ecf20Sopenharmony_cie1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
44998c2ecf20Sopenharmony_ci			     struct e1000_rx_ring *rx_ring, int cleaned_count)
45008c2ecf20Sopenharmony_ci{
45018c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
45028c2ecf20Sopenharmony_ci	struct e1000_rx_desc *rx_desc;
45038c2ecf20Sopenharmony_ci	struct e1000_rx_buffer *buffer_info;
45048c2ecf20Sopenharmony_ci	unsigned int i;
45058c2ecf20Sopenharmony_ci
45068c2ecf20Sopenharmony_ci	i = rx_ring->next_to_use;
45078c2ecf20Sopenharmony_ci	buffer_info = &rx_ring->buffer_info[i];
45088c2ecf20Sopenharmony_ci
45098c2ecf20Sopenharmony_ci	while (cleaned_count--) {
45108c2ecf20Sopenharmony_ci		/* allocate a new page if necessary */
45118c2ecf20Sopenharmony_ci		if (!buffer_info->rxbuf.page) {
45128c2ecf20Sopenharmony_ci			buffer_info->rxbuf.page = alloc_page(GFP_ATOMIC);
45138c2ecf20Sopenharmony_ci			if (unlikely(!buffer_info->rxbuf.page)) {
45148c2ecf20Sopenharmony_ci				adapter->alloc_rx_buff_failed++;
45158c2ecf20Sopenharmony_ci				break;
45168c2ecf20Sopenharmony_ci			}
45178c2ecf20Sopenharmony_ci		}
45188c2ecf20Sopenharmony_ci
45198c2ecf20Sopenharmony_ci		if (!buffer_info->dma) {
45208c2ecf20Sopenharmony_ci			buffer_info->dma = dma_map_page(&pdev->dev,
45218c2ecf20Sopenharmony_ci							buffer_info->rxbuf.page, 0,
45228c2ecf20Sopenharmony_ci							adapter->rx_buffer_len,
45238c2ecf20Sopenharmony_ci							DMA_FROM_DEVICE);
45248c2ecf20Sopenharmony_ci			if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
45258c2ecf20Sopenharmony_ci				put_page(buffer_info->rxbuf.page);
45268c2ecf20Sopenharmony_ci				buffer_info->rxbuf.page = NULL;
45278c2ecf20Sopenharmony_ci				buffer_info->dma = 0;
45288c2ecf20Sopenharmony_ci				adapter->alloc_rx_buff_failed++;
45298c2ecf20Sopenharmony_ci				break;
45308c2ecf20Sopenharmony_ci			}
45318c2ecf20Sopenharmony_ci		}
45328c2ecf20Sopenharmony_ci
45338c2ecf20Sopenharmony_ci		rx_desc = E1000_RX_DESC(*rx_ring, i);
45348c2ecf20Sopenharmony_ci		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
45358c2ecf20Sopenharmony_ci
45368c2ecf20Sopenharmony_ci		if (unlikely(++i == rx_ring->count))
45378c2ecf20Sopenharmony_ci			i = 0;
45388c2ecf20Sopenharmony_ci		buffer_info = &rx_ring->buffer_info[i];
45398c2ecf20Sopenharmony_ci	}
45408c2ecf20Sopenharmony_ci
45418c2ecf20Sopenharmony_ci	if (likely(rx_ring->next_to_use != i)) {
45428c2ecf20Sopenharmony_ci		rx_ring->next_to_use = i;
45438c2ecf20Sopenharmony_ci		if (unlikely(i-- == 0))
45448c2ecf20Sopenharmony_ci			i = (rx_ring->count - 1);
45458c2ecf20Sopenharmony_ci
45468c2ecf20Sopenharmony_ci		/* Force memory writes to complete before letting h/w
45478c2ecf20Sopenharmony_ci		 * know there are new descriptors to fetch.  (Only
45488c2ecf20Sopenharmony_ci		 * applicable for weak-ordered memory model archs,
45498c2ecf20Sopenharmony_ci		 * such as IA-64).
45508c2ecf20Sopenharmony_ci		 */
45518c2ecf20Sopenharmony_ci		dma_wmb();
45528c2ecf20Sopenharmony_ci		writel(i, adapter->hw.hw_addr + rx_ring->rdt);
45538c2ecf20Sopenharmony_ci	}
45548c2ecf20Sopenharmony_ci}
45558c2ecf20Sopenharmony_ci
45568c2ecf20Sopenharmony_ci/**
45578c2ecf20Sopenharmony_ci * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
45588c2ecf20Sopenharmony_ci * @adapter: address of board private structure
45598c2ecf20Sopenharmony_ci * @rx_ring: pointer to ring struct
45608c2ecf20Sopenharmony_ci * @cleaned_count: number of new Rx buffers to try to allocate
45618c2ecf20Sopenharmony_ci **/
45628c2ecf20Sopenharmony_cistatic void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
45638c2ecf20Sopenharmony_ci				   struct e1000_rx_ring *rx_ring,
45648c2ecf20Sopenharmony_ci				   int cleaned_count)
45658c2ecf20Sopenharmony_ci{
45668c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
45678c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
45688c2ecf20Sopenharmony_ci	struct e1000_rx_desc *rx_desc;
45698c2ecf20Sopenharmony_ci	struct e1000_rx_buffer *buffer_info;
45708c2ecf20Sopenharmony_ci	unsigned int i;
45718c2ecf20Sopenharmony_ci	unsigned int bufsz = adapter->rx_buffer_len;
45728c2ecf20Sopenharmony_ci
45738c2ecf20Sopenharmony_ci	i = rx_ring->next_to_use;
45748c2ecf20Sopenharmony_ci	buffer_info = &rx_ring->buffer_info[i];
45758c2ecf20Sopenharmony_ci
45768c2ecf20Sopenharmony_ci	while (cleaned_count--) {
45778c2ecf20Sopenharmony_ci		void *data;
45788c2ecf20Sopenharmony_ci
45798c2ecf20Sopenharmony_ci		if (buffer_info->rxbuf.data)
45808c2ecf20Sopenharmony_ci			goto skip;
45818c2ecf20Sopenharmony_ci
45828c2ecf20Sopenharmony_ci		data = e1000_alloc_frag(adapter);
45838c2ecf20Sopenharmony_ci		if (!data) {
45848c2ecf20Sopenharmony_ci			/* Better luck next round */
45858c2ecf20Sopenharmony_ci			adapter->alloc_rx_buff_failed++;
45868c2ecf20Sopenharmony_ci			break;
45878c2ecf20Sopenharmony_ci		}
45888c2ecf20Sopenharmony_ci
45898c2ecf20Sopenharmony_ci		/* Fix for errata 23, can't cross 64kB boundary */
45908c2ecf20Sopenharmony_ci		if (!e1000_check_64k_bound(adapter, data, bufsz)) {
45918c2ecf20Sopenharmony_ci			void *olddata = data;
45928c2ecf20Sopenharmony_ci			e_err(rx_err, "skb align check failed: %u bytes at "
45938c2ecf20Sopenharmony_ci			      "%p\n", bufsz, data);
45948c2ecf20Sopenharmony_ci			/* Try again, without freeing the previous */
45958c2ecf20Sopenharmony_ci			data = e1000_alloc_frag(adapter);
45968c2ecf20Sopenharmony_ci			/* Failed allocation, critical failure */
45978c2ecf20Sopenharmony_ci			if (!data) {
45988c2ecf20Sopenharmony_ci				skb_free_frag(olddata);
45998c2ecf20Sopenharmony_ci				adapter->alloc_rx_buff_failed++;
46008c2ecf20Sopenharmony_ci				break;
46018c2ecf20Sopenharmony_ci			}
46028c2ecf20Sopenharmony_ci
46038c2ecf20Sopenharmony_ci			if (!e1000_check_64k_bound(adapter, data, bufsz)) {
46048c2ecf20Sopenharmony_ci				/* give up */
46058c2ecf20Sopenharmony_ci				skb_free_frag(data);
46068c2ecf20Sopenharmony_ci				skb_free_frag(olddata);
46078c2ecf20Sopenharmony_ci				adapter->alloc_rx_buff_failed++;
46088c2ecf20Sopenharmony_ci				break;
46098c2ecf20Sopenharmony_ci			}
46108c2ecf20Sopenharmony_ci
46118c2ecf20Sopenharmony_ci			/* Use new allocation */
46128c2ecf20Sopenharmony_ci			skb_free_frag(olddata);
46138c2ecf20Sopenharmony_ci		}
46148c2ecf20Sopenharmony_ci		buffer_info->dma = dma_map_single(&pdev->dev,
46158c2ecf20Sopenharmony_ci						  data,
46168c2ecf20Sopenharmony_ci						  adapter->rx_buffer_len,
46178c2ecf20Sopenharmony_ci						  DMA_FROM_DEVICE);
46188c2ecf20Sopenharmony_ci		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
46198c2ecf20Sopenharmony_ci			skb_free_frag(data);
46208c2ecf20Sopenharmony_ci			buffer_info->dma = 0;
46218c2ecf20Sopenharmony_ci			adapter->alloc_rx_buff_failed++;
46228c2ecf20Sopenharmony_ci			break;
46238c2ecf20Sopenharmony_ci		}
46248c2ecf20Sopenharmony_ci
46258c2ecf20Sopenharmony_ci		/* XXX if it was allocated cleanly it will never map to a
46268c2ecf20Sopenharmony_ci		 * boundary crossing
46278c2ecf20Sopenharmony_ci		 */
46288c2ecf20Sopenharmony_ci
46298c2ecf20Sopenharmony_ci		/* Fix for errata 23, can't cross 64kB boundary */
46308c2ecf20Sopenharmony_ci		if (!e1000_check_64k_bound(adapter,
46318c2ecf20Sopenharmony_ci					(void *)(unsigned long)buffer_info->dma,
46328c2ecf20Sopenharmony_ci					adapter->rx_buffer_len)) {
46338c2ecf20Sopenharmony_ci			e_err(rx_err, "dma align check failed: %u bytes at "
46348c2ecf20Sopenharmony_ci			      "%p\n", adapter->rx_buffer_len,
46358c2ecf20Sopenharmony_ci			      (void *)(unsigned long)buffer_info->dma);
46368c2ecf20Sopenharmony_ci
46378c2ecf20Sopenharmony_ci			dma_unmap_single(&pdev->dev, buffer_info->dma,
46388c2ecf20Sopenharmony_ci					 adapter->rx_buffer_len,
46398c2ecf20Sopenharmony_ci					 DMA_FROM_DEVICE);
46408c2ecf20Sopenharmony_ci
46418c2ecf20Sopenharmony_ci			skb_free_frag(data);
46428c2ecf20Sopenharmony_ci			buffer_info->rxbuf.data = NULL;
46438c2ecf20Sopenharmony_ci			buffer_info->dma = 0;
46448c2ecf20Sopenharmony_ci
46458c2ecf20Sopenharmony_ci			adapter->alloc_rx_buff_failed++;
46468c2ecf20Sopenharmony_ci			break;
46478c2ecf20Sopenharmony_ci		}
46488c2ecf20Sopenharmony_ci		buffer_info->rxbuf.data = data;
46498c2ecf20Sopenharmony_ci skip:
46508c2ecf20Sopenharmony_ci		rx_desc = E1000_RX_DESC(*rx_ring, i);
46518c2ecf20Sopenharmony_ci		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
46528c2ecf20Sopenharmony_ci
46538c2ecf20Sopenharmony_ci		if (unlikely(++i == rx_ring->count))
46548c2ecf20Sopenharmony_ci			i = 0;
46558c2ecf20Sopenharmony_ci		buffer_info = &rx_ring->buffer_info[i];
46568c2ecf20Sopenharmony_ci	}
46578c2ecf20Sopenharmony_ci
46588c2ecf20Sopenharmony_ci	if (likely(rx_ring->next_to_use != i)) {
46598c2ecf20Sopenharmony_ci		rx_ring->next_to_use = i;
46608c2ecf20Sopenharmony_ci		if (unlikely(i-- == 0))
46618c2ecf20Sopenharmony_ci			i = (rx_ring->count - 1);
46628c2ecf20Sopenharmony_ci
46638c2ecf20Sopenharmony_ci		/* Force memory writes to complete before letting h/w
46648c2ecf20Sopenharmony_ci		 * know there are new descriptors to fetch.  (Only
46658c2ecf20Sopenharmony_ci		 * applicable for weak-ordered memory model archs,
46668c2ecf20Sopenharmony_ci		 * such as IA-64).
46678c2ecf20Sopenharmony_ci		 */
46688c2ecf20Sopenharmony_ci		dma_wmb();
46698c2ecf20Sopenharmony_ci		writel(i, hw->hw_addr + rx_ring->rdt);
46708c2ecf20Sopenharmony_ci	}
46718c2ecf20Sopenharmony_ci}
46728c2ecf20Sopenharmony_ci
46738c2ecf20Sopenharmony_ci/**
46748c2ecf20Sopenharmony_ci * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers.
46758c2ecf20Sopenharmony_ci * @adapter: address of board private structure
46768c2ecf20Sopenharmony_ci **/
46778c2ecf20Sopenharmony_cistatic void e1000_smartspeed(struct e1000_adapter *adapter)
46788c2ecf20Sopenharmony_ci{
46798c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
46808c2ecf20Sopenharmony_ci	u16 phy_status;
46818c2ecf20Sopenharmony_ci	u16 phy_ctrl;
46828c2ecf20Sopenharmony_ci
46838c2ecf20Sopenharmony_ci	if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg ||
46848c2ecf20Sopenharmony_ci	   !(hw->autoneg_advertised & ADVERTISE_1000_FULL))
46858c2ecf20Sopenharmony_ci		return;
46868c2ecf20Sopenharmony_ci
46878c2ecf20Sopenharmony_ci	if (adapter->smartspeed == 0) {
46888c2ecf20Sopenharmony_ci		/* If Master/Slave config fault is asserted twice,
46898c2ecf20Sopenharmony_ci		 * we assume back-to-back
46908c2ecf20Sopenharmony_ci		 */
46918c2ecf20Sopenharmony_ci		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
46928c2ecf20Sopenharmony_ci		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT))
46938c2ecf20Sopenharmony_ci			return;
46948c2ecf20Sopenharmony_ci		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
46958c2ecf20Sopenharmony_ci		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT))
46968c2ecf20Sopenharmony_ci			return;
46978c2ecf20Sopenharmony_ci		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
46988c2ecf20Sopenharmony_ci		if (phy_ctrl & CR_1000T_MS_ENABLE) {
46998c2ecf20Sopenharmony_ci			phy_ctrl &= ~CR_1000T_MS_ENABLE;
47008c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, PHY_1000T_CTRL,
47018c2ecf20Sopenharmony_ci					    phy_ctrl);
47028c2ecf20Sopenharmony_ci			adapter->smartspeed++;
47038c2ecf20Sopenharmony_ci			if (!e1000_phy_setup_autoneg(hw) &&
47048c2ecf20Sopenharmony_ci			   !e1000_read_phy_reg(hw, PHY_CTRL,
47058c2ecf20Sopenharmony_ci					       &phy_ctrl)) {
47068c2ecf20Sopenharmony_ci				phy_ctrl |= (MII_CR_AUTO_NEG_EN |
47078c2ecf20Sopenharmony_ci					     MII_CR_RESTART_AUTO_NEG);
47088c2ecf20Sopenharmony_ci				e1000_write_phy_reg(hw, PHY_CTRL,
47098c2ecf20Sopenharmony_ci						    phy_ctrl);
47108c2ecf20Sopenharmony_ci			}
47118c2ecf20Sopenharmony_ci		}
47128c2ecf20Sopenharmony_ci		return;
47138c2ecf20Sopenharmony_ci	} else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
47148c2ecf20Sopenharmony_ci		/* If still no link, perhaps using 2/3 pair cable */
47158c2ecf20Sopenharmony_ci		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
47168c2ecf20Sopenharmony_ci		phy_ctrl |= CR_1000T_MS_ENABLE;
47178c2ecf20Sopenharmony_ci		e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl);
47188c2ecf20Sopenharmony_ci		if (!e1000_phy_setup_autoneg(hw) &&
47198c2ecf20Sopenharmony_ci		   !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) {
47208c2ecf20Sopenharmony_ci			phy_ctrl |= (MII_CR_AUTO_NEG_EN |
47218c2ecf20Sopenharmony_ci				     MII_CR_RESTART_AUTO_NEG);
47228c2ecf20Sopenharmony_ci			e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl);
47238c2ecf20Sopenharmony_ci		}
47248c2ecf20Sopenharmony_ci	}
47258c2ecf20Sopenharmony_ci	/* Restart process after E1000_SMARTSPEED_MAX iterations */
47268c2ecf20Sopenharmony_ci	if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
47278c2ecf20Sopenharmony_ci		adapter->smartspeed = 0;
47288c2ecf20Sopenharmony_ci}
47298c2ecf20Sopenharmony_ci
47308c2ecf20Sopenharmony_ci/**
47318c2ecf20Sopenharmony_ci * e1000_ioctl - handle ioctl calls
47328c2ecf20Sopenharmony_ci * @netdev: pointer to our netdev
47338c2ecf20Sopenharmony_ci * @ifr: pointer to interface request structure
47348c2ecf20Sopenharmony_ci * @cmd: ioctl data
47358c2ecf20Sopenharmony_ci **/
47368c2ecf20Sopenharmony_cistatic int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
47378c2ecf20Sopenharmony_ci{
47388c2ecf20Sopenharmony_ci	switch (cmd) {
47398c2ecf20Sopenharmony_ci	case SIOCGMIIPHY:
47408c2ecf20Sopenharmony_ci	case SIOCGMIIREG:
47418c2ecf20Sopenharmony_ci	case SIOCSMIIREG:
47428c2ecf20Sopenharmony_ci		return e1000_mii_ioctl(netdev, ifr, cmd);
47438c2ecf20Sopenharmony_ci	default:
47448c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
47458c2ecf20Sopenharmony_ci	}
47468c2ecf20Sopenharmony_ci}
47478c2ecf20Sopenharmony_ci
47488c2ecf20Sopenharmony_ci/**
47498c2ecf20Sopenharmony_ci * e1000_mii_ioctl -
47508c2ecf20Sopenharmony_ci * @netdev: pointer to our netdev
47518c2ecf20Sopenharmony_ci * @ifr: pointer to interface request structure
47528c2ecf20Sopenharmony_ci * @cmd: ioctl data
47538c2ecf20Sopenharmony_ci **/
47548c2ecf20Sopenharmony_cistatic int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
47558c2ecf20Sopenharmony_ci			   int cmd)
47568c2ecf20Sopenharmony_ci{
47578c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
47588c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
47598c2ecf20Sopenharmony_ci	struct mii_ioctl_data *data = if_mii(ifr);
47608c2ecf20Sopenharmony_ci	int retval;
47618c2ecf20Sopenharmony_ci	u16 mii_reg;
47628c2ecf20Sopenharmony_ci	unsigned long flags;
47638c2ecf20Sopenharmony_ci
47648c2ecf20Sopenharmony_ci	if (hw->media_type != e1000_media_type_copper)
47658c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
47668c2ecf20Sopenharmony_ci
47678c2ecf20Sopenharmony_ci	switch (cmd) {
47688c2ecf20Sopenharmony_ci	case SIOCGMIIPHY:
47698c2ecf20Sopenharmony_ci		data->phy_id = hw->phy_addr;
47708c2ecf20Sopenharmony_ci		break;
47718c2ecf20Sopenharmony_ci	case SIOCGMIIREG:
47728c2ecf20Sopenharmony_ci		spin_lock_irqsave(&adapter->stats_lock, flags);
47738c2ecf20Sopenharmony_ci		if (e1000_read_phy_reg(hw, data->reg_num & 0x1F,
47748c2ecf20Sopenharmony_ci				   &data->val_out)) {
47758c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&adapter->stats_lock, flags);
47768c2ecf20Sopenharmony_ci			return -EIO;
47778c2ecf20Sopenharmony_ci		}
47788c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&adapter->stats_lock, flags);
47798c2ecf20Sopenharmony_ci		break;
47808c2ecf20Sopenharmony_ci	case SIOCSMIIREG:
47818c2ecf20Sopenharmony_ci		if (data->reg_num & ~(0x1F))
47828c2ecf20Sopenharmony_ci			return -EFAULT;
47838c2ecf20Sopenharmony_ci		mii_reg = data->val_in;
47848c2ecf20Sopenharmony_ci		spin_lock_irqsave(&adapter->stats_lock, flags);
47858c2ecf20Sopenharmony_ci		if (e1000_write_phy_reg(hw, data->reg_num,
47868c2ecf20Sopenharmony_ci					mii_reg)) {
47878c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&adapter->stats_lock, flags);
47888c2ecf20Sopenharmony_ci			return -EIO;
47898c2ecf20Sopenharmony_ci		}
47908c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&adapter->stats_lock, flags);
47918c2ecf20Sopenharmony_ci		if (hw->media_type == e1000_media_type_copper) {
47928c2ecf20Sopenharmony_ci			switch (data->reg_num) {
47938c2ecf20Sopenharmony_ci			case PHY_CTRL:
47948c2ecf20Sopenharmony_ci				if (mii_reg & MII_CR_POWER_DOWN)
47958c2ecf20Sopenharmony_ci					break;
47968c2ecf20Sopenharmony_ci				if (mii_reg & MII_CR_AUTO_NEG_EN) {
47978c2ecf20Sopenharmony_ci					hw->autoneg = 1;
47988c2ecf20Sopenharmony_ci					hw->autoneg_advertised = 0x2F;
47998c2ecf20Sopenharmony_ci				} else {
48008c2ecf20Sopenharmony_ci					u32 speed;
48018c2ecf20Sopenharmony_ci					if (mii_reg & 0x40)
48028c2ecf20Sopenharmony_ci						speed = SPEED_1000;
48038c2ecf20Sopenharmony_ci					else if (mii_reg & 0x2000)
48048c2ecf20Sopenharmony_ci						speed = SPEED_100;
48058c2ecf20Sopenharmony_ci					else
48068c2ecf20Sopenharmony_ci						speed = SPEED_10;
48078c2ecf20Sopenharmony_ci					retval = e1000_set_spd_dplx(
48088c2ecf20Sopenharmony_ci						adapter, speed,
48098c2ecf20Sopenharmony_ci						((mii_reg & 0x100)
48108c2ecf20Sopenharmony_ci						 ? DUPLEX_FULL :
48118c2ecf20Sopenharmony_ci						 DUPLEX_HALF));
48128c2ecf20Sopenharmony_ci					if (retval)
48138c2ecf20Sopenharmony_ci						return retval;
48148c2ecf20Sopenharmony_ci				}
48158c2ecf20Sopenharmony_ci				if (netif_running(adapter->netdev))
48168c2ecf20Sopenharmony_ci					e1000_reinit_locked(adapter);
48178c2ecf20Sopenharmony_ci				else
48188c2ecf20Sopenharmony_ci					e1000_reset(adapter);
48198c2ecf20Sopenharmony_ci				break;
48208c2ecf20Sopenharmony_ci			case M88E1000_PHY_SPEC_CTRL:
48218c2ecf20Sopenharmony_ci			case M88E1000_EXT_PHY_SPEC_CTRL:
48228c2ecf20Sopenharmony_ci				if (e1000_phy_reset(hw))
48238c2ecf20Sopenharmony_ci					return -EIO;
48248c2ecf20Sopenharmony_ci				break;
48258c2ecf20Sopenharmony_ci			}
48268c2ecf20Sopenharmony_ci		} else {
48278c2ecf20Sopenharmony_ci			switch (data->reg_num) {
48288c2ecf20Sopenharmony_ci			case PHY_CTRL:
48298c2ecf20Sopenharmony_ci				if (mii_reg & MII_CR_POWER_DOWN)
48308c2ecf20Sopenharmony_ci					break;
48318c2ecf20Sopenharmony_ci				if (netif_running(adapter->netdev))
48328c2ecf20Sopenharmony_ci					e1000_reinit_locked(adapter);
48338c2ecf20Sopenharmony_ci				else
48348c2ecf20Sopenharmony_ci					e1000_reset(adapter);
48358c2ecf20Sopenharmony_ci				break;
48368c2ecf20Sopenharmony_ci			}
48378c2ecf20Sopenharmony_ci		}
48388c2ecf20Sopenharmony_ci		break;
48398c2ecf20Sopenharmony_ci	default:
48408c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
48418c2ecf20Sopenharmony_ci	}
48428c2ecf20Sopenharmony_ci	return E1000_SUCCESS;
48438c2ecf20Sopenharmony_ci}
48448c2ecf20Sopenharmony_ci
48458c2ecf20Sopenharmony_civoid e1000_pci_set_mwi(struct e1000_hw *hw)
48468c2ecf20Sopenharmony_ci{
48478c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = hw->back;
48488c2ecf20Sopenharmony_ci	int ret_val = pci_set_mwi(adapter->pdev);
48498c2ecf20Sopenharmony_ci
48508c2ecf20Sopenharmony_ci	if (ret_val)
48518c2ecf20Sopenharmony_ci		e_err(probe, "Error in setting MWI\n");
48528c2ecf20Sopenharmony_ci}
48538c2ecf20Sopenharmony_ci
48548c2ecf20Sopenharmony_civoid e1000_pci_clear_mwi(struct e1000_hw *hw)
48558c2ecf20Sopenharmony_ci{
48568c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = hw->back;
48578c2ecf20Sopenharmony_ci
48588c2ecf20Sopenharmony_ci	pci_clear_mwi(adapter->pdev);
48598c2ecf20Sopenharmony_ci}
48608c2ecf20Sopenharmony_ci
48618c2ecf20Sopenharmony_ciint e1000_pcix_get_mmrbc(struct e1000_hw *hw)
48628c2ecf20Sopenharmony_ci{
48638c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = hw->back;
48648c2ecf20Sopenharmony_ci	return pcix_get_mmrbc(adapter->pdev);
48658c2ecf20Sopenharmony_ci}
48668c2ecf20Sopenharmony_ci
48678c2ecf20Sopenharmony_civoid e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
48688c2ecf20Sopenharmony_ci{
48698c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = hw->back;
48708c2ecf20Sopenharmony_ci	pcix_set_mmrbc(adapter->pdev, mmrbc);
48718c2ecf20Sopenharmony_ci}
48728c2ecf20Sopenharmony_ci
48738c2ecf20Sopenharmony_civoid e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
48748c2ecf20Sopenharmony_ci{
48758c2ecf20Sopenharmony_ci	outl(value, port);
48768c2ecf20Sopenharmony_ci}
48778c2ecf20Sopenharmony_ci
48788c2ecf20Sopenharmony_cistatic bool e1000_vlan_used(struct e1000_adapter *adapter)
48798c2ecf20Sopenharmony_ci{
48808c2ecf20Sopenharmony_ci	u16 vid;
48818c2ecf20Sopenharmony_ci
48828c2ecf20Sopenharmony_ci	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
48838c2ecf20Sopenharmony_ci		return true;
48848c2ecf20Sopenharmony_ci	return false;
48858c2ecf20Sopenharmony_ci}
48868c2ecf20Sopenharmony_ci
48878c2ecf20Sopenharmony_cistatic void __e1000_vlan_mode(struct e1000_adapter *adapter,
48888c2ecf20Sopenharmony_ci			      netdev_features_t features)
48898c2ecf20Sopenharmony_ci{
48908c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
48918c2ecf20Sopenharmony_ci	u32 ctrl;
48928c2ecf20Sopenharmony_ci
48938c2ecf20Sopenharmony_ci	ctrl = er32(CTRL);
48948c2ecf20Sopenharmony_ci	if (features & NETIF_F_HW_VLAN_CTAG_RX) {
48958c2ecf20Sopenharmony_ci		/* enable VLAN tag insert/strip */
48968c2ecf20Sopenharmony_ci		ctrl |= E1000_CTRL_VME;
48978c2ecf20Sopenharmony_ci	} else {
48988c2ecf20Sopenharmony_ci		/* disable VLAN tag insert/strip */
48998c2ecf20Sopenharmony_ci		ctrl &= ~E1000_CTRL_VME;
49008c2ecf20Sopenharmony_ci	}
49018c2ecf20Sopenharmony_ci	ew32(CTRL, ctrl);
49028c2ecf20Sopenharmony_ci}
49038c2ecf20Sopenharmony_cistatic void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
49048c2ecf20Sopenharmony_ci				     bool filter_on)
49058c2ecf20Sopenharmony_ci{
49068c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
49078c2ecf20Sopenharmony_ci	u32 rctl;
49088c2ecf20Sopenharmony_ci
49098c2ecf20Sopenharmony_ci	if (!test_bit(__E1000_DOWN, &adapter->flags))
49108c2ecf20Sopenharmony_ci		e1000_irq_disable(adapter);
49118c2ecf20Sopenharmony_ci
49128c2ecf20Sopenharmony_ci	__e1000_vlan_mode(adapter, adapter->netdev->features);
49138c2ecf20Sopenharmony_ci	if (filter_on) {
49148c2ecf20Sopenharmony_ci		/* enable VLAN receive filtering */
49158c2ecf20Sopenharmony_ci		rctl = er32(RCTL);
49168c2ecf20Sopenharmony_ci		rctl &= ~E1000_RCTL_CFIEN;
49178c2ecf20Sopenharmony_ci		if (!(adapter->netdev->flags & IFF_PROMISC))
49188c2ecf20Sopenharmony_ci			rctl |= E1000_RCTL_VFE;
49198c2ecf20Sopenharmony_ci		ew32(RCTL, rctl);
49208c2ecf20Sopenharmony_ci		e1000_update_mng_vlan(adapter);
49218c2ecf20Sopenharmony_ci	} else {
49228c2ecf20Sopenharmony_ci		/* disable VLAN receive filtering */
49238c2ecf20Sopenharmony_ci		rctl = er32(RCTL);
49248c2ecf20Sopenharmony_ci		rctl &= ~E1000_RCTL_VFE;
49258c2ecf20Sopenharmony_ci		ew32(RCTL, rctl);
49268c2ecf20Sopenharmony_ci	}
49278c2ecf20Sopenharmony_ci
49288c2ecf20Sopenharmony_ci	if (!test_bit(__E1000_DOWN, &adapter->flags))
49298c2ecf20Sopenharmony_ci		e1000_irq_enable(adapter);
49308c2ecf20Sopenharmony_ci}
49318c2ecf20Sopenharmony_ci
49328c2ecf20Sopenharmony_cistatic void e1000_vlan_mode(struct net_device *netdev,
49338c2ecf20Sopenharmony_ci			    netdev_features_t features)
49348c2ecf20Sopenharmony_ci{
49358c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
49368c2ecf20Sopenharmony_ci
49378c2ecf20Sopenharmony_ci	if (!test_bit(__E1000_DOWN, &adapter->flags))
49388c2ecf20Sopenharmony_ci		e1000_irq_disable(adapter);
49398c2ecf20Sopenharmony_ci
49408c2ecf20Sopenharmony_ci	__e1000_vlan_mode(adapter, features);
49418c2ecf20Sopenharmony_ci
49428c2ecf20Sopenharmony_ci	if (!test_bit(__E1000_DOWN, &adapter->flags))
49438c2ecf20Sopenharmony_ci		e1000_irq_enable(adapter);
49448c2ecf20Sopenharmony_ci}
49458c2ecf20Sopenharmony_ci
49468c2ecf20Sopenharmony_cistatic int e1000_vlan_rx_add_vid(struct net_device *netdev,
49478c2ecf20Sopenharmony_ci				 __be16 proto, u16 vid)
49488c2ecf20Sopenharmony_ci{
49498c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
49508c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
49518c2ecf20Sopenharmony_ci	u32 vfta, index;
49528c2ecf20Sopenharmony_ci
49538c2ecf20Sopenharmony_ci	if ((hw->mng_cookie.status &
49548c2ecf20Sopenharmony_ci	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
49558c2ecf20Sopenharmony_ci	    (vid == adapter->mng_vlan_id))
49568c2ecf20Sopenharmony_ci		return 0;
49578c2ecf20Sopenharmony_ci
49588c2ecf20Sopenharmony_ci	if (!e1000_vlan_used(adapter))
49598c2ecf20Sopenharmony_ci		e1000_vlan_filter_on_off(adapter, true);
49608c2ecf20Sopenharmony_ci
49618c2ecf20Sopenharmony_ci	/* add VID to filter table */
49628c2ecf20Sopenharmony_ci	index = (vid >> 5) & 0x7F;
49638c2ecf20Sopenharmony_ci	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
49648c2ecf20Sopenharmony_ci	vfta |= (1 << (vid & 0x1F));
49658c2ecf20Sopenharmony_ci	e1000_write_vfta(hw, index, vfta);
49668c2ecf20Sopenharmony_ci
49678c2ecf20Sopenharmony_ci	set_bit(vid, adapter->active_vlans);
49688c2ecf20Sopenharmony_ci
49698c2ecf20Sopenharmony_ci	return 0;
49708c2ecf20Sopenharmony_ci}
49718c2ecf20Sopenharmony_ci
49728c2ecf20Sopenharmony_cistatic int e1000_vlan_rx_kill_vid(struct net_device *netdev,
49738c2ecf20Sopenharmony_ci				  __be16 proto, u16 vid)
49748c2ecf20Sopenharmony_ci{
49758c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
49768c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
49778c2ecf20Sopenharmony_ci	u32 vfta, index;
49788c2ecf20Sopenharmony_ci
49798c2ecf20Sopenharmony_ci	if (!test_bit(__E1000_DOWN, &adapter->flags))
49808c2ecf20Sopenharmony_ci		e1000_irq_disable(adapter);
49818c2ecf20Sopenharmony_ci	if (!test_bit(__E1000_DOWN, &adapter->flags))
49828c2ecf20Sopenharmony_ci		e1000_irq_enable(adapter);
49838c2ecf20Sopenharmony_ci
49848c2ecf20Sopenharmony_ci	/* remove VID from filter table */
49858c2ecf20Sopenharmony_ci	index = (vid >> 5) & 0x7F;
49868c2ecf20Sopenharmony_ci	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
49878c2ecf20Sopenharmony_ci	vfta &= ~(1 << (vid & 0x1F));
49888c2ecf20Sopenharmony_ci	e1000_write_vfta(hw, index, vfta);
49898c2ecf20Sopenharmony_ci
49908c2ecf20Sopenharmony_ci	clear_bit(vid, adapter->active_vlans);
49918c2ecf20Sopenharmony_ci
49928c2ecf20Sopenharmony_ci	if (!e1000_vlan_used(adapter))
49938c2ecf20Sopenharmony_ci		e1000_vlan_filter_on_off(adapter, false);
49948c2ecf20Sopenharmony_ci
49958c2ecf20Sopenharmony_ci	return 0;
49968c2ecf20Sopenharmony_ci}
49978c2ecf20Sopenharmony_ci
49988c2ecf20Sopenharmony_cistatic void e1000_restore_vlan(struct e1000_adapter *adapter)
49998c2ecf20Sopenharmony_ci{
50008c2ecf20Sopenharmony_ci	u16 vid;
50018c2ecf20Sopenharmony_ci
50028c2ecf20Sopenharmony_ci	if (!e1000_vlan_used(adapter))
50038c2ecf20Sopenharmony_ci		return;
50048c2ecf20Sopenharmony_ci
50058c2ecf20Sopenharmony_ci	e1000_vlan_filter_on_off(adapter, true);
50068c2ecf20Sopenharmony_ci	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
50078c2ecf20Sopenharmony_ci		e1000_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid);
50088c2ecf20Sopenharmony_ci}
50098c2ecf20Sopenharmony_ci
50108c2ecf20Sopenharmony_ciint e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
50118c2ecf20Sopenharmony_ci{
50128c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
50138c2ecf20Sopenharmony_ci
50148c2ecf20Sopenharmony_ci	hw->autoneg = 0;
50158c2ecf20Sopenharmony_ci
50168c2ecf20Sopenharmony_ci	/* Make sure dplx is at most 1 bit and lsb of speed is not set
50178c2ecf20Sopenharmony_ci	 * for the switch() below to work
50188c2ecf20Sopenharmony_ci	 */
50198c2ecf20Sopenharmony_ci	if ((spd & 1) || (dplx & ~1))
50208c2ecf20Sopenharmony_ci		goto err_inval;
50218c2ecf20Sopenharmony_ci
50228c2ecf20Sopenharmony_ci	/* Fiber NICs only allow 1000 gbps Full duplex */
50238c2ecf20Sopenharmony_ci	if ((hw->media_type == e1000_media_type_fiber) &&
50248c2ecf20Sopenharmony_ci	    spd != SPEED_1000 &&
50258c2ecf20Sopenharmony_ci	    dplx != DUPLEX_FULL)
50268c2ecf20Sopenharmony_ci		goto err_inval;
50278c2ecf20Sopenharmony_ci
50288c2ecf20Sopenharmony_ci	switch (spd + dplx) {
50298c2ecf20Sopenharmony_ci	case SPEED_10 + DUPLEX_HALF:
50308c2ecf20Sopenharmony_ci		hw->forced_speed_duplex = e1000_10_half;
50318c2ecf20Sopenharmony_ci		break;
50328c2ecf20Sopenharmony_ci	case SPEED_10 + DUPLEX_FULL:
50338c2ecf20Sopenharmony_ci		hw->forced_speed_duplex = e1000_10_full;
50348c2ecf20Sopenharmony_ci		break;
50358c2ecf20Sopenharmony_ci	case SPEED_100 + DUPLEX_HALF:
50368c2ecf20Sopenharmony_ci		hw->forced_speed_duplex = e1000_100_half;
50378c2ecf20Sopenharmony_ci		break;
50388c2ecf20Sopenharmony_ci	case SPEED_100 + DUPLEX_FULL:
50398c2ecf20Sopenharmony_ci		hw->forced_speed_duplex = e1000_100_full;
50408c2ecf20Sopenharmony_ci		break;
50418c2ecf20Sopenharmony_ci	case SPEED_1000 + DUPLEX_FULL:
50428c2ecf20Sopenharmony_ci		hw->autoneg = 1;
50438c2ecf20Sopenharmony_ci		hw->autoneg_advertised = ADVERTISE_1000_FULL;
50448c2ecf20Sopenharmony_ci		break;
50458c2ecf20Sopenharmony_ci	case SPEED_1000 + DUPLEX_HALF: /* not supported */
50468c2ecf20Sopenharmony_ci	default:
50478c2ecf20Sopenharmony_ci		goto err_inval;
50488c2ecf20Sopenharmony_ci	}
50498c2ecf20Sopenharmony_ci
50508c2ecf20Sopenharmony_ci	/* clear MDI, MDI(-X) override is only allowed when autoneg enabled */
50518c2ecf20Sopenharmony_ci	hw->mdix = AUTO_ALL_MODES;
50528c2ecf20Sopenharmony_ci
50538c2ecf20Sopenharmony_ci	return 0;
50548c2ecf20Sopenharmony_ci
50558c2ecf20Sopenharmony_cierr_inval:
50568c2ecf20Sopenharmony_ci	e_err(probe, "Unsupported Speed/Duplex configuration\n");
50578c2ecf20Sopenharmony_ci	return -EINVAL;
50588c2ecf20Sopenharmony_ci}
50598c2ecf20Sopenharmony_ci
50608c2ecf20Sopenharmony_cistatic int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
50618c2ecf20Sopenharmony_ci{
50628c2ecf20Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
50638c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
50648c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
50658c2ecf20Sopenharmony_ci	u32 ctrl, ctrl_ext, rctl, status;
50668c2ecf20Sopenharmony_ci	u32 wufc = adapter->wol;
50678c2ecf20Sopenharmony_ci
50688c2ecf20Sopenharmony_ci	netif_device_detach(netdev);
50698c2ecf20Sopenharmony_ci
50708c2ecf20Sopenharmony_ci	if (netif_running(netdev)) {
50718c2ecf20Sopenharmony_ci		int count = E1000_CHECK_RESET_COUNT;
50728c2ecf20Sopenharmony_ci
50738c2ecf20Sopenharmony_ci		while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
50748c2ecf20Sopenharmony_ci			usleep_range(10000, 20000);
50758c2ecf20Sopenharmony_ci
50768c2ecf20Sopenharmony_ci		WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
50778c2ecf20Sopenharmony_ci		e1000_down(adapter);
50788c2ecf20Sopenharmony_ci	}
50798c2ecf20Sopenharmony_ci
50808c2ecf20Sopenharmony_ci	status = er32(STATUS);
50818c2ecf20Sopenharmony_ci	if (status & E1000_STATUS_LU)
50828c2ecf20Sopenharmony_ci		wufc &= ~E1000_WUFC_LNKC;
50838c2ecf20Sopenharmony_ci
50848c2ecf20Sopenharmony_ci	if (wufc) {
50858c2ecf20Sopenharmony_ci		e1000_setup_rctl(adapter);
50868c2ecf20Sopenharmony_ci		e1000_set_rx_mode(netdev);
50878c2ecf20Sopenharmony_ci
50888c2ecf20Sopenharmony_ci		rctl = er32(RCTL);
50898c2ecf20Sopenharmony_ci
50908c2ecf20Sopenharmony_ci		/* turn on all-multi mode if wake on multicast is enabled */
50918c2ecf20Sopenharmony_ci		if (wufc & E1000_WUFC_MC)
50928c2ecf20Sopenharmony_ci			rctl |= E1000_RCTL_MPE;
50938c2ecf20Sopenharmony_ci
50948c2ecf20Sopenharmony_ci		/* enable receives in the hardware */
50958c2ecf20Sopenharmony_ci		ew32(RCTL, rctl | E1000_RCTL_EN);
50968c2ecf20Sopenharmony_ci
50978c2ecf20Sopenharmony_ci		if (hw->mac_type >= e1000_82540) {
50988c2ecf20Sopenharmony_ci			ctrl = er32(CTRL);
50998c2ecf20Sopenharmony_ci			/* advertise wake from D3Cold */
51008c2ecf20Sopenharmony_ci			#define E1000_CTRL_ADVD3WUC 0x00100000
51018c2ecf20Sopenharmony_ci			/* phy power management enable */
51028c2ecf20Sopenharmony_ci			#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
51038c2ecf20Sopenharmony_ci			ctrl |= E1000_CTRL_ADVD3WUC |
51048c2ecf20Sopenharmony_ci				E1000_CTRL_EN_PHY_PWR_MGMT;
51058c2ecf20Sopenharmony_ci			ew32(CTRL, ctrl);
51068c2ecf20Sopenharmony_ci		}
51078c2ecf20Sopenharmony_ci
51088c2ecf20Sopenharmony_ci		if (hw->media_type == e1000_media_type_fiber ||
51098c2ecf20Sopenharmony_ci		    hw->media_type == e1000_media_type_internal_serdes) {
51108c2ecf20Sopenharmony_ci			/* keep the laser running in D3 */
51118c2ecf20Sopenharmony_ci			ctrl_ext = er32(CTRL_EXT);
51128c2ecf20Sopenharmony_ci			ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
51138c2ecf20Sopenharmony_ci			ew32(CTRL_EXT, ctrl_ext);
51148c2ecf20Sopenharmony_ci		}
51158c2ecf20Sopenharmony_ci
51168c2ecf20Sopenharmony_ci		ew32(WUC, E1000_WUC_PME_EN);
51178c2ecf20Sopenharmony_ci		ew32(WUFC, wufc);
51188c2ecf20Sopenharmony_ci	} else {
51198c2ecf20Sopenharmony_ci		ew32(WUC, 0);
51208c2ecf20Sopenharmony_ci		ew32(WUFC, 0);
51218c2ecf20Sopenharmony_ci	}
51228c2ecf20Sopenharmony_ci
51238c2ecf20Sopenharmony_ci	e1000_release_manageability(adapter);
51248c2ecf20Sopenharmony_ci
51258c2ecf20Sopenharmony_ci	*enable_wake = !!wufc;
51268c2ecf20Sopenharmony_ci
51278c2ecf20Sopenharmony_ci	/* make sure adapter isn't asleep if manageability is enabled */
51288c2ecf20Sopenharmony_ci	if (adapter->en_mng_pt)
51298c2ecf20Sopenharmony_ci		*enable_wake = true;
51308c2ecf20Sopenharmony_ci
51318c2ecf20Sopenharmony_ci	if (netif_running(netdev))
51328c2ecf20Sopenharmony_ci		e1000_free_irq(adapter);
51338c2ecf20Sopenharmony_ci
51348c2ecf20Sopenharmony_ci	if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags))
51358c2ecf20Sopenharmony_ci		pci_disable_device(pdev);
51368c2ecf20Sopenharmony_ci
51378c2ecf20Sopenharmony_ci	return 0;
51388c2ecf20Sopenharmony_ci}
51398c2ecf20Sopenharmony_ci
51408c2ecf20Sopenharmony_cistatic int __maybe_unused e1000_suspend(struct device *dev)
51418c2ecf20Sopenharmony_ci{
51428c2ecf20Sopenharmony_ci	int retval;
51438c2ecf20Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev);
51448c2ecf20Sopenharmony_ci	bool wake;
51458c2ecf20Sopenharmony_ci
51468c2ecf20Sopenharmony_ci	retval = __e1000_shutdown(pdev, &wake);
51478c2ecf20Sopenharmony_ci	device_set_wakeup_enable(dev, wake);
51488c2ecf20Sopenharmony_ci
51498c2ecf20Sopenharmony_ci	return retval;
51508c2ecf20Sopenharmony_ci}
51518c2ecf20Sopenharmony_ci
51528c2ecf20Sopenharmony_cistatic int __maybe_unused e1000_resume(struct device *dev)
51538c2ecf20Sopenharmony_ci{
51548c2ecf20Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev);
51558c2ecf20Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
51568c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
51578c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
51588c2ecf20Sopenharmony_ci	u32 err;
51598c2ecf20Sopenharmony_ci
51608c2ecf20Sopenharmony_ci	if (adapter->need_ioport)
51618c2ecf20Sopenharmony_ci		err = pci_enable_device(pdev);
51628c2ecf20Sopenharmony_ci	else
51638c2ecf20Sopenharmony_ci		err = pci_enable_device_mem(pdev);
51648c2ecf20Sopenharmony_ci	if (err) {
51658c2ecf20Sopenharmony_ci		pr_err("Cannot enable PCI device from suspend\n");
51668c2ecf20Sopenharmony_ci		return err;
51678c2ecf20Sopenharmony_ci	}
51688c2ecf20Sopenharmony_ci
51698c2ecf20Sopenharmony_ci	/* flush memory to make sure state is correct */
51708c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
51718c2ecf20Sopenharmony_ci	clear_bit(__E1000_DISABLED, &adapter->flags);
51728c2ecf20Sopenharmony_ci	pci_set_master(pdev);
51738c2ecf20Sopenharmony_ci
51748c2ecf20Sopenharmony_ci	pci_enable_wake(pdev, PCI_D3hot, 0);
51758c2ecf20Sopenharmony_ci	pci_enable_wake(pdev, PCI_D3cold, 0);
51768c2ecf20Sopenharmony_ci
51778c2ecf20Sopenharmony_ci	if (netif_running(netdev)) {
51788c2ecf20Sopenharmony_ci		err = e1000_request_irq(adapter);
51798c2ecf20Sopenharmony_ci		if (err)
51808c2ecf20Sopenharmony_ci			return err;
51818c2ecf20Sopenharmony_ci	}
51828c2ecf20Sopenharmony_ci
51838c2ecf20Sopenharmony_ci	e1000_power_up_phy(adapter);
51848c2ecf20Sopenharmony_ci	e1000_reset(adapter);
51858c2ecf20Sopenharmony_ci	ew32(WUS, ~0);
51868c2ecf20Sopenharmony_ci
51878c2ecf20Sopenharmony_ci	e1000_init_manageability(adapter);
51888c2ecf20Sopenharmony_ci
51898c2ecf20Sopenharmony_ci	if (netif_running(netdev))
51908c2ecf20Sopenharmony_ci		e1000_up(adapter);
51918c2ecf20Sopenharmony_ci
51928c2ecf20Sopenharmony_ci	netif_device_attach(netdev);
51938c2ecf20Sopenharmony_ci
51948c2ecf20Sopenharmony_ci	return 0;
51958c2ecf20Sopenharmony_ci}
51968c2ecf20Sopenharmony_ci
51978c2ecf20Sopenharmony_cistatic void e1000_shutdown(struct pci_dev *pdev)
51988c2ecf20Sopenharmony_ci{
51998c2ecf20Sopenharmony_ci	bool wake;
52008c2ecf20Sopenharmony_ci
52018c2ecf20Sopenharmony_ci	__e1000_shutdown(pdev, &wake);
52028c2ecf20Sopenharmony_ci
52038c2ecf20Sopenharmony_ci	if (system_state == SYSTEM_POWER_OFF) {
52048c2ecf20Sopenharmony_ci		pci_wake_from_d3(pdev, wake);
52058c2ecf20Sopenharmony_ci		pci_set_power_state(pdev, PCI_D3hot);
52068c2ecf20Sopenharmony_ci	}
52078c2ecf20Sopenharmony_ci}
52088c2ecf20Sopenharmony_ci
52098c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
52108c2ecf20Sopenharmony_ci/* Polling 'interrupt' - used by things like netconsole to send skbs
52118c2ecf20Sopenharmony_ci * without having to re-enable interrupts. It's not called while
52128c2ecf20Sopenharmony_ci * the interrupt routine is executing.
52138c2ecf20Sopenharmony_ci */
52148c2ecf20Sopenharmony_cistatic void e1000_netpoll(struct net_device *netdev)
52158c2ecf20Sopenharmony_ci{
52168c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
52178c2ecf20Sopenharmony_ci
52188c2ecf20Sopenharmony_ci	if (disable_hardirq(adapter->pdev->irq))
52198c2ecf20Sopenharmony_ci		e1000_intr(adapter->pdev->irq, netdev);
52208c2ecf20Sopenharmony_ci	enable_irq(adapter->pdev->irq);
52218c2ecf20Sopenharmony_ci}
52228c2ecf20Sopenharmony_ci#endif
52238c2ecf20Sopenharmony_ci
52248c2ecf20Sopenharmony_ci/**
52258c2ecf20Sopenharmony_ci * e1000_io_error_detected - called when PCI error is detected
52268c2ecf20Sopenharmony_ci * @pdev: Pointer to PCI device
52278c2ecf20Sopenharmony_ci * @state: The current pci connection state
52288c2ecf20Sopenharmony_ci *
52298c2ecf20Sopenharmony_ci * This function is called after a PCI bus error affecting
52308c2ecf20Sopenharmony_ci * this device has been detected.
52318c2ecf20Sopenharmony_ci */
52328c2ecf20Sopenharmony_cistatic pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
52338c2ecf20Sopenharmony_ci						pci_channel_state_t state)
52348c2ecf20Sopenharmony_ci{
52358c2ecf20Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
52368c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
52378c2ecf20Sopenharmony_ci
52388c2ecf20Sopenharmony_ci	netif_device_detach(netdev);
52398c2ecf20Sopenharmony_ci
52408c2ecf20Sopenharmony_ci	if (state == pci_channel_io_perm_failure)
52418c2ecf20Sopenharmony_ci		return PCI_ERS_RESULT_DISCONNECT;
52428c2ecf20Sopenharmony_ci
52438c2ecf20Sopenharmony_ci	if (netif_running(netdev))
52448c2ecf20Sopenharmony_ci		e1000_down(adapter);
52458c2ecf20Sopenharmony_ci
52468c2ecf20Sopenharmony_ci	if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags))
52478c2ecf20Sopenharmony_ci		pci_disable_device(pdev);
52488c2ecf20Sopenharmony_ci
52498c2ecf20Sopenharmony_ci	/* Request a slot slot reset. */
52508c2ecf20Sopenharmony_ci	return PCI_ERS_RESULT_NEED_RESET;
52518c2ecf20Sopenharmony_ci}
52528c2ecf20Sopenharmony_ci
52538c2ecf20Sopenharmony_ci/**
52548c2ecf20Sopenharmony_ci * e1000_io_slot_reset - called after the pci bus has been reset.
52558c2ecf20Sopenharmony_ci * @pdev: Pointer to PCI device
52568c2ecf20Sopenharmony_ci *
52578c2ecf20Sopenharmony_ci * Restart the card from scratch, as if from a cold-boot. Implementation
52588c2ecf20Sopenharmony_ci * resembles the first-half of the e1000_resume routine.
52598c2ecf20Sopenharmony_ci */
52608c2ecf20Sopenharmony_cistatic pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
52618c2ecf20Sopenharmony_ci{
52628c2ecf20Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
52638c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
52648c2ecf20Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
52658c2ecf20Sopenharmony_ci	int err;
52668c2ecf20Sopenharmony_ci
52678c2ecf20Sopenharmony_ci	if (adapter->need_ioport)
52688c2ecf20Sopenharmony_ci		err = pci_enable_device(pdev);
52698c2ecf20Sopenharmony_ci	else
52708c2ecf20Sopenharmony_ci		err = pci_enable_device_mem(pdev);
52718c2ecf20Sopenharmony_ci	if (err) {
52728c2ecf20Sopenharmony_ci		pr_err("Cannot re-enable PCI device after reset.\n");
52738c2ecf20Sopenharmony_ci		return PCI_ERS_RESULT_DISCONNECT;
52748c2ecf20Sopenharmony_ci	}
52758c2ecf20Sopenharmony_ci
52768c2ecf20Sopenharmony_ci	/* flush memory to make sure state is correct */
52778c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
52788c2ecf20Sopenharmony_ci	clear_bit(__E1000_DISABLED, &adapter->flags);
52798c2ecf20Sopenharmony_ci	pci_set_master(pdev);
52808c2ecf20Sopenharmony_ci
52818c2ecf20Sopenharmony_ci	pci_enable_wake(pdev, PCI_D3hot, 0);
52828c2ecf20Sopenharmony_ci	pci_enable_wake(pdev, PCI_D3cold, 0);
52838c2ecf20Sopenharmony_ci
52848c2ecf20Sopenharmony_ci	e1000_reset(adapter);
52858c2ecf20Sopenharmony_ci	ew32(WUS, ~0);
52868c2ecf20Sopenharmony_ci
52878c2ecf20Sopenharmony_ci	return PCI_ERS_RESULT_RECOVERED;
52888c2ecf20Sopenharmony_ci}
52898c2ecf20Sopenharmony_ci
52908c2ecf20Sopenharmony_ci/**
52918c2ecf20Sopenharmony_ci * e1000_io_resume - called when traffic can start flowing again.
52928c2ecf20Sopenharmony_ci * @pdev: Pointer to PCI device
52938c2ecf20Sopenharmony_ci *
52948c2ecf20Sopenharmony_ci * This callback is called when the error recovery driver tells us that
52958c2ecf20Sopenharmony_ci * its OK to resume normal operation. Implementation resembles the
52968c2ecf20Sopenharmony_ci * second-half of the e1000_resume routine.
52978c2ecf20Sopenharmony_ci */
52988c2ecf20Sopenharmony_cistatic void e1000_io_resume(struct pci_dev *pdev)
52998c2ecf20Sopenharmony_ci{
53008c2ecf20Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
53018c2ecf20Sopenharmony_ci	struct e1000_adapter *adapter = netdev_priv(netdev);
53028c2ecf20Sopenharmony_ci
53038c2ecf20Sopenharmony_ci	e1000_init_manageability(adapter);
53048c2ecf20Sopenharmony_ci
53058c2ecf20Sopenharmony_ci	if (netif_running(netdev)) {
53068c2ecf20Sopenharmony_ci		if (e1000_up(adapter)) {
53078c2ecf20Sopenharmony_ci			pr_info("can't bring device back up after reset\n");
53088c2ecf20Sopenharmony_ci			return;
53098c2ecf20Sopenharmony_ci		}
53108c2ecf20Sopenharmony_ci	}
53118c2ecf20Sopenharmony_ci
53128c2ecf20Sopenharmony_ci	netif_device_attach(netdev);
53138c2ecf20Sopenharmony_ci}
53148c2ecf20Sopenharmony_ci
53158c2ecf20Sopenharmony_ci/* e1000_main.c */
5316