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