1205869Sjfv/****************************************************************************** 2205869Sjfv 3294958Smarius Copyright (c) 2001-2015, Intel Corporation 4205869Sjfv All rights reserved. 5205869Sjfv 6205869Sjfv Redistribution and use in source and binary forms, with or without 7205869Sjfv modification, are permitted provided that the following conditions are met: 8205869Sjfv 9205869Sjfv 1. Redistributions of source code must retain the above copyright notice, 10205869Sjfv this list of conditions and the following disclaimer. 11205869Sjfv 12205869Sjfv 2. Redistributions in binary form must reproduce the above copyright 13205869Sjfv notice, this list of conditions and the following disclaimer in the 14205869Sjfv documentation and/or other materials provided with the distribution. 15205869Sjfv 16205869Sjfv 3. Neither the name of the Intel Corporation nor the names of its 17205869Sjfv contributors may be used to endorse or promote products derived from 18205869Sjfv this software without specific prior written permission. 19205869Sjfv 20205869Sjfv THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21205869Sjfv AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22205869Sjfv IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23205869Sjfv ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24205869Sjfv LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25205869Sjfv CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26205869Sjfv SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27205869Sjfv INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28205869Sjfv CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29205869Sjfv ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30205869Sjfv POSSIBILITY OF SUCH DAMAGE. 31205869Sjfv 32205869Sjfv******************************************************************************/ 33205869Sjfv/*$FreeBSD: stable/10/sys/dev/e1000/if_lem.c 323293 2017-09-08 00:11:35Z marius $*/ 34205869Sjfv 35270252Sluigi/* 36270252Sluigi * Uncomment the following extensions for better performance in a VM, 37270252Sluigi * especially if you have support in the hypervisor. 38270252Sluigi * See http://info.iet.unipi.it/~luigi/netmap/ 39270252Sluigi */ 40270252Sluigi// #define BATCH_DISPATCH 41270252Sluigi// #define NIC_SEND_COMBINING 42270252Sluigi// #define NIC_PARAVIRT /* enable virtio-like synchronization */ 43270252Sluigi 44253303Sjfv#include "opt_inet.h" 45253303Sjfv#include "opt_inet6.h" 46253303Sjfv 47205869Sjfv#ifdef HAVE_KERNEL_OPTION_HEADERS 48205869Sjfv#include "opt_device_polling.h" 49205869Sjfv#endif 50205869Sjfv 51205869Sjfv#include <sys/param.h> 52205869Sjfv#include <sys/systm.h> 53205869Sjfv#include <sys/bus.h> 54205869Sjfv#include <sys/endian.h> 55205869Sjfv#include <sys/kernel.h> 56205869Sjfv#include <sys/kthread.h> 57205869Sjfv#include <sys/malloc.h> 58205869Sjfv#include <sys/mbuf.h> 59205869Sjfv#include <sys/module.h> 60205869Sjfv#include <sys/rman.h> 61205869Sjfv#include <sys/socket.h> 62205869Sjfv#include <sys/sockio.h> 63205869Sjfv#include <sys/sysctl.h> 64205869Sjfv#include <sys/taskqueue.h> 65205869Sjfv#include <sys/eventhandler.h> 66205869Sjfv#include <machine/bus.h> 67205869Sjfv#include <machine/resource.h> 68205869Sjfv 69205869Sjfv#include <net/bpf.h> 70205869Sjfv#include <net/ethernet.h> 71205869Sjfv#include <net/if.h> 72205869Sjfv#include <net/if_arp.h> 73205869Sjfv#include <net/if_dl.h> 74205869Sjfv#include <net/if_media.h> 75205869Sjfv 76205869Sjfv#include <net/if_types.h> 77205869Sjfv#include <net/if_vlan_var.h> 78205869Sjfv 79205869Sjfv#include <netinet/in_systm.h> 80205869Sjfv#include <netinet/in.h> 81205869Sjfv#include <netinet/if_ether.h> 82205869Sjfv#include <netinet/ip.h> 83205869Sjfv#include <netinet/ip6.h> 84205869Sjfv#include <netinet/tcp.h> 85205869Sjfv#include <netinet/udp.h> 86205869Sjfv 87205869Sjfv#include <machine/in_cksum.h> 88206001Smarius#include <dev/led/led.h> 89205869Sjfv#include <dev/pci/pcivar.h> 90205869Sjfv#include <dev/pci/pcireg.h> 91205869Sjfv 92205869Sjfv#include "e1000_api.h" 93205869Sjfv#include "if_lem.h" 94205869Sjfv 95205869Sjfv/********************************************************************* 96205869Sjfv * Legacy Em Driver version: 97205869Sjfv *********************************************************************/ 98294958Smariuschar lem_driver_version[] = "1.1.0"; 99205869Sjfv 100205869Sjfv/********************************************************************* 101205869Sjfv * PCI Device ID Table 102205869Sjfv * 103205869Sjfv * Used by probe to select devices to load on 104205869Sjfv * Last field stores an index into e1000_strings 105205869Sjfv * Last entry must be all 0s 106205869Sjfv * 107205869Sjfv * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 108205869Sjfv *********************************************************************/ 109205869Sjfv 110205869Sjfvstatic em_vendor_info_t lem_vendor_info_array[] = 111205869Sjfv{ 112205869Sjfv /* Intel(R) PRO/1000 Network Connection */ 113205869Sjfv { 0x8086, E1000_DEV_ID_82540EM, PCI_ANY_ID, PCI_ANY_ID, 0}, 114205869Sjfv { 0x8086, E1000_DEV_ID_82540EM_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 115205869Sjfv { 0x8086, E1000_DEV_ID_82540EP, PCI_ANY_ID, PCI_ANY_ID, 0}, 116205869Sjfv { 0x8086, E1000_DEV_ID_82540EP_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 117205869Sjfv { 0x8086, E1000_DEV_ID_82540EP_LP, PCI_ANY_ID, PCI_ANY_ID, 0}, 118205869Sjfv 119205869Sjfv { 0x8086, E1000_DEV_ID_82541EI, PCI_ANY_ID, PCI_ANY_ID, 0}, 120205869Sjfv { 0x8086, E1000_DEV_ID_82541ER, PCI_ANY_ID, PCI_ANY_ID, 0}, 121205869Sjfv { 0x8086, E1000_DEV_ID_82541ER_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 122205869Sjfv { 0x8086, E1000_DEV_ID_82541EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, 123205869Sjfv { 0x8086, E1000_DEV_ID_82541GI, PCI_ANY_ID, PCI_ANY_ID, 0}, 124205869Sjfv { 0x8086, E1000_DEV_ID_82541GI_LF, PCI_ANY_ID, PCI_ANY_ID, 0}, 125205869Sjfv { 0x8086, E1000_DEV_ID_82541GI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, 126205869Sjfv 127205869Sjfv { 0x8086, E1000_DEV_ID_82542, PCI_ANY_ID, PCI_ANY_ID, 0}, 128205869Sjfv 129205869Sjfv { 0x8086, E1000_DEV_ID_82543GC_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 130205869Sjfv { 0x8086, E1000_DEV_ID_82543GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 131205869Sjfv 132205869Sjfv { 0x8086, E1000_DEV_ID_82544EI_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 133205869Sjfv { 0x8086, E1000_DEV_ID_82544EI_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 134205869Sjfv { 0x8086, E1000_DEV_ID_82544GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 135205869Sjfv { 0x8086, E1000_DEV_ID_82544GC_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 136205869Sjfv 137205869Sjfv { 0x8086, E1000_DEV_ID_82545EM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 138205869Sjfv { 0x8086, E1000_DEV_ID_82545EM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 139205869Sjfv { 0x8086, E1000_DEV_ID_82545GM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 140205869Sjfv { 0x8086, E1000_DEV_ID_82545GM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 141205869Sjfv { 0x8086, E1000_DEV_ID_82545GM_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, 142205869Sjfv 143205869Sjfv { 0x8086, E1000_DEV_ID_82546EB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 144205869Sjfv { 0x8086, E1000_DEV_ID_82546EB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 145205869Sjfv { 0x8086, E1000_DEV_ID_82546EB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 146205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 147205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 148205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, 149205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_PCIE, PCI_ANY_ID, PCI_ANY_ID, 0}, 150205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 151205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3, 152205869Sjfv PCI_ANY_ID, PCI_ANY_ID, 0}, 153205869Sjfv 154205869Sjfv { 0x8086, E1000_DEV_ID_82547EI, PCI_ANY_ID, PCI_ANY_ID, 0}, 155205869Sjfv { 0x8086, E1000_DEV_ID_82547EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, 156205869Sjfv { 0x8086, E1000_DEV_ID_82547GI, PCI_ANY_ID, PCI_ANY_ID, 0}, 157205869Sjfv /* required last entry */ 158205869Sjfv { 0, 0, 0, 0, 0} 159205869Sjfv}; 160205869Sjfv 161205869Sjfv/********************************************************************* 162205869Sjfv * Table of branding strings for all supported NICs. 163205869Sjfv *********************************************************************/ 164205869Sjfv 165205869Sjfvstatic char *lem_strings[] = { 166205869Sjfv "Intel(R) PRO/1000 Legacy Network Connection" 167205869Sjfv}; 168205869Sjfv 169205869Sjfv/********************************************************************* 170205869Sjfv * Function prototypes 171205869Sjfv *********************************************************************/ 172205869Sjfvstatic int lem_probe(device_t); 173205869Sjfvstatic int lem_attach(device_t); 174205869Sjfvstatic int lem_detach(device_t); 175205869Sjfvstatic int lem_shutdown(device_t); 176205869Sjfvstatic int lem_suspend(device_t); 177205869Sjfvstatic int lem_resume(device_t); 178205869Sjfvstatic void lem_start(struct ifnet *); 179205869Sjfvstatic void lem_start_locked(struct ifnet *ifp); 180205869Sjfvstatic int lem_ioctl(struct ifnet *, u_long, caddr_t); 181205869Sjfvstatic void lem_init(void *); 182205869Sjfvstatic void lem_init_locked(struct adapter *); 183205869Sjfvstatic void lem_stop(void *); 184205869Sjfvstatic void lem_media_status(struct ifnet *, struct ifmediareq *); 185205869Sjfvstatic int lem_media_change(struct ifnet *); 186205869Sjfvstatic void lem_identify_hardware(struct adapter *); 187205869Sjfvstatic int lem_allocate_pci_resources(struct adapter *); 188205869Sjfvstatic int lem_allocate_irq(struct adapter *adapter); 189205869Sjfvstatic void lem_free_pci_resources(struct adapter *); 190205869Sjfvstatic void lem_local_timer(void *); 191205869Sjfvstatic int lem_hardware_init(struct adapter *); 192211907Syongaristatic int lem_setup_interface(device_t, struct adapter *); 193205869Sjfvstatic void lem_setup_transmit_structures(struct adapter *); 194205869Sjfvstatic void lem_initialize_transmit_unit(struct adapter *); 195205869Sjfvstatic int lem_setup_receive_structures(struct adapter *); 196205869Sjfvstatic void lem_initialize_receive_unit(struct adapter *); 197205869Sjfvstatic void lem_enable_intr(struct adapter *); 198205869Sjfvstatic void lem_disable_intr(struct adapter *); 199205869Sjfvstatic void lem_free_transmit_structures(struct adapter *); 200205869Sjfvstatic void lem_free_receive_structures(struct adapter *); 201205869Sjfvstatic void lem_update_stats_counters(struct adapter *); 202212902Sjhbstatic void lem_add_hw_stats(struct adapter *adapter); 203205869Sjfvstatic void lem_txeof(struct adapter *); 204205869Sjfvstatic void lem_tx_purge(struct adapter *); 205205869Sjfvstatic int lem_allocate_receive_structures(struct adapter *); 206205869Sjfvstatic int lem_allocate_transmit_structures(struct adapter *); 207209238Sjfvstatic bool lem_rxeof(struct adapter *, int, int *); 208205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 209205869Sjfvstatic int lem_fixup_rx(struct adapter *); 210205869Sjfv#endif 211205869Sjfvstatic void lem_receive_checksum(struct adapter *, struct e1000_rx_desc *, 212205869Sjfv struct mbuf *); 213205869Sjfvstatic void lem_transmit_checksum_setup(struct adapter *, struct mbuf *, 214205869Sjfv u32 *, u32 *); 215205869Sjfvstatic void lem_set_promisc(struct adapter *); 216205869Sjfvstatic void lem_disable_promisc(struct adapter *); 217205869Sjfvstatic void lem_set_multi(struct adapter *); 218205869Sjfvstatic void lem_update_link_status(struct adapter *); 219205869Sjfvstatic int lem_get_buf(struct adapter *, int); 220205869Sjfvstatic void lem_register_vlan(void *, struct ifnet *, u16); 221205869Sjfvstatic void lem_unregister_vlan(void *, struct ifnet *, u16); 222205869Sjfvstatic void lem_setup_vlan_hw_support(struct adapter *); 223205869Sjfvstatic int lem_xmit(struct adapter *, struct mbuf **); 224205869Sjfvstatic void lem_smartspeed(struct adapter *); 225205869Sjfvstatic int lem_82547_fifo_workaround(struct adapter *, int); 226205869Sjfvstatic void lem_82547_update_fifo_head(struct adapter *, int); 227205869Sjfvstatic int lem_82547_tx_fifo_reset(struct adapter *); 228205869Sjfvstatic void lem_82547_move_tail(void *); 229205869Sjfvstatic int lem_dma_malloc(struct adapter *, bus_size_t, 230205869Sjfv struct em_dma_alloc *, int); 231205869Sjfvstatic void lem_dma_free(struct adapter *, struct em_dma_alloc *); 232212902Sjhbstatic int lem_sysctl_nvm_info(SYSCTL_HANDLER_ARGS); 233205869Sjfvstatic void lem_print_nvm_info(struct adapter *); 234205869Sjfvstatic int lem_is_valid_ether_addr(u8 *); 235205869Sjfvstatic u32 lem_fill_descriptors (bus_addr_t address, u32 length, 236205869Sjfv PDESC_ARRAY desc_array); 237205869Sjfvstatic int lem_sysctl_int_delay(SYSCTL_HANDLER_ARGS); 238205869Sjfvstatic void lem_add_int_delay_sysctl(struct adapter *, const char *, 239205869Sjfv const char *, struct em_int_delay_info *, int, int); 240214646Sjfvstatic void lem_set_flow_cntrl(struct adapter *, const char *, 241214646Sjfv const char *, int *, int); 242205869Sjfv/* Management and WOL Support */ 243205869Sjfvstatic void lem_init_manageability(struct adapter *); 244205869Sjfvstatic void lem_release_manageability(struct adapter *); 245205869Sjfvstatic void lem_get_hw_control(struct adapter *); 246205869Sjfvstatic void lem_release_hw_control(struct adapter *); 247205869Sjfvstatic void lem_get_wakeup(device_t); 248205869Sjfvstatic void lem_enable_wakeup(device_t); 249205869Sjfvstatic int lem_enable_phy_wakeup(struct adapter *); 250206001Smariusstatic void lem_led_func(void *, int); 251205869Sjfv 252205869Sjfvstatic void lem_intr(void *); 253205869Sjfvstatic int lem_irq_fast(void *); 254205869Sjfvstatic void lem_handle_rxtx(void *context, int pending); 255205869Sjfvstatic void lem_handle_link(void *context, int pending); 256205869Sjfvstatic void lem_add_rx_process_limit(struct adapter *, const char *, 257205869Sjfv const char *, int *, int); 258205869Sjfv 259205869Sjfv#ifdef DEVICE_POLLING 260205987Sjfvstatic poll_handler_t lem_poll; 261205869Sjfv#endif /* POLLING */ 262205869Sjfv 263205869Sjfv/********************************************************************* 264205869Sjfv * FreeBSD Device Interface Entry Points 265205869Sjfv *********************************************************************/ 266205869Sjfv 267205869Sjfvstatic device_method_t lem_methods[] = { 268205869Sjfv /* Device interface */ 269205869Sjfv DEVMETHOD(device_probe, lem_probe), 270205869Sjfv DEVMETHOD(device_attach, lem_attach), 271205869Sjfv DEVMETHOD(device_detach, lem_detach), 272205869Sjfv DEVMETHOD(device_shutdown, lem_shutdown), 273205869Sjfv DEVMETHOD(device_suspend, lem_suspend), 274205869Sjfv DEVMETHOD(device_resume, lem_resume), 275246128Ssbz DEVMETHOD_END 276205869Sjfv}; 277205869Sjfv 278205869Sjfvstatic driver_t lem_driver = { 279205869Sjfv "em", lem_methods, sizeof(struct adapter), 280205869Sjfv}; 281205869Sjfv 282205869Sjfvextern devclass_t em_devclass; 283205869SjfvDRIVER_MODULE(lem, pci, lem_driver, em_devclass, 0, 0); 284205869SjfvMODULE_DEPEND(lem, pci, 1, 1, 1); 285205869SjfvMODULE_DEPEND(lem, ether, 1, 1, 1); 286205869Sjfv 287205869Sjfv/********************************************************************* 288205869Sjfv * Tunable default values. 289205869Sjfv *********************************************************************/ 290205869Sjfv 291205869Sjfv#define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) 292205869Sjfv#define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) 293205869Sjfv 294250414Sluigi#define MAX_INTS_PER_SEC 8000 295250414Sluigi#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) 296250414Sluigi 297205869Sjfvstatic int lem_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV); 298205869Sjfvstatic int lem_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR); 299205869Sjfvstatic int lem_tx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_TADV); 300205869Sjfvstatic int lem_rx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_RADV); 301270252Sluigi/* 302270252Sluigi * increase lem_rxd and lem_txd to at least 2048 in netmap mode 303270252Sluigi * for better performance. 304270252Sluigi */ 305205869Sjfvstatic int lem_rxd = EM_DEFAULT_RXD; 306205869Sjfvstatic int lem_txd = EM_DEFAULT_TXD; 307205869Sjfvstatic int lem_smart_pwr_down = FALSE; 308205869Sjfv 309205869Sjfv/* Controls whether promiscuous also shows bad packets */ 310205869Sjfvstatic int lem_debug_sbp = FALSE; 311205869Sjfv 312205869SjfvTUNABLE_INT("hw.em.tx_int_delay", &lem_tx_int_delay_dflt); 313205869SjfvTUNABLE_INT("hw.em.rx_int_delay", &lem_rx_int_delay_dflt); 314205869SjfvTUNABLE_INT("hw.em.tx_abs_int_delay", &lem_tx_abs_int_delay_dflt); 315205869SjfvTUNABLE_INT("hw.em.rx_abs_int_delay", &lem_rx_abs_int_delay_dflt); 316205869SjfvTUNABLE_INT("hw.em.rxd", &lem_rxd); 317205869SjfvTUNABLE_INT("hw.em.txd", &lem_txd); 318205869SjfvTUNABLE_INT("hw.em.smart_pwr_down", &lem_smart_pwr_down); 319205869SjfvTUNABLE_INT("hw.em.sbp", &lem_debug_sbp); 320205869Sjfv 321238953Sjfv/* Interrupt style - default to fast */ 322238953Sjfvstatic int lem_use_legacy_irq = 0; 323238953SjfvTUNABLE_INT("hw.em.use_legacy_irq", &lem_use_legacy_irq); 324238953Sjfv 325205869Sjfv/* How many packets rxeof tries to clean at a time */ 326205869Sjfvstatic int lem_rx_process_limit = 100; 327205869SjfvTUNABLE_INT("hw.em.rx_process_limit", &lem_rx_process_limit); 328205869Sjfv 329205869Sjfv/* Flow control setting - default to FULL */ 330205869Sjfvstatic int lem_fc_setting = e1000_fc_full; 331205869SjfvTUNABLE_INT("hw.em.fc_setting", &lem_fc_setting); 332205869Sjfv 333205869Sjfv/* Global used in WOL setup with multiport cards */ 334205869Sjfvstatic int global_quad_port_a = 0; 335205869Sjfv 336228281Sluigi#ifdef DEV_NETMAP /* see ixgbe.c for details */ 337228281Sluigi#include <dev/netmap/if_lem_netmap.h> 338228281Sluigi#endif /* DEV_NETMAP */ 339228281Sluigi 340205869Sjfv/********************************************************************* 341205869Sjfv * Device identification routine 342205869Sjfv * 343205869Sjfv * em_probe determines if the driver should be loaded on 344205869Sjfv * adapter based on PCI vendor/device id of the adapter. 345205869Sjfv * 346205869Sjfv * return BUS_PROBE_DEFAULT on success, positive on failure 347205869Sjfv *********************************************************************/ 348205869Sjfv 349205869Sjfvstatic int 350205869Sjfvlem_probe(device_t dev) 351205869Sjfv{ 352205869Sjfv char adapter_name[60]; 353205869Sjfv u16 pci_vendor_id = 0; 354205869Sjfv u16 pci_device_id = 0; 355205869Sjfv u16 pci_subvendor_id = 0; 356205869Sjfv u16 pci_subdevice_id = 0; 357205869Sjfv em_vendor_info_t *ent; 358205869Sjfv 359205869Sjfv INIT_DEBUGOUT("em_probe: begin"); 360205869Sjfv 361205869Sjfv pci_vendor_id = pci_get_vendor(dev); 362205869Sjfv if (pci_vendor_id != EM_VENDOR_ID) 363205869Sjfv return (ENXIO); 364205869Sjfv 365205869Sjfv pci_device_id = pci_get_device(dev); 366205869Sjfv pci_subvendor_id = pci_get_subvendor(dev); 367205869Sjfv pci_subdevice_id = pci_get_subdevice(dev); 368205869Sjfv 369205869Sjfv ent = lem_vendor_info_array; 370205869Sjfv while (ent->vendor_id != 0) { 371205869Sjfv if ((pci_vendor_id == ent->vendor_id) && 372205869Sjfv (pci_device_id == ent->device_id) && 373205869Sjfv 374205869Sjfv ((pci_subvendor_id == ent->subvendor_id) || 375205869Sjfv (ent->subvendor_id == PCI_ANY_ID)) && 376205869Sjfv 377205869Sjfv ((pci_subdevice_id == ent->subdevice_id) || 378205869Sjfv (ent->subdevice_id == PCI_ANY_ID))) { 379205869Sjfv sprintf(adapter_name, "%s %s", 380205869Sjfv lem_strings[ent->index], 381205869Sjfv lem_driver_version); 382205869Sjfv device_set_desc_copy(dev, adapter_name); 383205869Sjfv return (BUS_PROBE_DEFAULT); 384205869Sjfv } 385205869Sjfv ent++; 386205869Sjfv } 387205869Sjfv 388205869Sjfv return (ENXIO); 389205869Sjfv} 390205869Sjfv 391205869Sjfv/********************************************************************* 392205869Sjfv * Device initialization routine 393205869Sjfv * 394205869Sjfv * The attach entry point is called when the driver is being loaded. 395205869Sjfv * This routine identifies the type of hardware, allocates all resources 396205869Sjfv * and initializes the hardware. 397205869Sjfv * 398205869Sjfv * return 0 on success, positive on failure 399205869Sjfv *********************************************************************/ 400205869Sjfv 401205869Sjfvstatic int 402205869Sjfvlem_attach(device_t dev) 403205869Sjfv{ 404205869Sjfv struct adapter *adapter; 405205869Sjfv int tsize, rsize; 406205869Sjfv int error = 0; 407205869Sjfv 408205869Sjfv INIT_DEBUGOUT("lem_attach: begin"); 409205869Sjfv 410205869Sjfv adapter = device_get_softc(dev); 411205869Sjfv adapter->dev = adapter->osdep.dev = dev; 412205869Sjfv EM_CORE_LOCK_INIT(adapter, device_get_nameunit(dev)); 413205869Sjfv EM_TX_LOCK_INIT(adapter, device_get_nameunit(dev)); 414205869Sjfv EM_RX_LOCK_INIT(adapter, device_get_nameunit(dev)); 415205869Sjfv 416205869Sjfv /* SYSCTL stuff */ 417205869Sjfv SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 418205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 419212902Sjhb OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0, 420212902Sjhb lem_sysctl_nvm_info, "I", "NVM Information"); 421205869Sjfv 422205869Sjfv callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0); 423205869Sjfv callout_init_mtx(&adapter->tx_fifo_timer, &adapter->tx_mtx, 0); 424205869Sjfv 425205869Sjfv /* Determine hardware and mac info */ 426205869Sjfv lem_identify_hardware(adapter); 427205869Sjfv 428205869Sjfv /* Setup PCI resources */ 429205869Sjfv if (lem_allocate_pci_resources(adapter)) { 430205869Sjfv device_printf(dev, "Allocation of PCI resources failed\n"); 431205869Sjfv error = ENXIO; 432205869Sjfv goto err_pci; 433205869Sjfv } 434205869Sjfv 435205869Sjfv /* Do Shared Code initialization */ 436205869Sjfv if (e1000_setup_init_funcs(&adapter->hw, TRUE)) { 437205869Sjfv device_printf(dev, "Setup of Shared code failed\n"); 438205869Sjfv error = ENXIO; 439205869Sjfv goto err_pci; 440205869Sjfv } 441205869Sjfv 442205869Sjfv e1000_get_bus_info(&adapter->hw); 443205869Sjfv 444205869Sjfv /* Set up some sysctls for the tunable interrupt delays */ 445205869Sjfv lem_add_int_delay_sysctl(adapter, "rx_int_delay", 446205869Sjfv "receive interrupt delay in usecs", &adapter->rx_int_delay, 447205869Sjfv E1000_REGISTER(&adapter->hw, E1000_RDTR), lem_rx_int_delay_dflt); 448205869Sjfv lem_add_int_delay_sysctl(adapter, "tx_int_delay", 449205869Sjfv "transmit interrupt delay in usecs", &adapter->tx_int_delay, 450205869Sjfv E1000_REGISTER(&adapter->hw, E1000_TIDV), lem_tx_int_delay_dflt); 451205869Sjfv if (adapter->hw.mac.type >= e1000_82540) { 452205869Sjfv lem_add_int_delay_sysctl(adapter, "rx_abs_int_delay", 453205869Sjfv "receive interrupt delay limit in usecs", 454205869Sjfv &adapter->rx_abs_int_delay, 455205869Sjfv E1000_REGISTER(&adapter->hw, E1000_RADV), 456205869Sjfv lem_rx_abs_int_delay_dflt); 457205869Sjfv lem_add_int_delay_sysctl(adapter, "tx_abs_int_delay", 458205869Sjfv "transmit interrupt delay limit in usecs", 459205869Sjfv &adapter->tx_abs_int_delay, 460205869Sjfv E1000_REGISTER(&adapter->hw, E1000_TADV), 461205869Sjfv lem_tx_abs_int_delay_dflt); 462250414Sluigi lem_add_int_delay_sysctl(adapter, "itr", 463250414Sluigi "interrupt delay limit in usecs/4", 464250414Sluigi &adapter->tx_itr, 465250414Sluigi E1000_REGISTER(&adapter->hw, E1000_ITR), 466250414Sluigi DEFAULT_ITR); 467205869Sjfv } 468205869Sjfv 469205869Sjfv /* Sysctls for limiting the amount of work done in the taskqueue */ 470205869Sjfv lem_add_rx_process_limit(adapter, "rx_processing_limit", 471205869Sjfv "max number of rx packets to process", &adapter->rx_process_limit, 472205869Sjfv lem_rx_process_limit); 473205869Sjfv 474270252Sluigi#ifdef NIC_SEND_COMBINING 475270252Sluigi /* Sysctls to control mitigation */ 476270252Sluigi lem_add_rx_process_limit(adapter, "sc_enable", 477270252Sluigi "driver TDT mitigation", &adapter->sc_enable, 0); 478270252Sluigi#endif /* NIC_SEND_COMBINING */ 479270252Sluigi#ifdef BATCH_DISPATCH 480270252Sluigi lem_add_rx_process_limit(adapter, "batch_enable", 481270252Sluigi "driver rx batch", &adapter->batch_enable, 0); 482270252Sluigi#endif /* BATCH_DISPATCH */ 483270252Sluigi#ifdef NIC_PARAVIRT 484270252Sluigi lem_add_rx_process_limit(adapter, "rx_retries", 485270252Sluigi "driver rx retries", &adapter->rx_retries, 0); 486270252Sluigi#endif /* NIC_PARAVIRT */ 487270252Sluigi 488214646Sjfv /* Sysctl for setting the interface flow control */ 489214646Sjfv lem_set_flow_cntrl(adapter, "flow_control", 490228387Sjfv "flow control setting", 491214646Sjfv &adapter->fc_setting, lem_fc_setting); 492214646Sjfv 493205869Sjfv /* 494205869Sjfv * Validate number of transmit and receive descriptors. It 495205869Sjfv * must not exceed hardware maximum, and must be multiple 496205869Sjfv * of E1000_DBA_ALIGN. 497205869Sjfv */ 498205869Sjfv if (((lem_txd * sizeof(struct e1000_tx_desc)) % EM_DBA_ALIGN) != 0 || 499205869Sjfv (adapter->hw.mac.type >= e1000_82544 && lem_txd > EM_MAX_TXD) || 500205869Sjfv (adapter->hw.mac.type < e1000_82544 && lem_txd > EM_MAX_TXD_82543) || 501205869Sjfv (lem_txd < EM_MIN_TXD)) { 502205869Sjfv device_printf(dev, "Using %d TX descriptors instead of %d!\n", 503205869Sjfv EM_DEFAULT_TXD, lem_txd); 504205869Sjfv adapter->num_tx_desc = EM_DEFAULT_TXD; 505205869Sjfv } else 506205869Sjfv adapter->num_tx_desc = lem_txd; 507205869Sjfv if (((lem_rxd * sizeof(struct e1000_rx_desc)) % EM_DBA_ALIGN) != 0 || 508205869Sjfv (adapter->hw.mac.type >= e1000_82544 && lem_rxd > EM_MAX_RXD) || 509205869Sjfv (adapter->hw.mac.type < e1000_82544 && lem_rxd > EM_MAX_RXD_82543) || 510205869Sjfv (lem_rxd < EM_MIN_RXD)) { 511205869Sjfv device_printf(dev, "Using %d RX descriptors instead of %d!\n", 512205869Sjfv EM_DEFAULT_RXD, lem_rxd); 513205869Sjfv adapter->num_rx_desc = EM_DEFAULT_RXD; 514205869Sjfv } else 515205869Sjfv adapter->num_rx_desc = lem_rxd; 516205869Sjfv 517205869Sjfv adapter->hw.mac.autoneg = DO_AUTO_NEG; 518205869Sjfv adapter->hw.phy.autoneg_wait_to_complete = FALSE; 519205869Sjfv adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; 520205869Sjfv adapter->rx_buffer_len = 2048; 521205869Sjfv 522205869Sjfv e1000_init_script_state_82541(&adapter->hw, TRUE); 523205869Sjfv e1000_set_tbi_compatibility_82543(&adapter->hw, TRUE); 524205869Sjfv 525205869Sjfv /* Copper options */ 526205869Sjfv if (adapter->hw.phy.media_type == e1000_media_type_copper) { 527205869Sjfv adapter->hw.phy.mdix = AUTO_ALL_MODES; 528205869Sjfv adapter->hw.phy.disable_polarity_correction = FALSE; 529205869Sjfv adapter->hw.phy.ms_type = EM_MASTER_SLAVE; 530205869Sjfv } 531205869Sjfv 532205869Sjfv /* 533205869Sjfv * Set the frame limits assuming 534205869Sjfv * standard ethernet sized frames. 535205869Sjfv */ 536205869Sjfv adapter->max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE; 537205869Sjfv adapter->min_frame_size = ETH_ZLEN + ETHERNET_FCS_SIZE; 538205869Sjfv 539205869Sjfv /* 540205869Sjfv * This controls when hardware reports transmit completion 541205869Sjfv * status. 542205869Sjfv */ 543205869Sjfv adapter->hw.mac.report_tx_early = 1; 544205869Sjfv 545270252Sluigi#ifdef NIC_PARAVIRT 546270252Sluigi device_printf(dev, "driver supports paravirt, subdev 0x%x\n", 547270252Sluigi adapter->hw.subsystem_device_id); 548270252Sluigi if (adapter->hw.subsystem_device_id == E1000_PARA_SUBDEV) { 549270252Sluigi uint64_t bus_addr; 550270252Sluigi 551270252Sluigi device_printf(dev, "paravirt support on dev %p\n", adapter); 552270252Sluigi tsize = 4096; // XXX one page for the csb 553270252Sluigi if (lem_dma_malloc(adapter, tsize, &adapter->csb_mem, BUS_DMA_NOWAIT)) { 554270252Sluigi device_printf(dev, "Unable to allocate csb memory\n"); 555270252Sluigi error = ENOMEM; 556270252Sluigi goto err_csb; 557270252Sluigi } 558270252Sluigi /* Setup the Base of the CSB */ 559270252Sluigi adapter->csb = (struct paravirt_csb *)adapter->csb_mem.dma_vaddr; 560270252Sluigi /* force the first kick */ 561270252Sluigi adapter->csb->host_need_txkick = 1; /* txring empty */ 562270252Sluigi adapter->csb->guest_need_rxkick = 1; /* no rx packets */ 563270252Sluigi bus_addr = adapter->csb_mem.dma_paddr; 564270252Sluigi lem_add_rx_process_limit(adapter, "csb_on", 565270252Sluigi "enable paravirt.", &adapter->csb->guest_csb_on, 0); 566270252Sluigi lem_add_rx_process_limit(adapter, "txc_lim", 567270252Sluigi "txc_lim", &adapter->csb->host_txcycles_lim, 1); 568270252Sluigi 569270252Sluigi /* some stats */ 570270252Sluigi#define PA_SC(name, var, val) \ 571270252Sluigi lem_add_rx_process_limit(adapter, name, name, var, val) 572270252Sluigi PA_SC("host_need_txkick",&adapter->csb->host_need_txkick, 1); 573270252Sluigi PA_SC("host_rxkick_at",&adapter->csb->host_rxkick_at, ~0); 574270252Sluigi PA_SC("guest_need_txkick",&adapter->csb->guest_need_txkick, 0); 575270252Sluigi PA_SC("guest_need_rxkick",&adapter->csb->guest_need_rxkick, 1); 576270252Sluigi PA_SC("tdt_reg_count",&adapter->tdt_reg_count, 0); 577270252Sluigi PA_SC("tdt_csb_count",&adapter->tdt_csb_count, 0); 578270252Sluigi PA_SC("tdt_int_count",&adapter->tdt_int_count, 0); 579270252Sluigi PA_SC("guest_need_kick_count",&adapter->guest_need_kick_count, 0); 580270252Sluigi /* tell the host where the block is */ 581270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_CSBAH, 582270252Sluigi (u32)(bus_addr >> 32)); 583270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_CSBAL, 584270252Sluigi (u32)bus_addr); 585270252Sluigi } 586270252Sluigi#endif /* NIC_PARAVIRT */ 587270252Sluigi 588205869Sjfv tsize = roundup2(adapter->num_tx_desc * sizeof(struct e1000_tx_desc), 589205869Sjfv EM_DBA_ALIGN); 590205869Sjfv 591205869Sjfv /* Allocate Transmit Descriptor ring */ 592205869Sjfv if (lem_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) { 593205869Sjfv device_printf(dev, "Unable to allocate tx_desc memory\n"); 594205869Sjfv error = ENOMEM; 595205869Sjfv goto err_tx_desc; 596205869Sjfv } 597205869Sjfv adapter->tx_desc_base = 598205869Sjfv (struct e1000_tx_desc *)adapter->txdma.dma_vaddr; 599205869Sjfv 600205869Sjfv rsize = roundup2(adapter->num_rx_desc * sizeof(struct e1000_rx_desc), 601205869Sjfv EM_DBA_ALIGN); 602205869Sjfv 603205869Sjfv /* Allocate Receive Descriptor ring */ 604205869Sjfv if (lem_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) { 605205869Sjfv device_printf(dev, "Unable to allocate rx_desc memory\n"); 606205869Sjfv error = ENOMEM; 607205869Sjfv goto err_rx_desc; 608205869Sjfv } 609205869Sjfv adapter->rx_desc_base = 610205869Sjfv (struct e1000_rx_desc *)adapter->rxdma.dma_vaddr; 611205869Sjfv 612211913Syongari /* Allocate multicast array memory. */ 613211913Syongari adapter->mta = malloc(sizeof(u8) * ETH_ADDR_LEN * 614211913Syongari MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT); 615211913Syongari if (adapter->mta == NULL) { 616211913Syongari device_printf(dev, "Can not allocate multicast setup array\n"); 617211913Syongari error = ENOMEM; 618211913Syongari goto err_hw_init; 619211913Syongari } 620211913Syongari 621205869Sjfv /* 622205869Sjfv ** Start from a known state, this is 623205869Sjfv ** important in reading the nvm and 624205869Sjfv ** mac from that. 625205869Sjfv */ 626205869Sjfv e1000_reset_hw(&adapter->hw); 627205869Sjfv 628205869Sjfv /* Make sure we have a good EEPROM before we read from it */ 629205869Sjfv if (e1000_validate_nvm_checksum(&adapter->hw) < 0) { 630205869Sjfv /* 631205869Sjfv ** Some PCI-E parts fail the first check due to 632205869Sjfv ** the link being in sleep state, call it again, 633205869Sjfv ** if it fails a second time its a real issue. 634205869Sjfv */ 635205869Sjfv if (e1000_validate_nvm_checksum(&adapter->hw) < 0) { 636205869Sjfv device_printf(dev, 637205869Sjfv "The EEPROM Checksum Is Not Valid\n"); 638205869Sjfv error = EIO; 639205869Sjfv goto err_hw_init; 640205869Sjfv } 641205869Sjfv } 642205869Sjfv 643205869Sjfv /* Copy the permanent MAC address out of the EEPROM */ 644205869Sjfv if (e1000_read_mac_addr(&adapter->hw) < 0) { 645205869Sjfv device_printf(dev, "EEPROM read error while reading MAC" 646205869Sjfv " address\n"); 647205869Sjfv error = EIO; 648205869Sjfv goto err_hw_init; 649205869Sjfv } 650205869Sjfv 651205869Sjfv if (!lem_is_valid_ether_addr(adapter->hw.mac.addr)) { 652205869Sjfv device_printf(dev, "Invalid MAC address\n"); 653205869Sjfv error = EIO; 654205869Sjfv goto err_hw_init; 655205869Sjfv } 656205869Sjfv 657205869Sjfv /* Initialize the hardware */ 658205869Sjfv if (lem_hardware_init(adapter)) { 659205869Sjfv device_printf(dev, "Unable to initialize the hardware\n"); 660205869Sjfv error = EIO; 661205869Sjfv goto err_hw_init; 662205869Sjfv } 663205869Sjfv 664205869Sjfv /* Allocate transmit descriptors and buffers */ 665205869Sjfv if (lem_allocate_transmit_structures(adapter)) { 666205869Sjfv device_printf(dev, "Could not setup transmit structures\n"); 667205869Sjfv error = ENOMEM; 668205869Sjfv goto err_tx_struct; 669205869Sjfv } 670205869Sjfv 671205869Sjfv /* Allocate receive descriptors and buffers */ 672205869Sjfv if (lem_allocate_receive_structures(adapter)) { 673205869Sjfv device_printf(dev, "Could not setup receive structures\n"); 674205869Sjfv error = ENOMEM; 675205869Sjfv goto err_rx_struct; 676205869Sjfv } 677205869Sjfv 678205869Sjfv /* 679205869Sjfv ** Do interrupt configuration 680205869Sjfv */ 681205869Sjfv error = lem_allocate_irq(adapter); 682205869Sjfv if (error) 683205869Sjfv goto err_rx_struct; 684205869Sjfv 685205869Sjfv /* 686205869Sjfv * Get Wake-on-Lan and Management info for later use 687205869Sjfv */ 688205869Sjfv lem_get_wakeup(dev); 689205869Sjfv 690205869Sjfv /* Setup OS specific network interface */ 691211907Syongari if (lem_setup_interface(dev, adapter) != 0) 692211907Syongari goto err_rx_struct; 693205869Sjfv 694205869Sjfv /* Initialize statistics */ 695205869Sjfv lem_update_stats_counters(adapter); 696205869Sjfv 697205869Sjfv adapter->hw.mac.get_link_status = 1; 698205869Sjfv lem_update_link_status(adapter); 699205869Sjfv 700205869Sjfv /* Indicate SOL/IDER usage */ 701205869Sjfv if (e1000_check_reset_block(&adapter->hw)) 702205869Sjfv device_printf(dev, 703205869Sjfv "PHY reset is blocked due to SOL/IDER session.\n"); 704205869Sjfv 705205869Sjfv /* Do we need workaround for 82544 PCI-X adapter? */ 706205869Sjfv if (adapter->hw.bus.type == e1000_bus_type_pcix && 707205869Sjfv adapter->hw.mac.type == e1000_82544) 708205869Sjfv adapter->pcix_82544 = TRUE; 709205869Sjfv else 710205869Sjfv adapter->pcix_82544 = FALSE; 711205869Sjfv 712205869Sjfv /* Register for VLAN events */ 713205869Sjfv adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 714205869Sjfv lem_register_vlan, adapter, EVENTHANDLER_PRI_FIRST); 715205869Sjfv adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 716205869Sjfv lem_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST); 717205869Sjfv 718212902Sjhb lem_add_hw_stats(adapter); 719212902Sjhb 720205869Sjfv /* Non-AMT based hardware can now take control from firmware */ 721205869Sjfv if (adapter->has_manage && !adapter->has_amt) 722205869Sjfv lem_get_hw_control(adapter); 723205869Sjfv 724205869Sjfv /* Tell the stack that the interface is not active */ 725205869Sjfv adapter->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 726205869Sjfv 727206001Smarius adapter->led_dev = led_create(lem_led_func, adapter, 728206001Smarius device_get_nameunit(dev)); 729206001Smarius 730228281Sluigi#ifdef DEV_NETMAP 731228281Sluigi lem_netmap_attach(adapter); 732228281Sluigi#endif /* DEV_NETMAP */ 733205869Sjfv INIT_DEBUGOUT("lem_attach: end"); 734205869Sjfv 735205869Sjfv return (0); 736205869Sjfv 737205869Sjfverr_rx_struct: 738205869Sjfv lem_free_transmit_structures(adapter); 739205869Sjfverr_tx_struct: 740205869Sjfverr_hw_init: 741205869Sjfv lem_release_hw_control(adapter); 742205869Sjfv lem_dma_free(adapter, &adapter->rxdma); 743205869Sjfverr_rx_desc: 744205869Sjfv lem_dma_free(adapter, &adapter->txdma); 745205869Sjfverr_tx_desc: 746270252Sluigi#ifdef NIC_PARAVIRT 747270252Sluigi lem_dma_free(adapter, &adapter->csb_mem); 748270252Sluigierr_csb: 749270252Sluigi#endif /* NIC_PARAVIRT */ 750270252Sluigi 751205869Sjfverr_pci: 752211907Syongari if (adapter->ifp != NULL) 753211907Syongari if_free(adapter->ifp); 754205869Sjfv lem_free_pci_resources(adapter); 755211913Syongari free(adapter->mta, M_DEVBUF); 756205869Sjfv EM_TX_LOCK_DESTROY(adapter); 757205869Sjfv EM_RX_LOCK_DESTROY(adapter); 758205869Sjfv EM_CORE_LOCK_DESTROY(adapter); 759205869Sjfv 760205869Sjfv return (error); 761205869Sjfv} 762205869Sjfv 763205869Sjfv/********************************************************************* 764205869Sjfv * Device removal routine 765205869Sjfv * 766205869Sjfv * The detach entry point is called when the driver is being removed. 767205869Sjfv * This routine stops the adapter and deallocates all the resources 768205869Sjfv * that were allocated for driver operation. 769205869Sjfv * 770205869Sjfv * return 0 on success, positive on failure 771205869Sjfv *********************************************************************/ 772205869Sjfv 773205869Sjfvstatic int 774205869Sjfvlem_detach(device_t dev) 775205869Sjfv{ 776205869Sjfv struct adapter *adapter = device_get_softc(dev); 777205869Sjfv struct ifnet *ifp = adapter->ifp; 778205869Sjfv 779205869Sjfv INIT_DEBUGOUT("em_detach: begin"); 780205869Sjfv 781205869Sjfv /* Make sure VLANS are not using driver */ 782205869Sjfv if (adapter->ifp->if_vlantrunk != NULL) { 783205869Sjfv device_printf(dev,"Vlan in use, detach first\n"); 784205869Sjfv return (EBUSY); 785205869Sjfv } 786205869Sjfv 787205869Sjfv#ifdef DEVICE_POLLING 788205869Sjfv if (ifp->if_capenable & IFCAP_POLLING) 789205869Sjfv ether_poll_deregister(ifp); 790205869Sjfv#endif 791205869Sjfv 792206001Smarius if (adapter->led_dev != NULL) 793206001Smarius led_destroy(adapter->led_dev); 794206001Smarius 795205869Sjfv EM_CORE_LOCK(adapter); 796205869Sjfv EM_TX_LOCK(adapter); 797205869Sjfv adapter->in_detach = 1; 798205869Sjfv lem_stop(adapter); 799205869Sjfv e1000_phy_hw_reset(&adapter->hw); 800205869Sjfv 801205869Sjfv lem_release_manageability(adapter); 802205869Sjfv 803205869Sjfv EM_TX_UNLOCK(adapter); 804205869Sjfv EM_CORE_UNLOCK(adapter); 805205869Sjfv 806205869Sjfv /* Unregister VLAN events */ 807205869Sjfv if (adapter->vlan_attach != NULL) 808205869Sjfv EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach); 809205869Sjfv if (adapter->vlan_detach != NULL) 810205869Sjfv EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); 811205869Sjfv 812205869Sjfv ether_ifdetach(adapter->ifp); 813205869Sjfv callout_drain(&adapter->timer); 814205869Sjfv callout_drain(&adapter->tx_fifo_timer); 815205869Sjfv 816228281Sluigi#ifdef DEV_NETMAP 817228281Sluigi netmap_detach(ifp); 818228281Sluigi#endif /* DEV_NETMAP */ 819205869Sjfv lem_free_pci_resources(adapter); 820205869Sjfv bus_generic_detach(dev); 821205869Sjfv if_free(ifp); 822205869Sjfv 823205869Sjfv lem_free_transmit_structures(adapter); 824205869Sjfv lem_free_receive_structures(adapter); 825205869Sjfv 826205869Sjfv /* Free Transmit Descriptor ring */ 827205869Sjfv if (adapter->tx_desc_base) { 828205869Sjfv lem_dma_free(adapter, &adapter->txdma); 829205869Sjfv adapter->tx_desc_base = NULL; 830205869Sjfv } 831205869Sjfv 832205869Sjfv /* Free Receive Descriptor ring */ 833205869Sjfv if (adapter->rx_desc_base) { 834205869Sjfv lem_dma_free(adapter, &adapter->rxdma); 835205869Sjfv adapter->rx_desc_base = NULL; 836205869Sjfv } 837205869Sjfv 838270252Sluigi#ifdef NIC_PARAVIRT 839270252Sluigi if (adapter->csb) { 840270252Sluigi lem_dma_free(adapter, &adapter->csb_mem); 841270252Sluigi adapter->csb = NULL; 842270252Sluigi } 843270252Sluigi#endif /* NIC_PARAVIRT */ 844205869Sjfv lem_release_hw_control(adapter); 845211913Syongari free(adapter->mta, M_DEVBUF); 846205869Sjfv EM_TX_LOCK_DESTROY(adapter); 847205869Sjfv EM_RX_LOCK_DESTROY(adapter); 848205869Sjfv EM_CORE_LOCK_DESTROY(adapter); 849205869Sjfv 850205869Sjfv return (0); 851205869Sjfv} 852205869Sjfv 853205869Sjfv/********************************************************************* 854205869Sjfv * 855205869Sjfv * Shutdown entry point 856205869Sjfv * 857205869Sjfv **********************************************************************/ 858205869Sjfv 859205869Sjfvstatic int 860205869Sjfvlem_shutdown(device_t dev) 861205869Sjfv{ 862205869Sjfv return lem_suspend(dev); 863205869Sjfv} 864205869Sjfv 865205869Sjfv/* 866205869Sjfv * Suspend/resume device methods. 867205869Sjfv */ 868205869Sjfvstatic int 869205869Sjfvlem_suspend(device_t dev) 870205869Sjfv{ 871205869Sjfv struct adapter *adapter = device_get_softc(dev); 872205869Sjfv 873205869Sjfv EM_CORE_LOCK(adapter); 874205869Sjfv 875205869Sjfv lem_release_manageability(adapter); 876205869Sjfv lem_release_hw_control(adapter); 877205869Sjfv lem_enable_wakeup(dev); 878205869Sjfv 879205869Sjfv EM_CORE_UNLOCK(adapter); 880205869Sjfv 881205869Sjfv return bus_generic_suspend(dev); 882205869Sjfv} 883205869Sjfv 884205869Sjfvstatic int 885205869Sjfvlem_resume(device_t dev) 886205869Sjfv{ 887205869Sjfv struct adapter *adapter = device_get_softc(dev); 888205869Sjfv struct ifnet *ifp = adapter->ifp; 889205869Sjfv 890205869Sjfv EM_CORE_LOCK(adapter); 891205869Sjfv lem_init_locked(adapter); 892205869Sjfv lem_init_manageability(adapter); 893205869Sjfv EM_CORE_UNLOCK(adapter); 894205869Sjfv lem_start(ifp); 895205869Sjfv 896205869Sjfv return bus_generic_resume(dev); 897205869Sjfv} 898205869Sjfv 899205869Sjfv 900205869Sjfvstatic void 901205869Sjfvlem_start_locked(struct ifnet *ifp) 902205869Sjfv{ 903205869Sjfv struct adapter *adapter = ifp->if_softc; 904205869Sjfv struct mbuf *m_head; 905205869Sjfv 906205869Sjfv EM_TX_LOCK_ASSERT(adapter); 907205869Sjfv 908205869Sjfv if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) != 909205869Sjfv IFF_DRV_RUNNING) 910205869Sjfv return; 911205869Sjfv if (!adapter->link_active) 912205869Sjfv return; 913205869Sjfv 914214646Sjfv /* 915214646Sjfv * Force a cleanup if number of TX descriptors 916214646Sjfv * available hits the threshold 917214646Sjfv */ 918214646Sjfv if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) { 919214646Sjfv lem_txeof(adapter); 920214646Sjfv /* Now do we at least have a minimal? */ 921214646Sjfv if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) { 922214646Sjfv adapter->no_tx_desc_avail1++; 923214646Sjfv return; 924214646Sjfv } 925214646Sjfv } 926214646Sjfv 927205869Sjfv while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 928205869Sjfv 929205869Sjfv IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 930205869Sjfv if (m_head == NULL) 931205869Sjfv break; 932205869Sjfv /* 933205869Sjfv * Encapsulation can modify our pointer, and or make it 934205869Sjfv * NULL on failure. In that event, we can't requeue. 935205869Sjfv */ 936205869Sjfv if (lem_xmit(adapter, &m_head)) { 937205869Sjfv if (m_head == NULL) 938205869Sjfv break; 939205869Sjfv ifp->if_drv_flags |= IFF_DRV_OACTIVE; 940205869Sjfv IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 941205869Sjfv break; 942205869Sjfv } 943205869Sjfv 944205869Sjfv /* Send a copy of the frame to the BPF listener */ 945205869Sjfv ETHER_BPF_MTAP(ifp, m_head); 946205869Sjfv 947205869Sjfv /* Set timeout in case hardware has problems transmitting. */ 948205869Sjfv adapter->watchdog_check = TRUE; 949206614Sjfv adapter->watchdog_time = ticks; 950205869Sjfv } 951205869Sjfv if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) 952205869Sjfv ifp->if_drv_flags |= IFF_DRV_OACTIVE; 953270252Sluigi#ifdef NIC_PARAVIRT 954289386Sadrian if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) && adapter->csb && 955270252Sluigi adapter->csb->guest_csb_on && 956270252Sluigi !(adapter->csb->guest_need_txkick & 1)) { 957270252Sluigi adapter->csb->guest_need_txkick = 1; 958270252Sluigi adapter->guest_need_kick_count++; 959270252Sluigi // XXX memory barrier 960270252Sluigi lem_txeof(adapter); // XXX possibly clear IFF_DRV_OACTIVE 961270252Sluigi } 962270252Sluigi#endif /* NIC_PARAVIRT */ 963205869Sjfv 964205869Sjfv return; 965205869Sjfv} 966205869Sjfv 967205869Sjfvstatic void 968205869Sjfvlem_start(struct ifnet *ifp) 969205869Sjfv{ 970205869Sjfv struct adapter *adapter = ifp->if_softc; 971205869Sjfv 972205869Sjfv EM_TX_LOCK(adapter); 973205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) 974205869Sjfv lem_start_locked(ifp); 975205869Sjfv EM_TX_UNLOCK(adapter); 976205869Sjfv} 977205869Sjfv 978205869Sjfv/********************************************************************* 979205869Sjfv * Ioctl entry point 980205869Sjfv * 981205869Sjfv * em_ioctl is called when the user wants to configure the 982205869Sjfv * interface. 983205869Sjfv * 984205869Sjfv * return 0 on success, positive on failure 985205869Sjfv **********************************************************************/ 986205869Sjfv 987205869Sjfvstatic int 988205869Sjfvlem_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 989205869Sjfv{ 990205869Sjfv struct adapter *adapter = ifp->if_softc; 991228387Sjfv struct ifreq *ifr = (struct ifreq *)data; 992228387Sjfv#if defined(INET) || defined(INET6) 993228387Sjfv struct ifaddr *ifa = (struct ifaddr *)data; 994205869Sjfv#endif 995228387Sjfv bool avoid_reset = FALSE; 996228387Sjfv int error = 0; 997205869Sjfv 998205869Sjfv if (adapter->in_detach) 999205869Sjfv return (error); 1000205869Sjfv 1001205869Sjfv switch (command) { 1002205869Sjfv case SIOCSIFADDR: 1003205869Sjfv#ifdef INET 1004228387Sjfv if (ifa->ifa_addr->sa_family == AF_INET) 1005228387Sjfv avoid_reset = TRUE; 1006228387Sjfv#endif 1007228387Sjfv#ifdef INET6 1008228387Sjfv if (ifa->ifa_addr->sa_family == AF_INET6) 1009228387Sjfv avoid_reset = TRUE; 1010228387Sjfv#endif 1011228387Sjfv /* 1012228387Sjfv ** Calling init results in link renegotiation, 1013228387Sjfv ** so we avoid doing it when possible. 1014228387Sjfv */ 1015228387Sjfv if (avoid_reset) { 1016205869Sjfv ifp->if_flags |= IFF_UP; 1017228387Sjfv if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 1018228387Sjfv lem_init(adapter); 1019228387Sjfv#ifdef INET 1020228387Sjfv if (!(ifp->if_flags & IFF_NOARP)) 1021228387Sjfv arp_ifinit(ifp, ifa); 1022228387Sjfv#endif 1023205869Sjfv } else 1024205869Sjfv error = ether_ioctl(ifp, command, data); 1025205869Sjfv break; 1026205869Sjfv case SIOCSIFMTU: 1027205869Sjfv { 1028205869Sjfv int max_frame_size; 1029205869Sjfv 1030205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); 1031205869Sjfv 1032205869Sjfv EM_CORE_LOCK(adapter); 1033205869Sjfv switch (adapter->hw.mac.type) { 1034205869Sjfv case e1000_82542: 1035205869Sjfv max_frame_size = ETHER_MAX_LEN; 1036205869Sjfv break; 1037205869Sjfv default: 1038205869Sjfv max_frame_size = MAX_JUMBO_FRAME_SIZE; 1039205869Sjfv } 1040205869Sjfv if (ifr->ifr_mtu > max_frame_size - ETHER_HDR_LEN - 1041205869Sjfv ETHER_CRC_LEN) { 1042205869Sjfv EM_CORE_UNLOCK(adapter); 1043205869Sjfv error = EINVAL; 1044205869Sjfv break; 1045205869Sjfv } 1046205869Sjfv 1047205869Sjfv ifp->if_mtu = ifr->ifr_mtu; 1048205869Sjfv adapter->max_frame_size = 1049205869Sjfv ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 1050303117Ssbruno if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1051303107Ssbruno lem_init_locked(adapter); 1052205869Sjfv EM_CORE_UNLOCK(adapter); 1053205869Sjfv break; 1054205869Sjfv } 1055205869Sjfv case SIOCSIFFLAGS: 1056205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd:\ 1057205869Sjfv SIOCSIFFLAGS (Set Interface Flags)"); 1058205869Sjfv EM_CORE_LOCK(adapter); 1059205869Sjfv if (ifp->if_flags & IFF_UP) { 1060205869Sjfv if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { 1061205869Sjfv if ((ifp->if_flags ^ adapter->if_flags) & 1062205869Sjfv (IFF_PROMISC | IFF_ALLMULTI)) { 1063205869Sjfv lem_disable_promisc(adapter); 1064205869Sjfv lem_set_promisc(adapter); 1065205869Sjfv } 1066205869Sjfv } else 1067205869Sjfv lem_init_locked(adapter); 1068205869Sjfv } else 1069205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1070205869Sjfv EM_TX_LOCK(adapter); 1071205869Sjfv lem_stop(adapter); 1072205869Sjfv EM_TX_UNLOCK(adapter); 1073205869Sjfv } 1074205869Sjfv adapter->if_flags = ifp->if_flags; 1075205869Sjfv EM_CORE_UNLOCK(adapter); 1076205869Sjfv break; 1077205869Sjfv case SIOCADDMULTI: 1078205869Sjfv case SIOCDELMULTI: 1079205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI"); 1080205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1081205869Sjfv EM_CORE_LOCK(adapter); 1082205869Sjfv lem_disable_intr(adapter); 1083205869Sjfv lem_set_multi(adapter); 1084205869Sjfv if (adapter->hw.mac.type == e1000_82542 && 1085205869Sjfv adapter->hw.revision_id == E1000_REVISION_2) { 1086205869Sjfv lem_initialize_receive_unit(adapter); 1087205869Sjfv } 1088205869Sjfv#ifdef DEVICE_POLLING 1089205869Sjfv if (!(ifp->if_capenable & IFCAP_POLLING)) 1090205869Sjfv#endif 1091205869Sjfv lem_enable_intr(adapter); 1092205869Sjfv EM_CORE_UNLOCK(adapter); 1093205869Sjfv } 1094205869Sjfv break; 1095205869Sjfv case SIOCSIFMEDIA: 1096205869Sjfv /* Check SOL/IDER usage */ 1097205869Sjfv EM_CORE_LOCK(adapter); 1098205869Sjfv if (e1000_check_reset_block(&adapter->hw)) { 1099205869Sjfv EM_CORE_UNLOCK(adapter); 1100205869Sjfv device_printf(adapter->dev, "Media change is" 1101205869Sjfv " blocked due to SOL/IDER session.\n"); 1102205869Sjfv break; 1103205869Sjfv } 1104205869Sjfv EM_CORE_UNLOCK(adapter); 1105205869Sjfv case SIOCGIFMEDIA: 1106205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: \ 1107205869Sjfv SIOCxIFMEDIA (Get/Set Interface Media)"); 1108205869Sjfv error = ifmedia_ioctl(ifp, ifr, &adapter->media, command); 1109205869Sjfv break; 1110205869Sjfv case SIOCSIFCAP: 1111205869Sjfv { 1112205869Sjfv int mask, reinit; 1113205869Sjfv 1114205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)"); 1115205869Sjfv reinit = 0; 1116205869Sjfv mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1117205869Sjfv#ifdef DEVICE_POLLING 1118205869Sjfv if (mask & IFCAP_POLLING) { 1119205869Sjfv if (ifr->ifr_reqcap & IFCAP_POLLING) { 1120205869Sjfv error = ether_poll_register(lem_poll, ifp); 1121205869Sjfv if (error) 1122205869Sjfv return (error); 1123205869Sjfv EM_CORE_LOCK(adapter); 1124205869Sjfv lem_disable_intr(adapter); 1125205869Sjfv ifp->if_capenable |= IFCAP_POLLING; 1126205869Sjfv EM_CORE_UNLOCK(adapter); 1127205869Sjfv } else { 1128205869Sjfv error = ether_poll_deregister(ifp); 1129205869Sjfv /* Enable interrupt even in error case */ 1130205869Sjfv EM_CORE_LOCK(adapter); 1131205869Sjfv lem_enable_intr(adapter); 1132205869Sjfv ifp->if_capenable &= ~IFCAP_POLLING; 1133205869Sjfv EM_CORE_UNLOCK(adapter); 1134205869Sjfv } 1135205869Sjfv } 1136205869Sjfv#endif 1137205869Sjfv if (mask & IFCAP_HWCSUM) { 1138205869Sjfv ifp->if_capenable ^= IFCAP_HWCSUM; 1139205869Sjfv reinit = 1; 1140205869Sjfv } 1141205869Sjfv if (mask & IFCAP_VLAN_HWTAGGING) { 1142205869Sjfv ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 1143205869Sjfv reinit = 1; 1144205869Sjfv } 1145205869Sjfv if ((mask & IFCAP_WOL) && 1146205869Sjfv (ifp->if_capabilities & IFCAP_WOL) != 0) { 1147205869Sjfv if (mask & IFCAP_WOL_MCAST) 1148205869Sjfv ifp->if_capenable ^= IFCAP_WOL_MCAST; 1149205869Sjfv if (mask & IFCAP_WOL_MAGIC) 1150205869Sjfv ifp->if_capenable ^= IFCAP_WOL_MAGIC; 1151205869Sjfv } 1152205869Sjfv if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING)) 1153205869Sjfv lem_init(adapter); 1154205869Sjfv VLAN_CAPABILITIES(ifp); 1155205869Sjfv break; 1156205869Sjfv } 1157205869Sjfv 1158205869Sjfv default: 1159205869Sjfv error = ether_ioctl(ifp, command, data); 1160205869Sjfv break; 1161205869Sjfv } 1162205869Sjfv 1163205869Sjfv return (error); 1164205869Sjfv} 1165205869Sjfv 1166205869Sjfv 1167205869Sjfv/********************************************************************* 1168205869Sjfv * Init entry point 1169205869Sjfv * 1170205869Sjfv * This routine is used in two ways. It is used by the stack as 1171205869Sjfv * init entry point in network interface structure. It is also used 1172205869Sjfv * by the driver as a hw/sw initialization routine to get to a 1173205869Sjfv * consistent state. 1174205869Sjfv * 1175205869Sjfv * return 0 on success, positive on failure 1176205869Sjfv **********************************************************************/ 1177205869Sjfv 1178205869Sjfvstatic void 1179205869Sjfvlem_init_locked(struct adapter *adapter) 1180205869Sjfv{ 1181205869Sjfv struct ifnet *ifp = adapter->ifp; 1182205869Sjfv device_t dev = adapter->dev; 1183205869Sjfv u32 pba; 1184205869Sjfv 1185205869Sjfv INIT_DEBUGOUT("lem_init: begin"); 1186205869Sjfv 1187205869Sjfv EM_CORE_LOCK_ASSERT(adapter); 1188205869Sjfv 1189205869Sjfv EM_TX_LOCK(adapter); 1190205869Sjfv lem_stop(adapter); 1191205869Sjfv EM_TX_UNLOCK(adapter); 1192205869Sjfv 1193205869Sjfv /* 1194205869Sjfv * Packet Buffer Allocation (PBA) 1195205869Sjfv * Writing PBA sets the receive portion of the buffer 1196205869Sjfv * the remainder is used for the transmit buffer. 1197205869Sjfv * 1198205869Sjfv * Devices before the 82547 had a Packet Buffer of 64K. 1199205869Sjfv * Default allocation: PBA=48K for Rx, leaving 16K for Tx. 1200205869Sjfv * After the 82547 the buffer was reduced to 40K. 1201205869Sjfv * Default allocation: PBA=30K for Rx, leaving 10K for Tx. 1202205869Sjfv * Note: default does not leave enough room for Jumbo Frame >10k. 1203205869Sjfv */ 1204205869Sjfv switch (adapter->hw.mac.type) { 1205205869Sjfv case e1000_82547: 1206205869Sjfv case e1000_82547_rev_2: /* 82547: Total Packet Buffer is 40K */ 1207205869Sjfv if (adapter->max_frame_size > 8192) 1208205869Sjfv pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */ 1209205869Sjfv else 1210205869Sjfv pba = E1000_PBA_30K; /* 30K for Rx, 10K for Tx */ 1211205869Sjfv adapter->tx_fifo_head = 0; 1212205869Sjfv adapter->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT; 1213205869Sjfv adapter->tx_fifo_size = 1214205869Sjfv (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT; 1215205869Sjfv break; 1216205869Sjfv default: 1217205869Sjfv /* Devices before 82547 had a Packet Buffer of 64K. */ 1218205869Sjfv if (adapter->max_frame_size > 8192) 1219205869Sjfv pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */ 1220205869Sjfv else 1221205869Sjfv pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */ 1222205869Sjfv } 1223205869Sjfv 1224205869Sjfv INIT_DEBUGOUT1("lem_init: pba=%dK",pba); 1225205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_PBA, pba); 1226205869Sjfv 1227205869Sjfv /* Get the latest mac address, User can use a LAA */ 1228205869Sjfv bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr, 1229205869Sjfv ETHER_ADDR_LEN); 1230205869Sjfv 1231205869Sjfv /* Put the address into the Receive Address Array */ 1232205869Sjfv e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); 1233205869Sjfv 1234205869Sjfv /* Initialize the hardware */ 1235205869Sjfv if (lem_hardware_init(adapter)) { 1236205869Sjfv device_printf(dev, "Unable to initialize the hardware\n"); 1237205869Sjfv return; 1238205869Sjfv } 1239205869Sjfv lem_update_link_status(adapter); 1240205869Sjfv 1241205869Sjfv /* Setup VLAN support, basic and offload if available */ 1242205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN); 1243205869Sjfv 1244205869Sjfv /* Set hardware offload abilities */ 1245205869Sjfv ifp->if_hwassist = 0; 1246205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 1247205869Sjfv if (ifp->if_capenable & IFCAP_TXCSUM) 1248205869Sjfv ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); 1249205869Sjfv } 1250205869Sjfv 1251205869Sjfv /* Configure for OS presence */ 1252205869Sjfv lem_init_manageability(adapter); 1253205869Sjfv 1254205869Sjfv /* Prepare transmit descriptors and buffers */ 1255205869Sjfv lem_setup_transmit_structures(adapter); 1256205869Sjfv lem_initialize_transmit_unit(adapter); 1257205869Sjfv 1258205869Sjfv /* Setup Multicast table */ 1259205869Sjfv lem_set_multi(adapter); 1260205869Sjfv 1261205869Sjfv /* Prepare receive descriptors and buffers */ 1262205869Sjfv if (lem_setup_receive_structures(adapter)) { 1263205869Sjfv device_printf(dev, "Could not setup receive structures\n"); 1264205869Sjfv EM_TX_LOCK(adapter); 1265205869Sjfv lem_stop(adapter); 1266205869Sjfv EM_TX_UNLOCK(adapter); 1267205869Sjfv return; 1268205869Sjfv } 1269205869Sjfv lem_initialize_receive_unit(adapter); 1270205869Sjfv 1271214646Sjfv /* Use real VLAN Filter support? */ 1272214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { 1273214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 1274214646Sjfv /* Use real VLAN Filter support */ 1275214646Sjfv lem_setup_vlan_hw_support(adapter); 1276214646Sjfv else { 1277214646Sjfv u32 ctrl; 1278214646Sjfv ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); 1279214646Sjfv ctrl |= E1000_CTRL_VME; 1280214646Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); 1281214646Sjfv } 1282214646Sjfv } 1283214646Sjfv 1284205869Sjfv /* Don't lose promiscuous settings */ 1285205869Sjfv lem_set_promisc(adapter); 1286205869Sjfv 1287205869Sjfv ifp->if_drv_flags |= IFF_DRV_RUNNING; 1288205869Sjfv ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1289205869Sjfv 1290205869Sjfv callout_reset(&adapter->timer, hz, lem_local_timer, adapter); 1291205869Sjfv e1000_clear_hw_cntrs_base_generic(&adapter->hw); 1292205869Sjfv 1293205869Sjfv#ifdef DEVICE_POLLING 1294205869Sjfv /* 1295205869Sjfv * Only enable interrupts if we are not polling, make sure 1296205869Sjfv * they are off otherwise. 1297205869Sjfv */ 1298205869Sjfv if (ifp->if_capenable & IFCAP_POLLING) 1299205869Sjfv lem_disable_intr(adapter); 1300205869Sjfv else 1301205869Sjfv#endif /* DEVICE_POLLING */ 1302205869Sjfv lem_enable_intr(adapter); 1303205869Sjfv 1304205869Sjfv /* AMT based hardware can now take control from firmware */ 1305205869Sjfv if (adapter->has_manage && adapter->has_amt) 1306205869Sjfv lem_get_hw_control(adapter); 1307205869Sjfv} 1308205869Sjfv 1309205869Sjfvstatic void 1310205869Sjfvlem_init(void *arg) 1311205869Sjfv{ 1312205869Sjfv struct adapter *adapter = arg; 1313205869Sjfv 1314205869Sjfv EM_CORE_LOCK(adapter); 1315205869Sjfv lem_init_locked(adapter); 1316205869Sjfv EM_CORE_UNLOCK(adapter); 1317205869Sjfv} 1318205869Sjfv 1319205869Sjfv 1320205869Sjfv#ifdef DEVICE_POLLING 1321205869Sjfv/********************************************************************* 1322205869Sjfv * 1323205869Sjfv * Legacy polling routine 1324205869Sjfv * 1325205869Sjfv *********************************************************************/ 1326205869Sjfvstatic int 1327205869Sjfvlem_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 1328205869Sjfv{ 1329205869Sjfv struct adapter *adapter = ifp->if_softc; 1330205869Sjfv u32 reg_icr, rx_done = 0; 1331205869Sjfv 1332205869Sjfv EM_CORE_LOCK(adapter); 1333205869Sjfv if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1334205869Sjfv EM_CORE_UNLOCK(adapter); 1335205869Sjfv return (rx_done); 1336205869Sjfv } 1337205869Sjfv 1338205869Sjfv if (cmd == POLL_AND_CHECK_STATUS) { 1339205869Sjfv reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); 1340205869Sjfv if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 1341205869Sjfv callout_stop(&adapter->timer); 1342205869Sjfv adapter->hw.mac.get_link_status = 1; 1343205869Sjfv lem_update_link_status(adapter); 1344205869Sjfv callout_reset(&adapter->timer, hz, 1345205869Sjfv lem_local_timer, adapter); 1346205869Sjfv } 1347205869Sjfv } 1348205869Sjfv EM_CORE_UNLOCK(adapter); 1349205869Sjfv 1350209238Sjfv lem_rxeof(adapter, count, &rx_done); 1351205869Sjfv 1352205869Sjfv EM_TX_LOCK(adapter); 1353205869Sjfv lem_txeof(adapter); 1354205869Sjfv if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1355205869Sjfv lem_start_locked(ifp); 1356205869Sjfv EM_TX_UNLOCK(adapter); 1357205869Sjfv return (rx_done); 1358205869Sjfv} 1359205869Sjfv#endif /* DEVICE_POLLING */ 1360205869Sjfv 1361205869Sjfv/********************************************************************* 1362205869Sjfv * 1363205869Sjfv * Legacy Interrupt Service routine 1364205869Sjfv * 1365205869Sjfv *********************************************************************/ 1366205869Sjfvstatic void 1367205869Sjfvlem_intr(void *arg) 1368205869Sjfv{ 1369205869Sjfv struct adapter *adapter = arg; 1370205869Sjfv struct ifnet *ifp = adapter->ifp; 1371205869Sjfv u32 reg_icr; 1372205869Sjfv 1373205869Sjfv 1374238953Sjfv if ((ifp->if_capenable & IFCAP_POLLING) || 1375238953Sjfv ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)) 1376205869Sjfv return; 1377205869Sjfv 1378205869Sjfv EM_CORE_LOCK(adapter); 1379205869Sjfv reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); 1380205869Sjfv if (reg_icr & E1000_ICR_RXO) 1381205869Sjfv adapter->rx_overruns++; 1382205869Sjfv 1383238953Sjfv if ((reg_icr == 0xffffffff) || (reg_icr == 0)) { 1384238953Sjfv EM_CORE_UNLOCK(adapter); 1385238953Sjfv return; 1386238953Sjfv } 1387205869Sjfv 1388205869Sjfv if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 1389205869Sjfv callout_stop(&adapter->timer); 1390205869Sjfv adapter->hw.mac.get_link_status = 1; 1391205869Sjfv lem_update_link_status(adapter); 1392205869Sjfv /* Deal with TX cruft when link lost */ 1393205869Sjfv lem_tx_purge(adapter); 1394205869Sjfv callout_reset(&adapter->timer, hz, 1395205869Sjfv lem_local_timer, adapter); 1396238953Sjfv EM_CORE_UNLOCK(adapter); 1397238953Sjfv return; 1398205869Sjfv } 1399205869Sjfv 1400238953Sjfv EM_CORE_UNLOCK(adapter); 1401238953Sjfv lem_rxeof(adapter, -1, NULL); 1402238953Sjfv 1403205869Sjfv EM_TX_LOCK(adapter); 1404205869Sjfv lem_txeof(adapter); 1405205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING && 1406205869Sjfv !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1407205869Sjfv lem_start_locked(ifp); 1408205869Sjfv EM_TX_UNLOCK(adapter); 1409205869Sjfv return; 1410205869Sjfv} 1411205869Sjfv 1412205869Sjfv 1413205869Sjfvstatic void 1414205869Sjfvlem_handle_link(void *context, int pending) 1415205869Sjfv{ 1416205869Sjfv struct adapter *adapter = context; 1417205869Sjfv struct ifnet *ifp = adapter->ifp; 1418205869Sjfv 1419205869Sjfv if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 1420205869Sjfv return; 1421205869Sjfv 1422205869Sjfv EM_CORE_LOCK(adapter); 1423205869Sjfv callout_stop(&adapter->timer); 1424205869Sjfv lem_update_link_status(adapter); 1425205869Sjfv /* Deal with TX cruft when link lost */ 1426205869Sjfv lem_tx_purge(adapter); 1427205869Sjfv callout_reset(&adapter->timer, hz, lem_local_timer, adapter); 1428205869Sjfv EM_CORE_UNLOCK(adapter); 1429205869Sjfv} 1430205869Sjfv 1431205869Sjfv 1432205869Sjfv/* Combined RX/TX handler, used by Legacy and MSI */ 1433205869Sjfvstatic void 1434205869Sjfvlem_handle_rxtx(void *context, int pending) 1435205869Sjfv{ 1436205869Sjfv struct adapter *adapter = context; 1437205869Sjfv struct ifnet *ifp = adapter->ifp; 1438205869Sjfv 1439205869Sjfv 1440205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1441250414Sluigi bool more = lem_rxeof(adapter, adapter->rx_process_limit, NULL); 1442205869Sjfv EM_TX_LOCK(adapter); 1443205869Sjfv lem_txeof(adapter); 1444205869Sjfv if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1445205869Sjfv lem_start_locked(ifp); 1446205869Sjfv EM_TX_UNLOCK(adapter); 1447250414Sluigi if (more) { 1448250414Sluigi taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); 1449250414Sluigi return; 1450250414Sluigi } 1451205869Sjfv } 1452205869Sjfv 1453214646Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1454214646Sjfv lem_enable_intr(adapter); 1455205869Sjfv} 1456205869Sjfv 1457205869Sjfv/********************************************************************* 1458205869Sjfv * 1459205869Sjfv * Fast Legacy/MSI Combined Interrupt Service routine 1460205869Sjfv * 1461205869Sjfv *********************************************************************/ 1462205869Sjfvstatic int 1463205869Sjfvlem_irq_fast(void *arg) 1464205869Sjfv{ 1465205869Sjfv struct adapter *adapter = arg; 1466205869Sjfv struct ifnet *ifp; 1467205869Sjfv u32 reg_icr; 1468205869Sjfv 1469205869Sjfv ifp = adapter->ifp; 1470205869Sjfv 1471205869Sjfv reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); 1472205869Sjfv 1473205869Sjfv /* Hot eject? */ 1474205869Sjfv if (reg_icr == 0xffffffff) 1475205869Sjfv return FILTER_STRAY; 1476205869Sjfv 1477205869Sjfv /* Definitely not our interrupt. */ 1478205869Sjfv if (reg_icr == 0x0) 1479205869Sjfv return FILTER_STRAY; 1480205869Sjfv 1481205869Sjfv /* 1482205869Sjfv * Mask interrupts until the taskqueue is finished running. This is 1483205869Sjfv * cheap, just assume that it is needed. This also works around the 1484205869Sjfv * MSI message reordering errata on certain systems. 1485205869Sjfv */ 1486205869Sjfv lem_disable_intr(adapter); 1487205869Sjfv taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); 1488205869Sjfv 1489205869Sjfv /* Link status change */ 1490205869Sjfv if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 1491205869Sjfv adapter->hw.mac.get_link_status = 1; 1492205869Sjfv taskqueue_enqueue(taskqueue_fast, &adapter->link_task); 1493205869Sjfv } 1494205869Sjfv 1495205869Sjfv if (reg_icr & E1000_ICR_RXO) 1496205869Sjfv adapter->rx_overruns++; 1497205869Sjfv return FILTER_HANDLED; 1498205869Sjfv} 1499205869Sjfv 1500205869Sjfv 1501205869Sjfv/********************************************************************* 1502205869Sjfv * 1503205869Sjfv * Media Ioctl callback 1504205869Sjfv * 1505205869Sjfv * This routine is called whenever the user queries the status of 1506205869Sjfv * the interface using ifconfig. 1507205869Sjfv * 1508205869Sjfv **********************************************************************/ 1509205869Sjfvstatic void 1510205869Sjfvlem_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 1511205869Sjfv{ 1512205869Sjfv struct adapter *adapter = ifp->if_softc; 1513205869Sjfv u_char fiber_type = IFM_1000_SX; 1514205869Sjfv 1515205869Sjfv INIT_DEBUGOUT("lem_media_status: begin"); 1516205869Sjfv 1517205869Sjfv EM_CORE_LOCK(adapter); 1518205869Sjfv lem_update_link_status(adapter); 1519205869Sjfv 1520205869Sjfv ifmr->ifm_status = IFM_AVALID; 1521205869Sjfv ifmr->ifm_active = IFM_ETHER; 1522205869Sjfv 1523205869Sjfv if (!adapter->link_active) { 1524205869Sjfv EM_CORE_UNLOCK(adapter); 1525205869Sjfv return; 1526205869Sjfv } 1527205869Sjfv 1528205869Sjfv ifmr->ifm_status |= IFM_ACTIVE; 1529205869Sjfv 1530205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 1531205869Sjfv (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) { 1532205869Sjfv if (adapter->hw.mac.type == e1000_82545) 1533205869Sjfv fiber_type = IFM_1000_LX; 1534205869Sjfv ifmr->ifm_active |= fiber_type | IFM_FDX; 1535205869Sjfv } else { 1536205869Sjfv switch (adapter->link_speed) { 1537205869Sjfv case 10: 1538205869Sjfv ifmr->ifm_active |= IFM_10_T; 1539205869Sjfv break; 1540205869Sjfv case 100: 1541205869Sjfv ifmr->ifm_active |= IFM_100_TX; 1542205869Sjfv break; 1543205869Sjfv case 1000: 1544205869Sjfv ifmr->ifm_active |= IFM_1000_T; 1545205869Sjfv break; 1546205869Sjfv } 1547205869Sjfv if (adapter->link_duplex == FULL_DUPLEX) 1548205869Sjfv ifmr->ifm_active |= IFM_FDX; 1549205869Sjfv else 1550205869Sjfv ifmr->ifm_active |= IFM_HDX; 1551205869Sjfv } 1552205869Sjfv EM_CORE_UNLOCK(adapter); 1553205869Sjfv} 1554205869Sjfv 1555205869Sjfv/********************************************************************* 1556205869Sjfv * 1557205869Sjfv * Media Ioctl callback 1558205869Sjfv * 1559205869Sjfv * This routine is called when the user changes speed/duplex using 1560205869Sjfv * media/mediopt option with ifconfig. 1561205869Sjfv * 1562205869Sjfv **********************************************************************/ 1563205869Sjfvstatic int 1564205869Sjfvlem_media_change(struct ifnet *ifp) 1565205869Sjfv{ 1566205869Sjfv struct adapter *adapter = ifp->if_softc; 1567205869Sjfv struct ifmedia *ifm = &adapter->media; 1568205869Sjfv 1569205869Sjfv INIT_DEBUGOUT("lem_media_change: begin"); 1570205869Sjfv 1571205869Sjfv if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1572205869Sjfv return (EINVAL); 1573205869Sjfv 1574205869Sjfv EM_CORE_LOCK(adapter); 1575205869Sjfv switch (IFM_SUBTYPE(ifm->ifm_media)) { 1576205869Sjfv case IFM_AUTO: 1577205869Sjfv adapter->hw.mac.autoneg = DO_AUTO_NEG; 1578205869Sjfv adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; 1579205869Sjfv break; 1580205869Sjfv case IFM_1000_LX: 1581205869Sjfv case IFM_1000_SX: 1582205869Sjfv case IFM_1000_T: 1583205869Sjfv adapter->hw.mac.autoneg = DO_AUTO_NEG; 1584205869Sjfv adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; 1585205869Sjfv break; 1586205869Sjfv case IFM_100_TX: 1587205869Sjfv adapter->hw.mac.autoneg = FALSE; 1588205869Sjfv adapter->hw.phy.autoneg_advertised = 0; 1589205869Sjfv if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1590205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_FULL; 1591205869Sjfv else 1592205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_HALF; 1593205869Sjfv break; 1594205869Sjfv case IFM_10_T: 1595205869Sjfv adapter->hw.mac.autoneg = FALSE; 1596205869Sjfv adapter->hw.phy.autoneg_advertised = 0; 1597205869Sjfv if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1598205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_FULL; 1599205869Sjfv else 1600205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_HALF; 1601205869Sjfv break; 1602205869Sjfv default: 1603205869Sjfv device_printf(adapter->dev, "Unsupported media type\n"); 1604205869Sjfv } 1605205869Sjfv 1606205869Sjfv lem_init_locked(adapter); 1607205869Sjfv EM_CORE_UNLOCK(adapter); 1608205869Sjfv 1609205869Sjfv return (0); 1610205869Sjfv} 1611205869Sjfv 1612205869Sjfv/********************************************************************* 1613205869Sjfv * 1614205869Sjfv * This routine maps the mbufs to tx descriptors. 1615205869Sjfv * 1616205869Sjfv * return 0 on success, positive on failure 1617205869Sjfv **********************************************************************/ 1618205869Sjfv 1619205869Sjfvstatic int 1620205869Sjfvlem_xmit(struct adapter *adapter, struct mbuf **m_headp) 1621205869Sjfv{ 1622205869Sjfv bus_dma_segment_t segs[EM_MAX_SCATTER]; 1623205869Sjfv bus_dmamap_t map; 1624205869Sjfv struct em_buffer *tx_buffer, *tx_buffer_mapped; 1625205869Sjfv struct e1000_tx_desc *ctxd = NULL; 1626205869Sjfv struct mbuf *m_head; 1627205869Sjfv u32 txd_upper, txd_lower, txd_used, txd_saved; 1628205869Sjfv int error, nsegs, i, j, first, last = 0; 1629214646Sjfv 1630205869Sjfv m_head = *m_headp; 1631205869Sjfv txd_upper = txd_lower = txd_used = txd_saved = 0; 1632205869Sjfv 1633205869Sjfv /* 1634209959Sjfv ** When doing checksum offload, it is critical to 1635209959Sjfv ** make sure the first mbuf has more than header, 1636209959Sjfv ** because that routine expects data to be present. 1637209959Sjfv */ 1638209959Sjfv if ((m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) && 1639209959Sjfv (m_head->m_len < ETHER_HDR_LEN + sizeof(struct ip))) { 1640209959Sjfv m_head = m_pullup(m_head, ETHER_HDR_LEN + sizeof(struct ip)); 1641209959Sjfv *m_headp = m_head; 1642209959Sjfv if (m_head == NULL) 1643209959Sjfv return (ENOBUFS); 1644209959Sjfv } 1645209959Sjfv 1646209959Sjfv /* 1647205869Sjfv * Map the packet for DMA 1648205869Sjfv * 1649205869Sjfv * Capture the first descriptor index, 1650205869Sjfv * this descriptor will have the index 1651205869Sjfv * of the EOP which is the only one that 1652205869Sjfv * now gets a DONE bit writeback. 1653205869Sjfv */ 1654205869Sjfv first = adapter->next_avail_tx_desc; 1655205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 1656205869Sjfv tx_buffer_mapped = tx_buffer; 1657205869Sjfv map = tx_buffer->map; 1658205869Sjfv 1659205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, 1660205869Sjfv *m_headp, segs, &nsegs, BUS_DMA_NOWAIT); 1661205869Sjfv 1662205869Sjfv /* 1663205869Sjfv * There are two types of errors we can (try) to handle: 1664205869Sjfv * - EFBIG means the mbuf chain was too long and bus_dma ran 1665205869Sjfv * out of segments. Defragment the mbuf chain and try again. 1666205869Sjfv * - ENOMEM means bus_dma could not obtain enough bounce buffers 1667205869Sjfv * at this point in time. Defer sending and try again later. 1668205869Sjfv * All other errors, in particular EINVAL, are fatal and prevent the 1669205869Sjfv * mbuf chain from ever going through. Drop it and report error. 1670205869Sjfv */ 1671205869Sjfv if (error == EFBIG) { 1672205869Sjfv struct mbuf *m; 1673205869Sjfv 1674294958Smarius m = m_collapse(*m_headp, M_NOWAIT, EM_MAX_SCATTER); 1675205869Sjfv if (m == NULL) { 1676294958Smarius adapter->mbuf_defrag_failed++; 1677205869Sjfv m_freem(*m_headp); 1678205869Sjfv *m_headp = NULL; 1679205869Sjfv return (ENOBUFS); 1680205869Sjfv } 1681205869Sjfv *m_headp = m; 1682205869Sjfv 1683205869Sjfv /* Try it again */ 1684205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, 1685205869Sjfv *m_headp, segs, &nsegs, BUS_DMA_NOWAIT); 1686205869Sjfv 1687205869Sjfv if (error) { 1688205869Sjfv adapter->no_tx_dma_setup++; 1689205869Sjfv m_freem(*m_headp); 1690205869Sjfv *m_headp = NULL; 1691205869Sjfv return (error); 1692205869Sjfv } 1693205869Sjfv } else if (error != 0) { 1694205869Sjfv adapter->no_tx_dma_setup++; 1695205869Sjfv return (error); 1696205869Sjfv } 1697205869Sjfv 1698299192Ssbruno if (adapter->num_tx_desc_avail < (nsegs + 2)) { 1699205869Sjfv adapter->no_tx_desc_avail2++; 1700205869Sjfv bus_dmamap_unload(adapter->txtag, map); 1701205869Sjfv return (ENOBUFS); 1702205869Sjfv } 1703205869Sjfv m_head = *m_headp; 1704205869Sjfv 1705205869Sjfv /* Do hardware assists */ 1706205869Sjfv if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) 1707205869Sjfv lem_transmit_checksum_setup(adapter, m_head, 1708205869Sjfv &txd_upper, &txd_lower); 1709205869Sjfv 1710205869Sjfv i = adapter->next_avail_tx_desc; 1711205869Sjfv if (adapter->pcix_82544) 1712205869Sjfv txd_saved = i; 1713205869Sjfv 1714205869Sjfv /* Set up our transmit descriptors */ 1715205869Sjfv for (j = 0; j < nsegs; j++) { 1716205869Sjfv bus_size_t seg_len; 1717205869Sjfv bus_addr_t seg_addr; 1718205869Sjfv /* If adapter is 82544 and on PCIX bus */ 1719205869Sjfv if(adapter->pcix_82544) { 1720205869Sjfv DESC_ARRAY desc_array; 1721205869Sjfv u32 array_elements, counter; 1722205869Sjfv /* 1723205869Sjfv * Check the Address and Length combination and 1724205869Sjfv * split the data accordingly 1725205869Sjfv */ 1726205869Sjfv array_elements = lem_fill_descriptors(segs[j].ds_addr, 1727205869Sjfv segs[j].ds_len, &desc_array); 1728205869Sjfv for (counter = 0; counter < array_elements; counter++) { 1729205869Sjfv if (txd_used == adapter->num_tx_desc_avail) { 1730205869Sjfv adapter->next_avail_tx_desc = txd_saved; 1731205869Sjfv adapter->no_tx_desc_avail2++; 1732205869Sjfv bus_dmamap_unload(adapter->txtag, map); 1733205869Sjfv return (ENOBUFS); 1734205869Sjfv } 1735205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 1736205869Sjfv ctxd = &adapter->tx_desc_base[i]; 1737205869Sjfv ctxd->buffer_addr = htole64( 1738205869Sjfv desc_array.descriptor[counter].address); 1739205869Sjfv ctxd->lower.data = htole32( 1740205869Sjfv (adapter->txd_cmd | txd_lower | (u16) 1741205869Sjfv desc_array.descriptor[counter].length)); 1742205869Sjfv ctxd->upper.data = 1743205869Sjfv htole32((txd_upper)); 1744205869Sjfv last = i; 1745205869Sjfv if (++i == adapter->num_tx_desc) 1746205869Sjfv i = 0; 1747205869Sjfv tx_buffer->m_head = NULL; 1748205869Sjfv tx_buffer->next_eop = -1; 1749205869Sjfv txd_used++; 1750205869Sjfv } 1751205869Sjfv } else { 1752205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 1753205869Sjfv ctxd = &adapter->tx_desc_base[i]; 1754205869Sjfv seg_addr = segs[j].ds_addr; 1755205869Sjfv seg_len = segs[j].ds_len; 1756205869Sjfv ctxd->buffer_addr = htole64(seg_addr); 1757205869Sjfv ctxd->lower.data = htole32( 1758205869Sjfv adapter->txd_cmd | txd_lower | seg_len); 1759205869Sjfv ctxd->upper.data = 1760205869Sjfv htole32(txd_upper); 1761205869Sjfv last = i; 1762205869Sjfv if (++i == adapter->num_tx_desc) 1763205869Sjfv i = 0; 1764205869Sjfv tx_buffer->m_head = NULL; 1765205869Sjfv tx_buffer->next_eop = -1; 1766205869Sjfv } 1767205869Sjfv } 1768205869Sjfv 1769205869Sjfv adapter->next_avail_tx_desc = i; 1770205869Sjfv 1771205869Sjfv if (adapter->pcix_82544) 1772205869Sjfv adapter->num_tx_desc_avail -= txd_used; 1773205869Sjfv else 1774205869Sjfv adapter->num_tx_desc_avail -= nsegs; 1775205869Sjfv 1776205869Sjfv if (m_head->m_flags & M_VLANTAG) { 1777205869Sjfv /* Set the vlan id. */ 1778205869Sjfv ctxd->upper.fields.special = 1779205869Sjfv htole16(m_head->m_pkthdr.ether_vtag); 1780205869Sjfv /* Tell hardware to add tag */ 1781205869Sjfv ctxd->lower.data |= htole32(E1000_TXD_CMD_VLE); 1782205869Sjfv } 1783205869Sjfv 1784205869Sjfv tx_buffer->m_head = m_head; 1785205869Sjfv tx_buffer_mapped->map = tx_buffer->map; 1786205869Sjfv tx_buffer->map = map; 1787205869Sjfv bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE); 1788205869Sjfv 1789205869Sjfv /* 1790205869Sjfv * Last Descriptor of Packet 1791205869Sjfv * needs End Of Packet (EOP) 1792205869Sjfv * and Report Status (RS) 1793205869Sjfv */ 1794205869Sjfv ctxd->lower.data |= 1795205869Sjfv htole32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS); 1796205869Sjfv /* 1797205869Sjfv * Keep track in the first buffer which 1798205869Sjfv * descriptor will be written back 1799205869Sjfv */ 1800205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 1801205869Sjfv tx_buffer->next_eop = last; 1802213234Sjfv adapter->watchdog_time = ticks; 1803205869Sjfv 1804205869Sjfv /* 1805205869Sjfv * Advance the Transmit Descriptor Tail (TDT), this tells the E1000 1806205869Sjfv * that this frame is available to transmit. 1807205869Sjfv */ 1808205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 1809205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1810270252Sluigi 1811270252Sluigi#ifdef NIC_PARAVIRT 1812270252Sluigi if (adapter->csb) { 1813270252Sluigi adapter->csb->guest_tdt = i; 1814270252Sluigi /* XXX memory barrier ? */ 1815270252Sluigi if (adapter->csb->guest_csb_on && 1816270252Sluigi !(adapter->csb->host_need_txkick & 1)) { 1817270252Sluigi /* XXX maybe useless 1818270252Sluigi * clean the ring. maybe do it before ? 1819270252Sluigi * maybe a little bit of histeresys ? 1820270252Sluigi */ 1821270252Sluigi if (adapter->num_tx_desc_avail <= 64) {// XXX 1822270252Sluigi lem_txeof(adapter); 1823270252Sluigi } 1824270252Sluigi return (0); 1825270252Sluigi } 1826270252Sluigi } 1827270252Sluigi#endif /* NIC_PARAVIRT */ 1828270252Sluigi 1829270252Sluigi#ifdef NIC_SEND_COMBINING 1830270252Sluigi if (adapter->sc_enable) { 1831270252Sluigi if (adapter->shadow_tdt & MIT_PENDING_INT) { 1832270252Sluigi /* signal intr and data pending */ 1833270252Sluigi adapter->shadow_tdt = MIT_PENDING_TDT | (i & 0xffff); 1834270252Sluigi return (0); 1835270252Sluigi } else { 1836270252Sluigi adapter->shadow_tdt = MIT_PENDING_INT; 1837270252Sluigi } 1838270252Sluigi } 1839270252Sluigi#endif /* NIC_SEND_COMBINING */ 1840270252Sluigi 1841205869Sjfv if (adapter->hw.mac.type == e1000_82547 && 1842205869Sjfv adapter->link_duplex == HALF_DUPLEX) 1843205869Sjfv lem_82547_move_tail(adapter); 1844205869Sjfv else { 1845205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), i); 1846205869Sjfv if (adapter->hw.mac.type == e1000_82547) 1847205869Sjfv lem_82547_update_fifo_head(adapter, 1848205869Sjfv m_head->m_pkthdr.len); 1849205869Sjfv } 1850205869Sjfv 1851205869Sjfv return (0); 1852205869Sjfv} 1853205869Sjfv 1854205869Sjfv/********************************************************************* 1855205869Sjfv * 1856205869Sjfv * 82547 workaround to avoid controller hang in half-duplex environment. 1857205869Sjfv * The workaround is to avoid queuing a large packet that would span 1858205869Sjfv * the internal Tx FIFO ring boundary. We need to reset the FIFO pointers 1859205869Sjfv * in this case. We do that only when FIFO is quiescent. 1860205869Sjfv * 1861205869Sjfv **********************************************************************/ 1862205869Sjfvstatic void 1863205869Sjfvlem_82547_move_tail(void *arg) 1864205869Sjfv{ 1865205869Sjfv struct adapter *adapter = arg; 1866205869Sjfv struct e1000_tx_desc *tx_desc; 1867205869Sjfv u16 hw_tdt, sw_tdt, length = 0; 1868205869Sjfv bool eop = 0; 1869205869Sjfv 1870205869Sjfv EM_TX_LOCK_ASSERT(adapter); 1871205869Sjfv 1872205869Sjfv hw_tdt = E1000_READ_REG(&adapter->hw, E1000_TDT(0)); 1873205869Sjfv sw_tdt = adapter->next_avail_tx_desc; 1874205869Sjfv 1875205869Sjfv while (hw_tdt != sw_tdt) { 1876205869Sjfv tx_desc = &adapter->tx_desc_base[hw_tdt]; 1877205869Sjfv length += tx_desc->lower.flags.length; 1878205869Sjfv eop = tx_desc->lower.data & E1000_TXD_CMD_EOP; 1879205869Sjfv if (++hw_tdt == adapter->num_tx_desc) 1880205869Sjfv hw_tdt = 0; 1881205869Sjfv 1882205869Sjfv if (eop) { 1883205869Sjfv if (lem_82547_fifo_workaround(adapter, length)) { 1884205869Sjfv adapter->tx_fifo_wrk_cnt++; 1885205869Sjfv callout_reset(&adapter->tx_fifo_timer, 1, 1886205869Sjfv lem_82547_move_tail, adapter); 1887205869Sjfv break; 1888205869Sjfv } 1889205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), hw_tdt); 1890205869Sjfv lem_82547_update_fifo_head(adapter, length); 1891205869Sjfv length = 0; 1892205869Sjfv } 1893205869Sjfv } 1894205869Sjfv} 1895205869Sjfv 1896205869Sjfvstatic int 1897205869Sjfvlem_82547_fifo_workaround(struct adapter *adapter, int len) 1898205869Sjfv{ 1899205869Sjfv int fifo_space, fifo_pkt_len; 1900205869Sjfv 1901205869Sjfv fifo_pkt_len = roundup2(len + EM_FIFO_HDR, EM_FIFO_HDR); 1902205869Sjfv 1903205869Sjfv if (adapter->link_duplex == HALF_DUPLEX) { 1904205869Sjfv fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; 1905205869Sjfv 1906205869Sjfv if (fifo_pkt_len >= (EM_82547_PKT_THRESH + fifo_space)) { 1907205869Sjfv if (lem_82547_tx_fifo_reset(adapter)) 1908205869Sjfv return (0); 1909205869Sjfv else 1910205869Sjfv return (1); 1911205869Sjfv } 1912205869Sjfv } 1913205869Sjfv 1914205869Sjfv return (0); 1915205869Sjfv} 1916205869Sjfv 1917205869Sjfvstatic void 1918205869Sjfvlem_82547_update_fifo_head(struct adapter *adapter, int len) 1919205869Sjfv{ 1920205869Sjfv int fifo_pkt_len = roundup2(len + EM_FIFO_HDR, EM_FIFO_HDR); 1921205869Sjfv 1922205869Sjfv /* tx_fifo_head is always 16 byte aligned */ 1923205869Sjfv adapter->tx_fifo_head += fifo_pkt_len; 1924205869Sjfv if (adapter->tx_fifo_head >= adapter->tx_fifo_size) { 1925205869Sjfv adapter->tx_fifo_head -= adapter->tx_fifo_size; 1926205869Sjfv } 1927205869Sjfv} 1928205869Sjfv 1929205869Sjfv 1930205869Sjfvstatic int 1931205869Sjfvlem_82547_tx_fifo_reset(struct adapter *adapter) 1932205869Sjfv{ 1933205869Sjfv u32 tctl; 1934205869Sjfv 1935205869Sjfv if ((E1000_READ_REG(&adapter->hw, E1000_TDT(0)) == 1936205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDH(0))) && 1937205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_TDFT) == 1938205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDFH)) && 1939205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_TDFTS) == 1940205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDFHS)) && 1941205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_TDFPC) == 0)) { 1942205869Sjfv /* Disable TX unit */ 1943205869Sjfv tctl = E1000_READ_REG(&adapter->hw, E1000_TCTL); 1944205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, 1945205869Sjfv tctl & ~E1000_TCTL_EN); 1946205869Sjfv 1947205869Sjfv /* Reset FIFO pointers */ 1948205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFT, 1949205869Sjfv adapter->tx_head_addr); 1950205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFH, 1951205869Sjfv adapter->tx_head_addr); 1952205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFTS, 1953205869Sjfv adapter->tx_head_addr); 1954205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFHS, 1955205869Sjfv adapter->tx_head_addr); 1956205869Sjfv 1957205869Sjfv /* Re-enable TX unit */ 1958205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); 1959205869Sjfv E1000_WRITE_FLUSH(&adapter->hw); 1960205869Sjfv 1961205869Sjfv adapter->tx_fifo_head = 0; 1962205869Sjfv adapter->tx_fifo_reset_cnt++; 1963205869Sjfv 1964205869Sjfv return (TRUE); 1965205869Sjfv } 1966205869Sjfv else { 1967205869Sjfv return (FALSE); 1968205869Sjfv } 1969205869Sjfv} 1970205869Sjfv 1971205869Sjfvstatic void 1972205869Sjfvlem_set_promisc(struct adapter *adapter) 1973205869Sjfv{ 1974205869Sjfv struct ifnet *ifp = adapter->ifp; 1975205869Sjfv u32 reg_rctl; 1976205869Sjfv 1977205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 1978205869Sjfv 1979205869Sjfv if (ifp->if_flags & IFF_PROMISC) { 1980205869Sjfv reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); 1981205869Sjfv /* Turn this on if you want to see bad packets */ 1982205869Sjfv if (lem_debug_sbp) 1983205869Sjfv reg_rctl |= E1000_RCTL_SBP; 1984205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1985205869Sjfv } else if (ifp->if_flags & IFF_ALLMULTI) { 1986205869Sjfv reg_rctl |= E1000_RCTL_MPE; 1987205869Sjfv reg_rctl &= ~E1000_RCTL_UPE; 1988205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1989205869Sjfv } 1990205869Sjfv} 1991205869Sjfv 1992205869Sjfvstatic void 1993205869Sjfvlem_disable_promisc(struct adapter *adapter) 1994205869Sjfv{ 1995249074Sjfv struct ifnet *ifp = adapter->ifp; 1996249074Sjfv u32 reg_rctl; 1997249074Sjfv int mcnt = 0; 1998205869Sjfv 1999205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 2000205869Sjfv reg_rctl &= (~E1000_RCTL_UPE); 2001249074Sjfv if (ifp->if_flags & IFF_ALLMULTI) 2002249074Sjfv mcnt = MAX_NUM_MULTICAST_ADDRESSES; 2003249074Sjfv else { 2004249074Sjfv struct ifmultiaddr *ifma; 2005249074Sjfv#if __FreeBSD_version < 800000 2006249074Sjfv IF_ADDR_LOCK(ifp); 2007249074Sjfv#else 2008249074Sjfv if_maddr_rlock(ifp); 2009249074Sjfv#endif 2010249074Sjfv TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2011249074Sjfv if (ifma->ifma_addr->sa_family != AF_LINK) 2012249074Sjfv continue; 2013249074Sjfv if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 2014249074Sjfv break; 2015249074Sjfv mcnt++; 2016249074Sjfv } 2017249074Sjfv#if __FreeBSD_version < 800000 2018249074Sjfv IF_ADDR_UNLOCK(ifp); 2019249074Sjfv#else 2020249074Sjfv if_maddr_runlock(ifp); 2021249074Sjfv#endif 2022249074Sjfv } 2023249074Sjfv /* Don't disable if in MAX groups */ 2024249074Sjfv if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) 2025249074Sjfv reg_rctl &= (~E1000_RCTL_MPE); 2026205869Sjfv reg_rctl &= (~E1000_RCTL_SBP); 2027205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 2028205869Sjfv} 2029205869Sjfv 2030205869Sjfv 2031205869Sjfv/********************************************************************* 2032205869Sjfv * Multicast Update 2033205869Sjfv * 2034205869Sjfv * This routine is called whenever multicast address list is updated. 2035205869Sjfv * 2036205869Sjfv **********************************************************************/ 2037205869Sjfv 2038205869Sjfvstatic void 2039205869Sjfvlem_set_multi(struct adapter *adapter) 2040205869Sjfv{ 2041205869Sjfv struct ifnet *ifp = adapter->ifp; 2042205869Sjfv struct ifmultiaddr *ifma; 2043205869Sjfv u32 reg_rctl = 0; 2044205869Sjfv u8 *mta; /* Multicast array memory */ 2045205869Sjfv int mcnt = 0; 2046205869Sjfv 2047205869Sjfv IOCTL_DEBUGOUT("lem_set_multi: begin"); 2048205869Sjfv 2049211913Syongari mta = adapter->mta; 2050211913Syongari bzero(mta, sizeof(u8) * ETH_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES); 2051211913Syongari 2052205869Sjfv if (adapter->hw.mac.type == e1000_82542 && 2053205869Sjfv adapter->hw.revision_id == E1000_REVISION_2) { 2054205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 2055205869Sjfv if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) 2056205869Sjfv e1000_pci_clear_mwi(&adapter->hw); 2057205869Sjfv reg_rctl |= E1000_RCTL_RST; 2058205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 2059205869Sjfv msec_delay(5); 2060205869Sjfv } 2061205869Sjfv 2062205869Sjfv#if __FreeBSD_version < 800000 2063205869Sjfv IF_ADDR_LOCK(ifp); 2064205869Sjfv#else 2065205869Sjfv if_maddr_rlock(ifp); 2066205869Sjfv#endif 2067205869Sjfv TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2068205869Sjfv if (ifma->ifma_addr->sa_family != AF_LINK) 2069205869Sjfv continue; 2070205869Sjfv 2071205869Sjfv if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 2072205869Sjfv break; 2073205869Sjfv 2074205869Sjfv bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 2075205869Sjfv &mta[mcnt * ETH_ADDR_LEN], ETH_ADDR_LEN); 2076205869Sjfv mcnt++; 2077205869Sjfv } 2078205869Sjfv#if __FreeBSD_version < 800000 2079205869Sjfv IF_ADDR_UNLOCK(ifp); 2080205869Sjfv#else 2081205869Sjfv if_maddr_runlock(ifp); 2082205869Sjfv#endif 2083205869Sjfv if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) { 2084205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 2085205869Sjfv reg_rctl |= E1000_RCTL_MPE; 2086205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 2087205869Sjfv } else 2088205869Sjfv e1000_update_mc_addr_list(&adapter->hw, mta, mcnt); 2089205869Sjfv 2090205869Sjfv if (adapter->hw.mac.type == e1000_82542 && 2091205869Sjfv adapter->hw.revision_id == E1000_REVISION_2) { 2092205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 2093205869Sjfv reg_rctl &= ~E1000_RCTL_RST; 2094205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 2095205869Sjfv msec_delay(5); 2096205869Sjfv if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) 2097205869Sjfv e1000_pci_set_mwi(&adapter->hw); 2098205869Sjfv } 2099205869Sjfv} 2100205869Sjfv 2101205869Sjfv 2102205869Sjfv/********************************************************************* 2103205869Sjfv * Timer routine 2104205869Sjfv * 2105205869Sjfv * This routine checks for link status and updates statistics. 2106205869Sjfv * 2107205869Sjfv **********************************************************************/ 2108205869Sjfv 2109205869Sjfvstatic void 2110205869Sjfvlem_local_timer(void *arg) 2111205869Sjfv{ 2112205869Sjfv struct adapter *adapter = arg; 2113205869Sjfv 2114205869Sjfv EM_CORE_LOCK_ASSERT(adapter); 2115205869Sjfv 2116205869Sjfv lem_update_link_status(adapter); 2117205869Sjfv lem_update_stats_counters(adapter); 2118205869Sjfv 2119205869Sjfv lem_smartspeed(adapter); 2120205869Sjfv 2121270252Sluigi#ifdef NIC_PARAVIRT 2122270252Sluigi /* recover space if needed */ 2123270252Sluigi if (adapter->csb && adapter->csb->guest_csb_on && 2124270252Sluigi (adapter->watchdog_check == TRUE) && 2125270252Sluigi (ticks - adapter->watchdog_time > EM_WATCHDOG) && 2126270252Sluigi (adapter->num_tx_desc_avail != adapter->num_tx_desc) ) { 2127270252Sluigi lem_txeof(adapter); 2128270252Sluigi /* 2129270252Sluigi * lem_txeof() normally (except when space in the queue 2130270252Sluigi * runs low XXX) cleans watchdog_check so that 2131270252Sluigi * we do not hung. 2132270252Sluigi */ 2133270252Sluigi } 2134270252Sluigi#endif /* NIC_PARAVIRT */ 2135205869Sjfv /* 2136205869Sjfv * We check the watchdog: the time since 2137205869Sjfv * the last TX descriptor was cleaned. 2138205869Sjfv * This implies a functional TX engine. 2139205869Sjfv */ 2140205869Sjfv if ((adapter->watchdog_check == TRUE) && 2141205869Sjfv (ticks - adapter->watchdog_time > EM_WATCHDOG)) 2142205869Sjfv goto hung; 2143205869Sjfv 2144205869Sjfv callout_reset(&adapter->timer, hz, lem_local_timer, adapter); 2145205869Sjfv return; 2146205869Sjfvhung: 2147205869Sjfv device_printf(adapter->dev, "Watchdog timeout -- resetting\n"); 2148205869Sjfv adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 2149205869Sjfv adapter->watchdog_events++; 2150205869Sjfv lem_init_locked(adapter); 2151205869Sjfv} 2152205869Sjfv 2153205869Sjfvstatic void 2154205869Sjfvlem_update_link_status(struct adapter *adapter) 2155205869Sjfv{ 2156205869Sjfv struct e1000_hw *hw = &adapter->hw; 2157205869Sjfv struct ifnet *ifp = adapter->ifp; 2158205869Sjfv device_t dev = adapter->dev; 2159205869Sjfv u32 link_check = 0; 2160205869Sjfv 2161205869Sjfv /* Get the cached link value or read phy for real */ 2162205869Sjfv switch (hw->phy.media_type) { 2163205869Sjfv case e1000_media_type_copper: 2164205869Sjfv if (hw->mac.get_link_status) { 2165205869Sjfv /* Do the work to read phy */ 2166205869Sjfv e1000_check_for_link(hw); 2167205869Sjfv link_check = !hw->mac.get_link_status; 2168205869Sjfv if (link_check) /* ESB2 fix */ 2169205869Sjfv e1000_cfg_on_link_up(hw); 2170205869Sjfv } else 2171205869Sjfv link_check = TRUE; 2172205869Sjfv break; 2173205869Sjfv case e1000_media_type_fiber: 2174205869Sjfv e1000_check_for_link(hw); 2175205869Sjfv link_check = (E1000_READ_REG(hw, E1000_STATUS) & 2176205869Sjfv E1000_STATUS_LU); 2177205869Sjfv break; 2178205869Sjfv case e1000_media_type_internal_serdes: 2179205869Sjfv e1000_check_for_link(hw); 2180205869Sjfv link_check = adapter->hw.mac.serdes_has_link; 2181205869Sjfv break; 2182205869Sjfv default: 2183205869Sjfv case e1000_media_type_unknown: 2184205869Sjfv break; 2185205869Sjfv } 2186205869Sjfv 2187205869Sjfv /* Now check for a transition */ 2188205869Sjfv if (link_check && (adapter->link_active == 0)) { 2189205869Sjfv e1000_get_speed_and_duplex(hw, &adapter->link_speed, 2190205869Sjfv &adapter->link_duplex); 2191205869Sjfv if (bootverbose) 2192205869Sjfv device_printf(dev, "Link is up %d Mbps %s\n", 2193205869Sjfv adapter->link_speed, 2194205869Sjfv ((adapter->link_duplex == FULL_DUPLEX) ? 2195205869Sjfv "Full Duplex" : "Half Duplex")); 2196205869Sjfv adapter->link_active = 1; 2197205869Sjfv adapter->smartspeed = 0; 2198205869Sjfv ifp->if_baudrate = adapter->link_speed * 1000000; 2199205869Sjfv if_link_state_change(ifp, LINK_STATE_UP); 2200205869Sjfv } else if (!link_check && (adapter->link_active == 1)) { 2201205869Sjfv ifp->if_baudrate = adapter->link_speed = 0; 2202205869Sjfv adapter->link_duplex = 0; 2203205869Sjfv if (bootverbose) 2204205869Sjfv device_printf(dev, "Link is Down\n"); 2205205869Sjfv adapter->link_active = 0; 2206205869Sjfv /* Link down, disable watchdog */ 2207205869Sjfv adapter->watchdog_check = FALSE; 2208205869Sjfv if_link_state_change(ifp, LINK_STATE_DOWN); 2209205869Sjfv } 2210205869Sjfv} 2211205869Sjfv 2212205869Sjfv/********************************************************************* 2213205869Sjfv * 2214205869Sjfv * This routine disables all traffic on the adapter by issuing a 2215205869Sjfv * global reset on the MAC and deallocates TX/RX buffers. 2216205869Sjfv * 2217205869Sjfv * This routine should always be called with BOTH the CORE 2218205869Sjfv * and TX locks. 2219205869Sjfv **********************************************************************/ 2220205869Sjfv 2221205869Sjfvstatic void 2222205869Sjfvlem_stop(void *arg) 2223205869Sjfv{ 2224205869Sjfv struct adapter *adapter = arg; 2225205869Sjfv struct ifnet *ifp = adapter->ifp; 2226205869Sjfv 2227205869Sjfv EM_CORE_LOCK_ASSERT(adapter); 2228205869Sjfv EM_TX_LOCK_ASSERT(adapter); 2229205869Sjfv 2230205869Sjfv INIT_DEBUGOUT("lem_stop: begin"); 2231205869Sjfv 2232205869Sjfv lem_disable_intr(adapter); 2233205869Sjfv callout_stop(&adapter->timer); 2234205869Sjfv callout_stop(&adapter->tx_fifo_timer); 2235205869Sjfv 2236205869Sjfv /* Tell the stack that the interface is no longer active */ 2237205869Sjfv ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2238205869Sjfv 2239205869Sjfv e1000_reset_hw(&adapter->hw); 2240205869Sjfv if (adapter->hw.mac.type >= e1000_82544) 2241205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0); 2242206001Smarius 2243206001Smarius e1000_led_off(&adapter->hw); 2244206001Smarius e1000_cleanup_led(&adapter->hw); 2245205869Sjfv} 2246205869Sjfv 2247205869Sjfv 2248205869Sjfv/********************************************************************* 2249205869Sjfv * 2250205869Sjfv * Determine hardware revision. 2251205869Sjfv * 2252205869Sjfv **********************************************************************/ 2253205869Sjfvstatic void 2254205869Sjfvlem_identify_hardware(struct adapter *adapter) 2255205869Sjfv{ 2256205869Sjfv device_t dev = adapter->dev; 2257205869Sjfv 2258205869Sjfv /* Make sure our PCI config space has the necessary stuff set */ 2259254263Sscottl pci_enable_busmaster(dev); 2260205869Sjfv adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); 2261205869Sjfv 2262205869Sjfv /* Save off the information about this board */ 2263205869Sjfv adapter->hw.vendor_id = pci_get_vendor(dev); 2264205869Sjfv adapter->hw.device_id = pci_get_device(dev); 2265205869Sjfv adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1); 2266205869Sjfv adapter->hw.subsystem_vendor_id = 2267205869Sjfv pci_read_config(dev, PCIR_SUBVEND_0, 2); 2268205869Sjfv adapter->hw.subsystem_device_id = 2269205869Sjfv pci_read_config(dev, PCIR_SUBDEV_0, 2); 2270205869Sjfv 2271205869Sjfv /* Do Shared Code Init and Setup */ 2272205869Sjfv if (e1000_set_mac_type(&adapter->hw)) { 2273205869Sjfv device_printf(dev, "Setup init failure\n"); 2274205869Sjfv return; 2275205869Sjfv } 2276205869Sjfv} 2277205869Sjfv 2278205869Sjfvstatic int 2279205869Sjfvlem_allocate_pci_resources(struct adapter *adapter) 2280205869Sjfv{ 2281205869Sjfv device_t dev = adapter->dev; 2282205869Sjfv int val, rid, error = E1000_SUCCESS; 2283205869Sjfv 2284205869Sjfv rid = PCIR_BAR(0); 2285205869Sjfv adapter->memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 2286205869Sjfv &rid, RF_ACTIVE); 2287205869Sjfv if (adapter->memory == NULL) { 2288205869Sjfv device_printf(dev, "Unable to allocate bus resource: memory\n"); 2289205869Sjfv return (ENXIO); 2290205869Sjfv } 2291205869Sjfv adapter->osdep.mem_bus_space_tag = 2292205869Sjfv rman_get_bustag(adapter->memory); 2293205869Sjfv adapter->osdep.mem_bus_space_handle = 2294205869Sjfv rman_get_bushandle(adapter->memory); 2295205869Sjfv adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; 2296205869Sjfv 2297205869Sjfv /* Only older adapters use IO mapping */ 2298205869Sjfv if (adapter->hw.mac.type > e1000_82543) { 2299205869Sjfv /* Figure our where our IO BAR is ? */ 2300205869Sjfv for (rid = PCIR_BAR(0); rid < PCIR_CIS;) { 2301205869Sjfv val = pci_read_config(dev, rid, 4); 2302205869Sjfv if (EM_BAR_TYPE(val) == EM_BAR_TYPE_IO) { 2303205869Sjfv adapter->io_rid = rid; 2304205869Sjfv break; 2305205869Sjfv } 2306205869Sjfv rid += 4; 2307205869Sjfv /* check for 64bit BAR */ 2308205869Sjfv if (EM_BAR_MEM_TYPE(val) == EM_BAR_MEM_TYPE_64BIT) 2309205869Sjfv rid += 4; 2310205869Sjfv } 2311205869Sjfv if (rid >= PCIR_CIS) { 2312205869Sjfv device_printf(dev, "Unable to locate IO BAR\n"); 2313205869Sjfv return (ENXIO); 2314205869Sjfv } 2315205869Sjfv adapter->ioport = bus_alloc_resource_any(dev, 2316205869Sjfv SYS_RES_IOPORT, &adapter->io_rid, RF_ACTIVE); 2317205869Sjfv if (adapter->ioport == NULL) { 2318205869Sjfv device_printf(dev, "Unable to allocate bus resource: " 2319205869Sjfv "ioport\n"); 2320205869Sjfv return (ENXIO); 2321205869Sjfv } 2322205869Sjfv adapter->hw.io_base = 0; 2323205869Sjfv adapter->osdep.io_bus_space_tag = 2324205869Sjfv rman_get_bustag(adapter->ioport); 2325205869Sjfv adapter->osdep.io_bus_space_handle = 2326205869Sjfv rman_get_bushandle(adapter->ioport); 2327205869Sjfv } 2328205869Sjfv 2329205869Sjfv adapter->hw.back = &adapter->osdep; 2330205869Sjfv 2331205869Sjfv return (error); 2332205869Sjfv} 2333205869Sjfv 2334205869Sjfv/********************************************************************* 2335205869Sjfv * 2336205869Sjfv * Setup the Legacy or MSI Interrupt handler 2337205869Sjfv * 2338205869Sjfv **********************************************************************/ 2339323293Smariusstatic int 2340205869Sjfvlem_allocate_irq(struct adapter *adapter) 2341205869Sjfv{ 2342205869Sjfv device_t dev = adapter->dev; 2343205869Sjfv int error, rid = 0; 2344205869Sjfv 2345205869Sjfv /* Manually turn off all interrupts */ 2346205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff); 2347205869Sjfv 2348205869Sjfv /* We allocate a single interrupt resource */ 2349205869Sjfv adapter->res[0] = bus_alloc_resource_any(dev, 2350205869Sjfv SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); 2351205869Sjfv if (adapter->res[0] == NULL) { 2352205869Sjfv device_printf(dev, "Unable to allocate bus resource: " 2353205869Sjfv "interrupt\n"); 2354205869Sjfv return (ENXIO); 2355205869Sjfv } 2356205869Sjfv 2357238953Sjfv /* Do Legacy setup? */ 2358238953Sjfv if (lem_use_legacy_irq) { 2359238953Sjfv if ((error = bus_setup_intr(dev, adapter->res[0], 2360238953Sjfv INTR_TYPE_NET | INTR_MPSAFE, NULL, lem_intr, adapter, 2361238953Sjfv &adapter->tag[0])) != 0) { 2362238953Sjfv device_printf(dev, 2363238953Sjfv "Failed to register interrupt handler"); 2364238953Sjfv return (error); 2365238953Sjfv } 2366238953Sjfv return (0); 2367205869Sjfv } 2368205869Sjfv 2369205869Sjfv /* 2370238953Sjfv * Use a Fast interrupt and the associated 2371238953Sjfv * deferred processing contexts. 2372205869Sjfv */ 2373205869Sjfv TASK_INIT(&adapter->rxtx_task, 0, lem_handle_rxtx, adapter); 2374205869Sjfv TASK_INIT(&adapter->link_task, 0, lem_handle_link, adapter); 2375205869Sjfv adapter->tq = taskqueue_create_fast("lem_taskq", M_NOWAIT, 2376205869Sjfv taskqueue_thread_enqueue, &adapter->tq); 2377205869Sjfv taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq", 2378205869Sjfv device_get_nameunit(adapter->dev)); 2379205869Sjfv if ((error = bus_setup_intr(dev, adapter->res[0], 2380205869Sjfv INTR_TYPE_NET, lem_irq_fast, NULL, adapter, 2381205869Sjfv &adapter->tag[0])) != 0) { 2382205869Sjfv device_printf(dev, "Failed to register fast interrupt " 2383205869Sjfv "handler: %d\n", error); 2384205869Sjfv taskqueue_free(adapter->tq); 2385205869Sjfv adapter->tq = NULL; 2386205869Sjfv return (error); 2387205869Sjfv } 2388205869Sjfv 2389205869Sjfv return (0); 2390205869Sjfv} 2391205869Sjfv 2392205869Sjfv 2393205869Sjfvstatic void 2394205869Sjfvlem_free_pci_resources(struct adapter *adapter) 2395205869Sjfv{ 2396205869Sjfv device_t dev = adapter->dev; 2397205869Sjfv 2398205869Sjfv 2399205869Sjfv if (adapter->tag[0] != NULL) { 2400205869Sjfv bus_teardown_intr(dev, adapter->res[0], 2401205869Sjfv adapter->tag[0]); 2402205869Sjfv adapter->tag[0] = NULL; 2403205869Sjfv } 2404205869Sjfv 2405205869Sjfv if (adapter->res[0] != NULL) { 2406205869Sjfv bus_release_resource(dev, SYS_RES_IRQ, 2407205869Sjfv 0, adapter->res[0]); 2408205869Sjfv } 2409205869Sjfv 2410205869Sjfv if (adapter->memory != NULL) 2411205869Sjfv bus_release_resource(dev, SYS_RES_MEMORY, 2412205869Sjfv PCIR_BAR(0), adapter->memory); 2413205869Sjfv 2414205869Sjfv if (adapter->ioport != NULL) 2415205869Sjfv bus_release_resource(dev, SYS_RES_IOPORT, 2416205869Sjfv adapter->io_rid, adapter->ioport); 2417205869Sjfv} 2418205869Sjfv 2419205869Sjfv 2420205869Sjfv/********************************************************************* 2421205869Sjfv * 2422205869Sjfv * Initialize the hardware to a configuration 2423205869Sjfv * as specified by the adapter structure. 2424205869Sjfv * 2425205869Sjfv **********************************************************************/ 2426205869Sjfvstatic int 2427205869Sjfvlem_hardware_init(struct adapter *adapter) 2428205869Sjfv{ 2429205869Sjfv device_t dev = adapter->dev; 2430205869Sjfv u16 rx_buffer_size; 2431205869Sjfv 2432205869Sjfv INIT_DEBUGOUT("lem_hardware_init: begin"); 2433205869Sjfv 2434205869Sjfv /* Issue a global reset */ 2435205869Sjfv e1000_reset_hw(&adapter->hw); 2436205869Sjfv 2437205869Sjfv /* When hardware is reset, fifo_head is also reset */ 2438205869Sjfv adapter->tx_fifo_head = 0; 2439205869Sjfv 2440205869Sjfv /* 2441205869Sjfv * These parameters control the automatic generation (Tx) and 2442205869Sjfv * response (Rx) to Ethernet PAUSE frames. 2443205869Sjfv * - High water mark should allow for at least two frames to be 2444205869Sjfv * received after sending an XOFF. 2445205869Sjfv * - Low water mark works best when it is very near the high water mark. 2446205869Sjfv * This allows the receiver to restart by sending XON when it has 2447205869Sjfv * drained a bit. Here we use an arbitary value of 1500 which will 2448205869Sjfv * restart after one full frame is pulled from the buffer. There 2449205869Sjfv * could be several smaller frames in the buffer and if so they will 2450205869Sjfv * not trigger the XON until their total number reduces the buffer 2451205869Sjfv * by 1500. 2452205869Sjfv * - The pause time is fairly large at 1000 x 512ns = 512 usec. 2453205869Sjfv */ 2454205869Sjfv rx_buffer_size = ((E1000_READ_REG(&adapter->hw, E1000_PBA) & 2455205869Sjfv 0xffff) << 10 ); 2456205869Sjfv 2457205869Sjfv adapter->hw.fc.high_water = rx_buffer_size - 2458205869Sjfv roundup2(adapter->max_frame_size, 1024); 2459205869Sjfv adapter->hw.fc.low_water = adapter->hw.fc.high_water - 1500; 2460205869Sjfv 2461205869Sjfv adapter->hw.fc.pause_time = EM_FC_PAUSE_TIME; 2462205869Sjfv adapter->hw.fc.send_xon = TRUE; 2463205869Sjfv 2464205869Sjfv /* Set Flow control, use the tunable location if sane */ 2465214646Sjfv if ((lem_fc_setting >= 0) && (lem_fc_setting < 4)) 2466205869Sjfv adapter->hw.fc.requested_mode = lem_fc_setting; 2467205869Sjfv else 2468205869Sjfv adapter->hw.fc.requested_mode = e1000_fc_none; 2469205869Sjfv 2470205869Sjfv if (e1000_init_hw(&adapter->hw) < 0) { 2471205869Sjfv device_printf(dev, "Hardware Initialization Failed\n"); 2472205869Sjfv return (EIO); 2473205869Sjfv } 2474205869Sjfv 2475205869Sjfv e1000_check_for_link(&adapter->hw); 2476205869Sjfv 2477205869Sjfv return (0); 2478205869Sjfv} 2479205869Sjfv 2480205869Sjfv/********************************************************************* 2481205869Sjfv * 2482205869Sjfv * Setup networking device structure and register an interface. 2483205869Sjfv * 2484205869Sjfv **********************************************************************/ 2485211907Syongaristatic int 2486205869Sjfvlem_setup_interface(device_t dev, struct adapter *adapter) 2487205869Sjfv{ 2488205869Sjfv struct ifnet *ifp; 2489205869Sjfv 2490205869Sjfv INIT_DEBUGOUT("lem_setup_interface: begin"); 2491205869Sjfv 2492205869Sjfv ifp = adapter->ifp = if_alloc(IFT_ETHER); 2493211907Syongari if (ifp == NULL) { 2494211907Syongari device_printf(dev, "can not allocate ifnet structure\n"); 2495211907Syongari return (-1); 2496211907Syongari } 2497205869Sjfv if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 2498205869Sjfv ifp->if_init = lem_init; 2499205869Sjfv ifp->if_softc = adapter; 2500205869Sjfv ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 2501205869Sjfv ifp->if_ioctl = lem_ioctl; 2502205869Sjfv ifp->if_start = lem_start; 2503205869Sjfv IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1); 2504205869Sjfv ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1; 2505205869Sjfv IFQ_SET_READY(&ifp->if_snd); 2506205869Sjfv 2507205869Sjfv ether_ifattach(ifp, adapter->hw.mac.addr); 2508205869Sjfv 2509205869Sjfv ifp->if_capabilities = ifp->if_capenable = 0; 2510205869Sjfv 2511205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 2512214646Sjfv ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; 2513214646Sjfv ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; 2514205869Sjfv } 2515205869Sjfv 2516205869Sjfv /* 2517205869Sjfv * Tell the upper layer(s) we support long frames. 2518205869Sjfv */ 2519205869Sjfv ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 2520205869Sjfv ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 2521205869Sjfv ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 2522205869Sjfv 2523214646Sjfv /* 2524214646Sjfv ** Dont turn this on by default, if vlans are 2525214646Sjfv ** created on another pseudo device (eg. lagg) 2526214646Sjfv ** then vlan events are not passed thru, breaking 2527214646Sjfv ** operation, but with HW FILTER off it works. If 2528214646Sjfv ** using vlans directly on the em driver you can 2529214646Sjfv ** enable this and get full hardware tag filtering. 2530214646Sjfv */ 2531214646Sjfv ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; 2532214646Sjfv 2533205869Sjfv#ifdef DEVICE_POLLING 2534205869Sjfv ifp->if_capabilities |= IFCAP_POLLING; 2535205869Sjfv#endif 2536205869Sjfv 2537208103Sjfv /* Enable only WOL MAGIC by default */ 2538205869Sjfv if (adapter->wol) { 2539205869Sjfv ifp->if_capabilities |= IFCAP_WOL; 2540208103Sjfv ifp->if_capenable |= IFCAP_WOL_MAGIC; 2541205869Sjfv } 2542205869Sjfv 2543205869Sjfv /* 2544205869Sjfv * Specify the media types supported by this adapter and register 2545205869Sjfv * callbacks to update media and link information 2546205869Sjfv */ 2547205869Sjfv ifmedia_init(&adapter->media, IFM_IMASK, 2548205869Sjfv lem_media_change, lem_media_status); 2549205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 2550205869Sjfv (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) { 2551205869Sjfv u_char fiber_type = IFM_1000_SX; /* default type */ 2552205869Sjfv 2553205869Sjfv if (adapter->hw.mac.type == e1000_82545) 2554205869Sjfv fiber_type = IFM_1000_LX; 2555205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | fiber_type | IFM_FDX, 2556205869Sjfv 0, NULL); 2557205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | fiber_type, 0, NULL); 2558205869Sjfv } else { 2559205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); 2560205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX, 2561205869Sjfv 0, NULL); 2562205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, 2563205869Sjfv 0, NULL); 2564205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 2565205869Sjfv 0, NULL); 2566205869Sjfv if (adapter->hw.phy.type != e1000_phy_ife) { 2567205869Sjfv ifmedia_add(&adapter->media, 2568205869Sjfv IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); 2569205869Sjfv ifmedia_add(&adapter->media, 2570205869Sjfv IFM_ETHER | IFM_1000_T, 0, NULL); 2571205869Sjfv } 2572205869Sjfv } 2573205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); 2574205869Sjfv ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); 2575211907Syongari return (0); 2576205869Sjfv} 2577205869Sjfv 2578205869Sjfv 2579205869Sjfv/********************************************************************* 2580205869Sjfv * 2581205869Sjfv * Workaround for SmartSpeed on 82541 and 82547 controllers 2582205869Sjfv * 2583205869Sjfv **********************************************************************/ 2584205869Sjfvstatic void 2585205869Sjfvlem_smartspeed(struct adapter *adapter) 2586205869Sjfv{ 2587205869Sjfv u16 phy_tmp; 2588205869Sjfv 2589205869Sjfv if (adapter->link_active || (adapter->hw.phy.type != e1000_phy_igp) || 2590205869Sjfv adapter->hw.mac.autoneg == 0 || 2591205869Sjfv (adapter->hw.phy.autoneg_advertised & ADVERTISE_1000_FULL) == 0) 2592205869Sjfv return; 2593205869Sjfv 2594205869Sjfv if (adapter->smartspeed == 0) { 2595205869Sjfv /* If Master/Slave config fault is asserted twice, 2596205869Sjfv * we assume back-to-back */ 2597205869Sjfv e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp); 2598205869Sjfv if (!(phy_tmp & SR_1000T_MS_CONFIG_FAULT)) 2599205869Sjfv return; 2600205869Sjfv e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp); 2601205869Sjfv if (phy_tmp & SR_1000T_MS_CONFIG_FAULT) { 2602205869Sjfv e1000_read_phy_reg(&adapter->hw, 2603205869Sjfv PHY_1000T_CTRL, &phy_tmp); 2604205869Sjfv if(phy_tmp & CR_1000T_MS_ENABLE) { 2605205869Sjfv phy_tmp &= ~CR_1000T_MS_ENABLE; 2606205869Sjfv e1000_write_phy_reg(&adapter->hw, 2607205869Sjfv PHY_1000T_CTRL, phy_tmp); 2608205869Sjfv adapter->smartspeed++; 2609205869Sjfv if(adapter->hw.mac.autoneg && 2610205869Sjfv !e1000_copper_link_autoneg(&adapter->hw) && 2611205869Sjfv !e1000_read_phy_reg(&adapter->hw, 2612205869Sjfv PHY_CONTROL, &phy_tmp)) { 2613205869Sjfv phy_tmp |= (MII_CR_AUTO_NEG_EN | 2614205869Sjfv MII_CR_RESTART_AUTO_NEG); 2615205869Sjfv e1000_write_phy_reg(&adapter->hw, 2616205869Sjfv PHY_CONTROL, phy_tmp); 2617205869Sjfv } 2618205869Sjfv } 2619205869Sjfv } 2620205869Sjfv return; 2621205869Sjfv } else if(adapter->smartspeed == EM_SMARTSPEED_DOWNSHIFT) { 2622205869Sjfv /* If still no link, perhaps using 2/3 pair cable */ 2623205869Sjfv e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_tmp); 2624205869Sjfv phy_tmp |= CR_1000T_MS_ENABLE; 2625205869Sjfv e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_tmp); 2626205869Sjfv if(adapter->hw.mac.autoneg && 2627205869Sjfv !e1000_copper_link_autoneg(&adapter->hw) && 2628205869Sjfv !e1000_read_phy_reg(&adapter->hw, PHY_CONTROL, &phy_tmp)) { 2629205869Sjfv phy_tmp |= (MII_CR_AUTO_NEG_EN | 2630205869Sjfv MII_CR_RESTART_AUTO_NEG); 2631205869Sjfv e1000_write_phy_reg(&adapter->hw, PHY_CONTROL, phy_tmp); 2632205869Sjfv } 2633205869Sjfv } 2634205869Sjfv /* Restart process after EM_SMARTSPEED_MAX iterations */ 2635205869Sjfv if(adapter->smartspeed++ == EM_SMARTSPEED_MAX) 2636205869Sjfv adapter->smartspeed = 0; 2637205869Sjfv} 2638205869Sjfv 2639205869Sjfv 2640205869Sjfv/* 2641205869Sjfv * Manage DMA'able memory. 2642205869Sjfv */ 2643205869Sjfvstatic void 2644205869Sjfvlem_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2645205869Sjfv{ 2646205869Sjfv if (error) 2647205869Sjfv return; 2648205869Sjfv *(bus_addr_t *) arg = segs[0].ds_addr; 2649205869Sjfv} 2650205869Sjfv 2651205869Sjfvstatic int 2652205869Sjfvlem_dma_malloc(struct adapter *adapter, bus_size_t size, 2653205869Sjfv struct em_dma_alloc *dma, int mapflags) 2654205869Sjfv{ 2655205869Sjfv int error; 2656205869Sjfv 2657205869Sjfv error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */ 2658205869Sjfv EM_DBA_ALIGN, 0, /* alignment, bounds */ 2659205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 2660205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 2661205869Sjfv NULL, NULL, /* filter, filterarg */ 2662205869Sjfv size, /* maxsize */ 2663205869Sjfv 1, /* nsegments */ 2664205869Sjfv size, /* maxsegsize */ 2665205869Sjfv 0, /* flags */ 2666205869Sjfv NULL, /* lockfunc */ 2667205869Sjfv NULL, /* lockarg */ 2668205869Sjfv &dma->dma_tag); 2669205869Sjfv if (error) { 2670205869Sjfv device_printf(adapter->dev, 2671205869Sjfv "%s: bus_dma_tag_create failed: %d\n", 2672205869Sjfv __func__, error); 2673205869Sjfv goto fail_0; 2674205869Sjfv } 2675205869Sjfv 2676205869Sjfv error = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr, 2677205869Sjfv BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map); 2678205869Sjfv if (error) { 2679205869Sjfv device_printf(adapter->dev, 2680205869Sjfv "%s: bus_dmamem_alloc(%ju) failed: %d\n", 2681205869Sjfv __func__, (uintmax_t)size, error); 2682205869Sjfv goto fail_2; 2683205869Sjfv } 2684205869Sjfv 2685205869Sjfv dma->dma_paddr = 0; 2686205869Sjfv error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, 2687205869Sjfv size, lem_dmamap_cb, &dma->dma_paddr, mapflags | BUS_DMA_NOWAIT); 2688205869Sjfv if (error || dma->dma_paddr == 0) { 2689205869Sjfv device_printf(adapter->dev, 2690205869Sjfv "%s: bus_dmamap_load failed: %d\n", 2691205869Sjfv __func__, error); 2692205869Sjfv goto fail_3; 2693205869Sjfv } 2694205869Sjfv 2695205869Sjfv return (0); 2696205869Sjfv 2697205869Sjfvfail_3: 2698205869Sjfv bus_dmamap_unload(dma->dma_tag, dma->dma_map); 2699205869Sjfvfail_2: 2700205869Sjfv bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 2701205869Sjfv bus_dma_tag_destroy(dma->dma_tag); 2702205869Sjfvfail_0: 2703205869Sjfv dma->dma_tag = NULL; 2704205869Sjfv 2705205869Sjfv return (error); 2706205869Sjfv} 2707205869Sjfv 2708205869Sjfvstatic void 2709205869Sjfvlem_dma_free(struct adapter *adapter, struct em_dma_alloc *dma) 2710205869Sjfv{ 2711205869Sjfv if (dma->dma_tag == NULL) 2712205869Sjfv return; 2713294958Smarius if (dma->dma_paddr != 0) { 2714205869Sjfv bus_dmamap_sync(dma->dma_tag, dma->dma_map, 2715205869Sjfv BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2716205869Sjfv bus_dmamap_unload(dma->dma_tag, dma->dma_map); 2717294958Smarius dma->dma_paddr = 0; 2718294958Smarius } 2719294958Smarius if (dma->dma_vaddr != NULL) { 2720205869Sjfv bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 2721294958Smarius dma->dma_vaddr = NULL; 2722205869Sjfv } 2723205869Sjfv bus_dma_tag_destroy(dma->dma_tag); 2724205869Sjfv dma->dma_tag = NULL; 2725205869Sjfv} 2726205869Sjfv 2727205869Sjfv 2728205869Sjfv/********************************************************************* 2729205869Sjfv * 2730205869Sjfv * Allocate memory for tx_buffer structures. The tx_buffer stores all 2731205869Sjfv * the information needed to transmit a packet on the wire. 2732205869Sjfv * 2733205869Sjfv **********************************************************************/ 2734205869Sjfvstatic int 2735205869Sjfvlem_allocate_transmit_structures(struct adapter *adapter) 2736205869Sjfv{ 2737205869Sjfv device_t dev = adapter->dev; 2738205869Sjfv struct em_buffer *tx_buffer; 2739205869Sjfv int error; 2740205869Sjfv 2741205869Sjfv /* 2742205869Sjfv * Create DMA tags for tx descriptors 2743205869Sjfv */ 2744205869Sjfv if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 2745205869Sjfv 1, 0, /* alignment, bounds */ 2746205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 2747205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 2748205869Sjfv NULL, NULL, /* filter, filterarg */ 2749214646Sjfv MCLBYTES * EM_MAX_SCATTER, /* maxsize */ 2750205869Sjfv EM_MAX_SCATTER, /* nsegments */ 2751214646Sjfv MCLBYTES, /* maxsegsize */ 2752205869Sjfv 0, /* flags */ 2753214646Sjfv NULL, /* lockfunc */ 2754214646Sjfv NULL, /* lockarg */ 2755205869Sjfv &adapter->txtag)) != 0) { 2756205869Sjfv device_printf(dev, "Unable to allocate TX DMA tag\n"); 2757205869Sjfv goto fail; 2758205869Sjfv } 2759205869Sjfv 2760205869Sjfv adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) * 2761205869Sjfv adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); 2762205869Sjfv if (adapter->tx_buffer_area == NULL) { 2763205869Sjfv device_printf(dev, "Unable to allocate tx_buffer memory\n"); 2764205869Sjfv error = ENOMEM; 2765205869Sjfv goto fail; 2766205869Sjfv } 2767205869Sjfv 2768205869Sjfv /* Create the descriptor buffer dma maps */ 2769205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++) { 2770205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2771205869Sjfv error = bus_dmamap_create(adapter->txtag, 0, &tx_buffer->map); 2772205869Sjfv if (error != 0) { 2773205869Sjfv device_printf(dev, "Unable to create TX DMA map\n"); 2774205869Sjfv goto fail; 2775205869Sjfv } 2776205869Sjfv tx_buffer->next_eop = -1; 2777205869Sjfv } 2778205869Sjfv 2779205869Sjfv return (0); 2780205869Sjfvfail: 2781205869Sjfv lem_free_transmit_structures(adapter); 2782205869Sjfv return (error); 2783205869Sjfv} 2784205869Sjfv 2785205869Sjfv/********************************************************************* 2786205869Sjfv * 2787205869Sjfv * (Re)Initialize transmit structures. 2788205869Sjfv * 2789205869Sjfv **********************************************************************/ 2790205869Sjfvstatic void 2791205869Sjfvlem_setup_transmit_structures(struct adapter *adapter) 2792205869Sjfv{ 2793205869Sjfv struct em_buffer *tx_buffer; 2794228281Sluigi#ifdef DEV_NETMAP 2795228281Sluigi /* we are already locked */ 2796228281Sluigi struct netmap_adapter *na = NA(adapter->ifp); 2797228281Sluigi struct netmap_slot *slot = netmap_reset(na, NR_TX, 0, 0); 2798228281Sluigi#endif /* DEV_NETMAP */ 2799205869Sjfv 2800205869Sjfv /* Clear the old ring contents */ 2801205869Sjfv bzero(adapter->tx_desc_base, 2802205869Sjfv (sizeof(struct e1000_tx_desc)) * adapter->num_tx_desc); 2803205869Sjfv 2804205869Sjfv /* Free any existing TX buffers */ 2805205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) { 2806205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2807205869Sjfv bus_dmamap_sync(adapter->txtag, tx_buffer->map, 2808205869Sjfv BUS_DMASYNC_POSTWRITE); 2809205869Sjfv bus_dmamap_unload(adapter->txtag, tx_buffer->map); 2810205869Sjfv m_freem(tx_buffer->m_head); 2811205869Sjfv tx_buffer->m_head = NULL; 2812228281Sluigi#ifdef DEV_NETMAP 2813228281Sluigi if (slot) { 2814231796Sluigi /* the i-th NIC entry goes to slot si */ 2815232238Sluigi int si = netmap_idx_n2k(&na->tx_rings[0], i); 2816229939Sluigi uint64_t paddr; 2817228281Sluigi void *addr; 2818228281Sluigi 2819270252Sluigi addr = PNMB(na, slot + si, &paddr); 2820270235Sluigi adapter->tx_desc_base[i].buffer_addr = htole64(paddr); 2821228281Sluigi /* reload the map for netmap mode */ 2822270252Sluigi netmap_load_map(na, adapter->txtag, tx_buffer->map, addr); 2823228281Sluigi } 2824228281Sluigi#endif /* DEV_NETMAP */ 2825205869Sjfv tx_buffer->next_eop = -1; 2826205869Sjfv } 2827205869Sjfv 2828205869Sjfv /* Reset state */ 2829225640Srstone adapter->last_hw_offload = 0; 2830205869Sjfv adapter->next_avail_tx_desc = 0; 2831205869Sjfv adapter->next_tx_to_clean = 0; 2832205869Sjfv adapter->num_tx_desc_avail = adapter->num_tx_desc; 2833205869Sjfv 2834205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 2835205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2836205869Sjfv 2837205869Sjfv return; 2838205869Sjfv} 2839205869Sjfv 2840205869Sjfv/********************************************************************* 2841205869Sjfv * 2842205869Sjfv * Enable transmit unit. 2843205869Sjfv * 2844205869Sjfv **********************************************************************/ 2845205869Sjfvstatic void 2846205869Sjfvlem_initialize_transmit_unit(struct adapter *adapter) 2847205869Sjfv{ 2848205869Sjfv u32 tctl, tipg = 0; 2849205869Sjfv u64 bus_addr; 2850205869Sjfv 2851205869Sjfv INIT_DEBUGOUT("lem_initialize_transmit_unit: begin"); 2852205869Sjfv /* Setup the Base and Length of the Tx Descriptor Ring */ 2853205869Sjfv bus_addr = adapter->txdma.dma_paddr; 2854205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDLEN(0), 2855205869Sjfv adapter->num_tx_desc * sizeof(struct e1000_tx_desc)); 2856205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDBAH(0), 2857205869Sjfv (u32)(bus_addr >> 32)); 2858205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDBAL(0), 2859205869Sjfv (u32)bus_addr); 2860205869Sjfv /* Setup the HW Tx Head and Tail descriptor pointers */ 2861205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0); 2862205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDH(0), 0); 2863205869Sjfv 2864205869Sjfv HW_DEBUGOUT2("Base = %x, Length = %x\n", 2865205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDBAL(0)), 2866205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDLEN(0))); 2867205869Sjfv 2868205869Sjfv /* Set the default values for the Tx Inter Packet Gap timer */ 2869205869Sjfv switch (adapter->hw.mac.type) { 2870205869Sjfv case e1000_82542: 2871205869Sjfv tipg = DEFAULT_82542_TIPG_IPGT; 2872205869Sjfv tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 2873205869Sjfv tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 2874205869Sjfv break; 2875205869Sjfv default: 2876205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 2877205869Sjfv (adapter->hw.phy.media_type == 2878205869Sjfv e1000_media_type_internal_serdes)) 2879205869Sjfv tipg = DEFAULT_82543_TIPG_IPGT_FIBER; 2880205869Sjfv else 2881205869Sjfv tipg = DEFAULT_82543_TIPG_IPGT_COPPER; 2882205869Sjfv tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 2883205869Sjfv tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 2884205869Sjfv } 2885205869Sjfv 2886205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TIPG, tipg); 2887205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TIDV, adapter->tx_int_delay.value); 2888205869Sjfv if(adapter->hw.mac.type >= e1000_82540) 2889205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TADV, 2890205869Sjfv adapter->tx_abs_int_delay.value); 2891205869Sjfv 2892205869Sjfv /* Program the Transmit Control Register */ 2893205869Sjfv tctl = E1000_READ_REG(&adapter->hw, E1000_TCTL); 2894205869Sjfv tctl &= ~E1000_TCTL_CT; 2895205869Sjfv tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN | 2896205869Sjfv (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); 2897205869Sjfv 2898205869Sjfv /* This write will effectively turn on the transmit unit. */ 2899205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); 2900205869Sjfv 2901205869Sjfv /* Setup Transmit Descriptor Base Settings */ 2902205869Sjfv adapter->txd_cmd = E1000_TXD_CMD_IFCS; 2903205869Sjfv 2904205869Sjfv if (adapter->tx_int_delay.value > 0) 2905205869Sjfv adapter->txd_cmd |= E1000_TXD_CMD_IDE; 2906205869Sjfv} 2907205869Sjfv 2908205869Sjfv/********************************************************************* 2909205869Sjfv * 2910205869Sjfv * Free all transmit related data structures. 2911205869Sjfv * 2912205869Sjfv **********************************************************************/ 2913205869Sjfvstatic void 2914205869Sjfvlem_free_transmit_structures(struct adapter *adapter) 2915205869Sjfv{ 2916205869Sjfv struct em_buffer *tx_buffer; 2917205869Sjfv 2918205869Sjfv INIT_DEBUGOUT("free_transmit_structures: begin"); 2919205869Sjfv 2920205869Sjfv if (adapter->tx_buffer_area != NULL) { 2921205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++) { 2922205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2923205869Sjfv if (tx_buffer->m_head != NULL) { 2924205869Sjfv bus_dmamap_sync(adapter->txtag, tx_buffer->map, 2925205869Sjfv BUS_DMASYNC_POSTWRITE); 2926205869Sjfv bus_dmamap_unload(adapter->txtag, 2927205869Sjfv tx_buffer->map); 2928205869Sjfv m_freem(tx_buffer->m_head); 2929205869Sjfv tx_buffer->m_head = NULL; 2930205869Sjfv } else if (tx_buffer->map != NULL) 2931205869Sjfv bus_dmamap_unload(adapter->txtag, 2932205869Sjfv tx_buffer->map); 2933205869Sjfv if (tx_buffer->map != NULL) { 2934205869Sjfv bus_dmamap_destroy(adapter->txtag, 2935205869Sjfv tx_buffer->map); 2936205869Sjfv tx_buffer->map = NULL; 2937205869Sjfv } 2938205869Sjfv } 2939205869Sjfv } 2940205869Sjfv if (adapter->tx_buffer_area != NULL) { 2941205869Sjfv free(adapter->tx_buffer_area, M_DEVBUF); 2942205869Sjfv adapter->tx_buffer_area = NULL; 2943205869Sjfv } 2944205869Sjfv if (adapter->txtag != NULL) { 2945205869Sjfv bus_dma_tag_destroy(adapter->txtag); 2946205869Sjfv adapter->txtag = NULL; 2947205869Sjfv } 2948205869Sjfv} 2949205869Sjfv 2950205869Sjfv/********************************************************************* 2951205869Sjfv * 2952205869Sjfv * The offload context needs to be set when we transfer the first 2953205869Sjfv * packet of a particular protocol (TCP/UDP). This routine has been 2954205869Sjfv * enhanced to deal with inserted VLAN headers, and IPV6 (not complete) 2955205869Sjfv * 2956205869Sjfv * Added back the old method of keeping the current context type 2957205869Sjfv * and not setting if unnecessary, as this is reported to be a 2958205869Sjfv * big performance win. -jfv 2959205869Sjfv **********************************************************************/ 2960205869Sjfvstatic void 2961205869Sjfvlem_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp, 2962205869Sjfv u32 *txd_upper, u32 *txd_lower) 2963205869Sjfv{ 2964205869Sjfv struct e1000_context_desc *TXD = NULL; 2965205869Sjfv struct em_buffer *tx_buffer; 2966205869Sjfv struct ether_vlan_header *eh; 2967205869Sjfv struct ip *ip = NULL; 2968205869Sjfv struct ip6_hdr *ip6; 2969205869Sjfv int curr_txd, ehdrlen; 2970205869Sjfv u32 cmd, hdr_len, ip_hlen; 2971205869Sjfv u16 etype; 2972205869Sjfv u8 ipproto; 2973205869Sjfv 2974205869Sjfv 2975205869Sjfv cmd = hdr_len = ipproto = 0; 2976209959Sjfv *txd_upper = *txd_lower = 0; 2977205869Sjfv curr_txd = adapter->next_avail_tx_desc; 2978205869Sjfv 2979205869Sjfv /* 2980205869Sjfv * Determine where frame payload starts. 2981205869Sjfv * Jump over vlan headers if already present, 2982205869Sjfv * helpful for QinQ too. 2983205869Sjfv */ 2984205869Sjfv eh = mtod(mp, struct ether_vlan_header *); 2985205869Sjfv if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 2986205869Sjfv etype = ntohs(eh->evl_proto); 2987205869Sjfv ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 2988205869Sjfv } else { 2989205869Sjfv etype = ntohs(eh->evl_encap_proto); 2990205869Sjfv ehdrlen = ETHER_HDR_LEN; 2991205869Sjfv } 2992205869Sjfv 2993205869Sjfv /* 2994205869Sjfv * We only support TCP/UDP for IPv4 and IPv6 for the moment. 2995205869Sjfv * TODO: Support SCTP too when it hits the tree. 2996205869Sjfv */ 2997205869Sjfv switch (etype) { 2998205869Sjfv case ETHERTYPE_IP: 2999205869Sjfv ip = (struct ip *)(mp->m_data + ehdrlen); 3000205869Sjfv ip_hlen = ip->ip_hl << 2; 3001205869Sjfv 3002205869Sjfv /* Setup of IP header checksum. */ 3003205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_IP) { 3004205869Sjfv /* 3005205869Sjfv * Start offset for header checksum calculation. 3006205869Sjfv * End offset for header checksum calculation. 3007205869Sjfv * Offset of place to put the checksum. 3008205869Sjfv */ 3009205869Sjfv TXD = (struct e1000_context_desc *) 3010205869Sjfv &adapter->tx_desc_base[curr_txd]; 3011205869Sjfv TXD->lower_setup.ip_fields.ipcss = ehdrlen; 3012205869Sjfv TXD->lower_setup.ip_fields.ipcse = 3013205869Sjfv htole16(ehdrlen + ip_hlen); 3014205869Sjfv TXD->lower_setup.ip_fields.ipcso = 3015205869Sjfv ehdrlen + offsetof(struct ip, ip_sum); 3016205869Sjfv cmd |= E1000_TXD_CMD_IP; 3017205869Sjfv *txd_upper |= E1000_TXD_POPTS_IXSM << 8; 3018205869Sjfv } 3019205869Sjfv 3020205869Sjfv hdr_len = ehdrlen + ip_hlen; 3021205869Sjfv ipproto = ip->ip_p; 3022205869Sjfv 3023205869Sjfv break; 3024205869Sjfv case ETHERTYPE_IPV6: 3025205869Sjfv ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 3026205869Sjfv ip_hlen = sizeof(struct ip6_hdr); /* XXX: No header stacking. */ 3027205869Sjfv 3028205869Sjfv /* IPv6 doesn't have a header checksum. */ 3029205869Sjfv 3030205869Sjfv hdr_len = ehdrlen + ip_hlen; 3031205869Sjfv ipproto = ip6->ip6_nxt; 3032209959Sjfv break; 3033205869Sjfv 3034205869Sjfv default: 3035205869Sjfv return; 3036205869Sjfv } 3037205869Sjfv 3038205869Sjfv switch (ipproto) { 3039205869Sjfv case IPPROTO_TCP: 3040205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_TCP) { 3041205869Sjfv *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 3042205869Sjfv *txd_upper |= E1000_TXD_POPTS_TXSM << 8; 3043205869Sjfv /* no need for context if already set */ 3044205869Sjfv if (adapter->last_hw_offload == CSUM_TCP) 3045205869Sjfv return; 3046205869Sjfv adapter->last_hw_offload = CSUM_TCP; 3047205869Sjfv /* 3048205869Sjfv * Start offset for payload checksum calculation. 3049205869Sjfv * End offset for payload checksum calculation. 3050205869Sjfv * Offset of place to put the checksum. 3051205869Sjfv */ 3052205869Sjfv TXD = (struct e1000_context_desc *) 3053205869Sjfv &adapter->tx_desc_base[curr_txd]; 3054205869Sjfv TXD->upper_setup.tcp_fields.tucss = hdr_len; 3055205869Sjfv TXD->upper_setup.tcp_fields.tucse = htole16(0); 3056205869Sjfv TXD->upper_setup.tcp_fields.tucso = 3057205869Sjfv hdr_len + offsetof(struct tcphdr, th_sum); 3058205869Sjfv cmd |= E1000_TXD_CMD_TCP; 3059205869Sjfv } 3060205869Sjfv break; 3061205869Sjfv case IPPROTO_UDP: 3062205869Sjfv { 3063205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_UDP) { 3064205869Sjfv *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 3065205869Sjfv *txd_upper |= E1000_TXD_POPTS_TXSM << 8; 3066205869Sjfv /* no need for context if already set */ 3067205869Sjfv if (adapter->last_hw_offload == CSUM_UDP) 3068205869Sjfv return; 3069205869Sjfv adapter->last_hw_offload = CSUM_UDP; 3070205869Sjfv /* 3071205869Sjfv * Start offset for header checksum calculation. 3072205869Sjfv * End offset for header checksum calculation. 3073205869Sjfv * Offset of place to put the checksum. 3074205869Sjfv */ 3075205869Sjfv TXD = (struct e1000_context_desc *) 3076205869Sjfv &adapter->tx_desc_base[curr_txd]; 3077205869Sjfv TXD->upper_setup.tcp_fields.tucss = hdr_len; 3078205869Sjfv TXD->upper_setup.tcp_fields.tucse = htole16(0); 3079205869Sjfv TXD->upper_setup.tcp_fields.tucso = 3080205869Sjfv hdr_len + offsetof(struct udphdr, uh_sum); 3081205869Sjfv } 3082205869Sjfv /* Fall Thru */ 3083205869Sjfv } 3084205869Sjfv default: 3085205869Sjfv break; 3086205869Sjfv } 3087205869Sjfv 3088209959Sjfv if (TXD == NULL) 3089209959Sjfv return; 3090205869Sjfv TXD->tcp_seg_setup.data = htole32(0); 3091205869Sjfv TXD->cmd_and_length = 3092205869Sjfv htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd); 3093205869Sjfv tx_buffer = &adapter->tx_buffer_area[curr_txd]; 3094205869Sjfv tx_buffer->m_head = NULL; 3095205869Sjfv tx_buffer->next_eop = -1; 3096205869Sjfv 3097205869Sjfv if (++curr_txd == adapter->num_tx_desc) 3098205869Sjfv curr_txd = 0; 3099205869Sjfv 3100205869Sjfv adapter->num_tx_desc_avail--; 3101205869Sjfv adapter->next_avail_tx_desc = curr_txd; 3102205869Sjfv} 3103205869Sjfv 3104205869Sjfv 3105205869Sjfv/********************************************************************** 3106205869Sjfv * 3107205869Sjfv * Examine each tx_buffer in the used queue. If the hardware is done 3108205869Sjfv * processing the packet then free associated resources. The 3109205869Sjfv * tx_buffer is put back on the free queue. 3110205869Sjfv * 3111205869Sjfv **********************************************************************/ 3112205869Sjfvstatic void 3113205869Sjfvlem_txeof(struct adapter *adapter) 3114205869Sjfv{ 3115205869Sjfv int first, last, done, num_avail; 3116205869Sjfv struct em_buffer *tx_buffer; 3117205869Sjfv struct e1000_tx_desc *tx_desc, *eop_desc; 3118205869Sjfv struct ifnet *ifp = adapter->ifp; 3119205869Sjfv 3120205869Sjfv EM_TX_LOCK_ASSERT(adapter); 3121205869Sjfv 3122228281Sluigi#ifdef DEV_NETMAP 3123262151Sluigi if (netmap_tx_irq(ifp, 0)) 3124228281Sluigi return; 3125228281Sluigi#endif /* DEV_NETMAP */ 3126205869Sjfv if (adapter->num_tx_desc_avail == adapter->num_tx_desc) 3127205869Sjfv return; 3128205869Sjfv 3129205869Sjfv num_avail = adapter->num_tx_desc_avail; 3130205869Sjfv first = adapter->next_tx_to_clean; 3131205869Sjfv tx_desc = &adapter->tx_desc_base[first]; 3132205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 3133205869Sjfv last = tx_buffer->next_eop; 3134205869Sjfv eop_desc = &adapter->tx_desc_base[last]; 3135205869Sjfv 3136205869Sjfv /* 3137205869Sjfv * What this does is get the index of the 3138205869Sjfv * first descriptor AFTER the EOP of the 3139205869Sjfv * first packet, that way we can do the 3140205869Sjfv * simple comparison on the inner while loop. 3141205869Sjfv */ 3142205869Sjfv if (++last == adapter->num_tx_desc) 3143205869Sjfv last = 0; 3144205869Sjfv done = last; 3145205869Sjfv 3146205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 3147205869Sjfv BUS_DMASYNC_POSTREAD); 3148205869Sjfv 3149205869Sjfv while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) { 3150205869Sjfv /* We clean the range of the packet */ 3151205869Sjfv while (first != done) { 3152205869Sjfv tx_desc->upper.data = 0; 3153205869Sjfv tx_desc->lower.data = 0; 3154205869Sjfv tx_desc->buffer_addr = 0; 3155205869Sjfv ++num_avail; 3156205869Sjfv 3157205869Sjfv if (tx_buffer->m_head) { 3158205869Sjfv ifp->if_opackets++; 3159205869Sjfv bus_dmamap_sync(adapter->txtag, 3160205869Sjfv tx_buffer->map, 3161205869Sjfv BUS_DMASYNC_POSTWRITE); 3162205869Sjfv bus_dmamap_unload(adapter->txtag, 3163205869Sjfv tx_buffer->map); 3164205869Sjfv 3165205869Sjfv m_freem(tx_buffer->m_head); 3166205869Sjfv tx_buffer->m_head = NULL; 3167205869Sjfv } 3168205869Sjfv tx_buffer->next_eop = -1; 3169205869Sjfv adapter->watchdog_time = ticks; 3170205869Sjfv 3171205869Sjfv if (++first == adapter->num_tx_desc) 3172205869Sjfv first = 0; 3173205869Sjfv 3174205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 3175205869Sjfv tx_desc = &adapter->tx_desc_base[first]; 3176205869Sjfv } 3177205869Sjfv /* See if we can continue to the next packet */ 3178205869Sjfv last = tx_buffer->next_eop; 3179205869Sjfv if (last != -1) { 3180205869Sjfv eop_desc = &adapter->tx_desc_base[last]; 3181205869Sjfv /* Get new done point */ 3182205869Sjfv if (++last == adapter->num_tx_desc) last = 0; 3183205869Sjfv done = last; 3184205869Sjfv } else 3185205869Sjfv break; 3186205869Sjfv } 3187205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 3188205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3189205869Sjfv 3190205869Sjfv adapter->next_tx_to_clean = first; 3191214646Sjfv adapter->num_tx_desc_avail = num_avail; 3192205869Sjfv 3193270252Sluigi#ifdef NIC_SEND_COMBINING 3194270252Sluigi if ((adapter->shadow_tdt & MIT_PENDING_TDT) == MIT_PENDING_TDT) { 3195270252Sluigi /* a tdt write is pending, do it */ 3196270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 3197270252Sluigi 0xffff & adapter->shadow_tdt); 3198270252Sluigi adapter->shadow_tdt = MIT_PENDING_INT; 3199270252Sluigi } else { 3200270252Sluigi adapter->shadow_tdt = 0; // disable 3201270252Sluigi } 3202270252Sluigi#endif /* NIC_SEND_COMBINING */ 3203205869Sjfv /* 3204205869Sjfv * If we have enough room, clear IFF_DRV_OACTIVE to 3205205869Sjfv * tell the stack that it is OK to send packets. 3206205869Sjfv * If there are no pending descriptors, clear the watchdog. 3207205869Sjfv */ 3208214646Sjfv if (adapter->num_tx_desc_avail > EM_TX_CLEANUP_THRESHOLD) { 3209205869Sjfv ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 3210270252Sluigi#ifdef NIC_PARAVIRT 3211270252Sluigi if (adapter->csb) { // XXX also csb_on ? 3212270252Sluigi adapter->csb->guest_need_txkick = 2; /* acked */ 3213270252Sluigi // XXX memory barrier 3214270252Sluigi } 3215270252Sluigi#endif /* NIC_PARAVIRT */ 3216214646Sjfv if (adapter->num_tx_desc_avail == adapter->num_tx_desc) { 3217205869Sjfv adapter->watchdog_check = FALSE; 3218205869Sjfv return; 3219205869Sjfv } 3220205869Sjfv } 3221205869Sjfv} 3222205869Sjfv 3223205869Sjfv/********************************************************************* 3224205869Sjfv * 3225205869Sjfv * When Link is lost sometimes there is work still in the TX ring 3226205869Sjfv * which may result in a watchdog, rather than allow that we do an 3227205869Sjfv * attempted cleanup and then reinit here. Note that this has been 3228205869Sjfv * seens mostly with fiber adapters. 3229205869Sjfv * 3230205869Sjfv **********************************************************************/ 3231205869Sjfvstatic void 3232205869Sjfvlem_tx_purge(struct adapter *adapter) 3233205869Sjfv{ 3234205869Sjfv if ((!adapter->link_active) && (adapter->watchdog_check)) { 3235205869Sjfv EM_TX_LOCK(adapter); 3236205869Sjfv lem_txeof(adapter); 3237205869Sjfv EM_TX_UNLOCK(adapter); 3238205869Sjfv if (adapter->watchdog_check) /* Still outstanding? */ 3239205869Sjfv lem_init_locked(adapter); 3240205869Sjfv } 3241205869Sjfv} 3242205869Sjfv 3243205869Sjfv/********************************************************************* 3244205869Sjfv * 3245205869Sjfv * Get a buffer from system mbuf buffer pool. 3246205869Sjfv * 3247205869Sjfv **********************************************************************/ 3248205869Sjfvstatic int 3249205869Sjfvlem_get_buf(struct adapter *adapter, int i) 3250205869Sjfv{ 3251205869Sjfv struct mbuf *m; 3252205869Sjfv bus_dma_segment_t segs[1]; 3253205869Sjfv bus_dmamap_t map; 3254205869Sjfv struct em_buffer *rx_buffer; 3255205869Sjfv int error, nsegs; 3256205869Sjfv 3257243857Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 3258205869Sjfv if (m == NULL) { 3259205869Sjfv adapter->mbuf_cluster_failed++; 3260205869Sjfv return (ENOBUFS); 3261205869Sjfv } 3262205869Sjfv m->m_len = m->m_pkthdr.len = MCLBYTES; 3263205869Sjfv 3264205869Sjfv if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN)) 3265205869Sjfv m_adj(m, ETHER_ALIGN); 3266205869Sjfv 3267205869Sjfv /* 3268205869Sjfv * Using memory from the mbuf cluster pool, invoke the 3269205869Sjfv * bus_dma machinery to arrange the memory mapping. 3270205869Sjfv */ 3271205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->rxtag, 3272205869Sjfv adapter->rx_sparemap, m, segs, &nsegs, BUS_DMA_NOWAIT); 3273205869Sjfv if (error != 0) { 3274205869Sjfv m_free(m); 3275205869Sjfv return (error); 3276205869Sjfv } 3277205869Sjfv 3278205869Sjfv /* If nsegs is wrong then the stack is corrupt. */ 3279205869Sjfv KASSERT(nsegs == 1, ("Too many segments returned!")); 3280205869Sjfv 3281205869Sjfv rx_buffer = &adapter->rx_buffer_area[i]; 3282205869Sjfv if (rx_buffer->m_head != NULL) 3283205869Sjfv bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 3284205869Sjfv 3285205869Sjfv map = rx_buffer->map; 3286205869Sjfv rx_buffer->map = adapter->rx_sparemap; 3287205869Sjfv adapter->rx_sparemap = map; 3288205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD); 3289205869Sjfv rx_buffer->m_head = m; 3290205869Sjfv 3291205869Sjfv adapter->rx_desc_base[i].buffer_addr = htole64(segs[0].ds_addr); 3292205869Sjfv return (0); 3293205869Sjfv} 3294205869Sjfv 3295205869Sjfv/********************************************************************* 3296205869Sjfv * 3297205869Sjfv * Allocate memory for rx_buffer structures. Since we use one 3298205869Sjfv * rx_buffer per received packet, the maximum number of rx_buffer's 3299205869Sjfv * that we'll need is equal to the number of receive descriptors 3300205869Sjfv * that we've allocated. 3301205869Sjfv * 3302205869Sjfv **********************************************************************/ 3303205869Sjfvstatic int 3304205869Sjfvlem_allocate_receive_structures(struct adapter *adapter) 3305205869Sjfv{ 3306205869Sjfv device_t dev = adapter->dev; 3307205869Sjfv struct em_buffer *rx_buffer; 3308205869Sjfv int i, error; 3309205869Sjfv 3310205869Sjfv adapter->rx_buffer_area = malloc(sizeof(struct em_buffer) * 3311205869Sjfv adapter->num_rx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); 3312205869Sjfv if (adapter->rx_buffer_area == NULL) { 3313205869Sjfv device_printf(dev, "Unable to allocate rx_buffer memory\n"); 3314205869Sjfv return (ENOMEM); 3315205869Sjfv } 3316205869Sjfv 3317205869Sjfv error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 3318205869Sjfv 1, 0, /* alignment, bounds */ 3319205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 3320205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 3321205869Sjfv NULL, NULL, /* filter, filterarg */ 3322205869Sjfv MCLBYTES, /* maxsize */ 3323205869Sjfv 1, /* nsegments */ 3324205869Sjfv MCLBYTES, /* maxsegsize */ 3325205869Sjfv 0, /* flags */ 3326205869Sjfv NULL, /* lockfunc */ 3327205869Sjfv NULL, /* lockarg */ 3328205869Sjfv &adapter->rxtag); 3329205869Sjfv if (error) { 3330205869Sjfv device_printf(dev, "%s: bus_dma_tag_create failed %d\n", 3331205869Sjfv __func__, error); 3332205869Sjfv goto fail; 3333205869Sjfv } 3334205869Sjfv 3335205869Sjfv /* Create the spare map (used by getbuf) */ 3336259508Skib error = bus_dmamap_create(adapter->rxtag, 0, &adapter->rx_sparemap); 3337205869Sjfv if (error) { 3338205869Sjfv device_printf(dev, "%s: bus_dmamap_create failed: %d\n", 3339205869Sjfv __func__, error); 3340205869Sjfv goto fail; 3341205869Sjfv } 3342205869Sjfv 3343205869Sjfv rx_buffer = adapter->rx_buffer_area; 3344205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3345259508Skib error = bus_dmamap_create(adapter->rxtag, 0, &rx_buffer->map); 3346205869Sjfv if (error) { 3347205869Sjfv device_printf(dev, "%s: bus_dmamap_create failed: %d\n", 3348205869Sjfv __func__, error); 3349205869Sjfv goto fail; 3350205869Sjfv } 3351205869Sjfv } 3352205869Sjfv 3353205869Sjfv return (0); 3354205869Sjfv 3355205869Sjfvfail: 3356205869Sjfv lem_free_receive_structures(adapter); 3357205869Sjfv return (error); 3358205869Sjfv} 3359205869Sjfv 3360205869Sjfv/********************************************************************* 3361205869Sjfv * 3362205869Sjfv * (Re)initialize receive structures. 3363205869Sjfv * 3364205869Sjfv **********************************************************************/ 3365205869Sjfvstatic int 3366205869Sjfvlem_setup_receive_structures(struct adapter *adapter) 3367205869Sjfv{ 3368205869Sjfv struct em_buffer *rx_buffer; 3369205869Sjfv int i, error; 3370228281Sluigi#ifdef DEV_NETMAP 3371228281Sluigi /* we are already under lock */ 3372228281Sluigi struct netmap_adapter *na = NA(adapter->ifp); 3373228281Sluigi struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0); 3374228281Sluigi#endif 3375205869Sjfv 3376205869Sjfv /* Reset descriptor ring */ 3377205869Sjfv bzero(adapter->rx_desc_base, 3378205869Sjfv (sizeof(struct e1000_rx_desc)) * adapter->num_rx_desc); 3379205869Sjfv 3380205869Sjfv /* Free current RX buffers. */ 3381205869Sjfv rx_buffer = adapter->rx_buffer_area; 3382205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3383205869Sjfv if (rx_buffer->m_head != NULL) { 3384205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, 3385205869Sjfv BUS_DMASYNC_POSTREAD); 3386205869Sjfv bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 3387205869Sjfv m_freem(rx_buffer->m_head); 3388205869Sjfv rx_buffer->m_head = NULL; 3389205869Sjfv } 3390205869Sjfv } 3391205869Sjfv 3392205869Sjfv /* Allocate new ones. */ 3393205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++) { 3394228281Sluigi#ifdef DEV_NETMAP 3395228281Sluigi if (slot) { 3396231796Sluigi /* the i-th NIC entry goes to slot si */ 3397232238Sluigi int si = netmap_idx_n2k(&na->rx_rings[0], i); 3398229939Sluigi uint64_t paddr; 3399228281Sluigi void *addr; 3400228281Sluigi 3401270252Sluigi addr = PNMB(na, slot + si, &paddr); 3402270252Sluigi netmap_load_map(na, adapter->rxtag, rx_buffer->map, addr); 3403228281Sluigi /* Update descriptor */ 3404229939Sluigi adapter->rx_desc_base[i].buffer_addr = htole64(paddr); 3405228281Sluigi continue; 3406228281Sluigi } 3407228281Sluigi#endif /* DEV_NETMAP */ 3408205869Sjfv error = lem_get_buf(adapter, i); 3409205869Sjfv if (error) 3410205869Sjfv return (error); 3411205869Sjfv } 3412205869Sjfv 3413205869Sjfv /* Setup our descriptor pointers */ 3414205869Sjfv adapter->next_rx_desc_to_check = 0; 3415205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3416205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3417205869Sjfv 3418205869Sjfv return (0); 3419205869Sjfv} 3420205869Sjfv 3421205869Sjfv/********************************************************************* 3422205869Sjfv * 3423205869Sjfv * Enable receive unit. 3424205869Sjfv * 3425205869Sjfv **********************************************************************/ 3426205869Sjfv 3427205869Sjfvstatic void 3428205869Sjfvlem_initialize_receive_unit(struct adapter *adapter) 3429205869Sjfv{ 3430205869Sjfv struct ifnet *ifp = adapter->ifp; 3431205869Sjfv u64 bus_addr; 3432205869Sjfv u32 rctl, rxcsum; 3433205869Sjfv 3434205869Sjfv INIT_DEBUGOUT("lem_initialize_receive_unit: begin"); 3435205869Sjfv 3436205869Sjfv /* 3437205869Sjfv * Make sure receives are disabled while setting 3438205869Sjfv * up the descriptor ring 3439205869Sjfv */ 3440205869Sjfv rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 3441205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); 3442205869Sjfv 3443205869Sjfv if (adapter->hw.mac.type >= e1000_82540) { 3444205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RADV, 3445205869Sjfv adapter->rx_abs_int_delay.value); 3446205869Sjfv /* 3447205869Sjfv * Set the interrupt throttling rate. Value is calculated 3448205869Sjfv * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) 3449205869Sjfv */ 3450205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_ITR, DEFAULT_ITR); 3451205869Sjfv } 3452205869Sjfv 3453205869Sjfv /* Setup the Base and Length of the Rx Descriptor Ring */ 3454205869Sjfv bus_addr = adapter->rxdma.dma_paddr; 3455205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0), 3456205869Sjfv adapter->num_rx_desc * sizeof(struct e1000_rx_desc)); 3457205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDBAH(0), 3458205869Sjfv (u32)(bus_addr >> 32)); 3459205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDBAL(0), 3460205869Sjfv (u32)bus_addr); 3461205869Sjfv 3462205869Sjfv /* Setup the Receive Control Register */ 3463205869Sjfv rctl &= ~(3 << E1000_RCTL_MO_SHIFT); 3464205869Sjfv rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | 3465205869Sjfv E1000_RCTL_RDMTS_HALF | 3466205869Sjfv (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); 3467205869Sjfv 3468205869Sjfv /* Make sure VLAN Filters are off */ 3469205869Sjfv rctl &= ~E1000_RCTL_VFE; 3470205869Sjfv 3471205869Sjfv if (e1000_tbi_sbp_enabled_82543(&adapter->hw)) 3472205869Sjfv rctl |= E1000_RCTL_SBP; 3473205869Sjfv else 3474205869Sjfv rctl &= ~E1000_RCTL_SBP; 3475205869Sjfv 3476205869Sjfv switch (adapter->rx_buffer_len) { 3477205869Sjfv default: 3478205869Sjfv case 2048: 3479205869Sjfv rctl |= E1000_RCTL_SZ_2048; 3480205869Sjfv break; 3481205869Sjfv case 4096: 3482205869Sjfv rctl |= E1000_RCTL_SZ_4096 | 3483205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3484205869Sjfv break; 3485205869Sjfv case 8192: 3486205869Sjfv rctl |= E1000_RCTL_SZ_8192 | 3487205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3488205869Sjfv break; 3489205869Sjfv case 16384: 3490205869Sjfv rctl |= E1000_RCTL_SZ_16384 | 3491205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3492205869Sjfv break; 3493205869Sjfv } 3494205869Sjfv 3495205869Sjfv if (ifp->if_mtu > ETHERMTU) 3496205869Sjfv rctl |= E1000_RCTL_LPE; 3497205869Sjfv else 3498205869Sjfv rctl &= ~E1000_RCTL_LPE; 3499205869Sjfv 3500205869Sjfv /* Enable 82543 Receive Checksum Offload for TCP and UDP */ 3501205869Sjfv if ((adapter->hw.mac.type >= e1000_82543) && 3502205869Sjfv (ifp->if_capenable & IFCAP_RXCSUM)) { 3503205869Sjfv rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM); 3504205869Sjfv rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); 3505205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum); 3506205869Sjfv } 3507205869Sjfv 3508205869Sjfv /* Enable Receives */ 3509205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); 3510205869Sjfv 3511205869Sjfv /* 3512205869Sjfv * Setup the HW Rx Head and 3513205869Sjfv * Tail Descriptor Pointers 3514205869Sjfv */ 3515205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0); 3516250413Sluigi rctl = adapter->num_rx_desc - 1; /* default RDT value */ 3517228281Sluigi#ifdef DEV_NETMAP 3518228281Sluigi /* preserve buffers already made available to clients */ 3519250413Sluigi if (ifp->if_capenable & IFCAP_NETMAP) 3520262151Sluigi rctl -= nm_kr_rxspace(&NA(adapter->ifp)->rx_rings[0]); 3521228281Sluigi#endif /* DEV_NETMAP */ 3522250413Sluigi E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), rctl); 3523205869Sjfv 3524205869Sjfv return; 3525205869Sjfv} 3526205869Sjfv 3527205869Sjfv/********************************************************************* 3528205869Sjfv * 3529205869Sjfv * Free receive related data structures. 3530205869Sjfv * 3531205869Sjfv **********************************************************************/ 3532205869Sjfvstatic void 3533205869Sjfvlem_free_receive_structures(struct adapter *adapter) 3534205869Sjfv{ 3535205869Sjfv struct em_buffer *rx_buffer; 3536205869Sjfv int i; 3537205869Sjfv 3538205869Sjfv INIT_DEBUGOUT("free_receive_structures: begin"); 3539205869Sjfv 3540205869Sjfv if (adapter->rx_sparemap) { 3541205869Sjfv bus_dmamap_destroy(adapter->rxtag, adapter->rx_sparemap); 3542205869Sjfv adapter->rx_sparemap = NULL; 3543205869Sjfv } 3544205869Sjfv 3545205869Sjfv /* Cleanup any existing buffers */ 3546205869Sjfv if (adapter->rx_buffer_area != NULL) { 3547205869Sjfv rx_buffer = adapter->rx_buffer_area; 3548205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3549205869Sjfv if (rx_buffer->m_head != NULL) { 3550205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, 3551205869Sjfv BUS_DMASYNC_POSTREAD); 3552205869Sjfv bus_dmamap_unload(adapter->rxtag, 3553205869Sjfv rx_buffer->map); 3554205869Sjfv m_freem(rx_buffer->m_head); 3555205869Sjfv rx_buffer->m_head = NULL; 3556205869Sjfv } else if (rx_buffer->map != NULL) 3557205869Sjfv bus_dmamap_unload(adapter->rxtag, 3558205869Sjfv rx_buffer->map); 3559205869Sjfv if (rx_buffer->map != NULL) { 3560205869Sjfv bus_dmamap_destroy(adapter->rxtag, 3561205869Sjfv rx_buffer->map); 3562205869Sjfv rx_buffer->map = NULL; 3563205869Sjfv } 3564205869Sjfv } 3565205869Sjfv } 3566205869Sjfv 3567205869Sjfv if (adapter->rx_buffer_area != NULL) { 3568205869Sjfv free(adapter->rx_buffer_area, M_DEVBUF); 3569205869Sjfv adapter->rx_buffer_area = NULL; 3570205869Sjfv } 3571205869Sjfv 3572205869Sjfv if (adapter->rxtag != NULL) { 3573205869Sjfv bus_dma_tag_destroy(adapter->rxtag); 3574205869Sjfv adapter->rxtag = NULL; 3575205869Sjfv } 3576205869Sjfv} 3577205869Sjfv 3578205869Sjfv/********************************************************************* 3579205869Sjfv * 3580205869Sjfv * This routine executes in interrupt context. It replenishes 3581205869Sjfv * the mbufs in the descriptor and sends data which has been 3582205869Sjfv * dma'ed into host memory to upper layer. 3583205869Sjfv * 3584205869Sjfv * We loop at most count times if count is > 0, or until done if 3585205869Sjfv * count < 0. 3586205869Sjfv * 3587205869Sjfv * For polling we also now return the number of cleaned packets 3588205869Sjfv *********************************************************************/ 3589209238Sjfvstatic bool 3590209238Sjfvlem_rxeof(struct adapter *adapter, int count, int *done) 3591205869Sjfv{ 3592241844Seadler struct ifnet *ifp = adapter->ifp; 3593205869Sjfv struct mbuf *mp; 3594214646Sjfv u8 status = 0, accept_frame = 0, eop = 0; 3595205869Sjfv u16 len, desc_len, prev_len_adj; 3596205869Sjfv int i, rx_sent = 0; 3597205869Sjfv struct e1000_rx_desc *current_desc; 3598205869Sjfv 3599270252Sluigi#ifdef BATCH_DISPATCH 3600270252Sluigi struct mbuf *mh = NULL, *mt = NULL; 3601270252Sluigi#endif /* BATCH_DISPATCH */ 3602270252Sluigi#ifdef NIC_PARAVIRT 3603270252Sluigi int retries = 0; 3604270252Sluigi struct paravirt_csb* csb = adapter->csb; 3605270252Sluigi int csb_mode = csb && csb->guest_csb_on; 3606270252Sluigi 3607270252Sluigi //ND("clear guest_rxkick at %d", adapter->next_rx_desc_to_check); 3608270252Sluigi if (csb_mode && csb->guest_need_rxkick) 3609270252Sluigi csb->guest_need_rxkick = 0; 3610270252Sluigi#endif /* NIC_PARAVIRT */ 3611205869Sjfv EM_RX_LOCK(adapter); 3612270252Sluigi 3613270252Sluigi#ifdef BATCH_DISPATCH 3614270252Sluigi batch_again: 3615270252Sluigi#endif /* BATCH_DISPATCH */ 3616205869Sjfv i = adapter->next_rx_desc_to_check; 3617205869Sjfv current_desc = &adapter->rx_desc_base[i]; 3618205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3619205869Sjfv BUS_DMASYNC_POSTREAD); 3620205869Sjfv 3621228281Sluigi#ifdef DEV_NETMAP 3622262151Sluigi if (netmap_rx_irq(ifp, 0, &rx_sent)) { 3623262151Sluigi EM_RX_UNLOCK(adapter); 3624250109Sluigi return (FALSE); 3625262151Sluigi } 3626228281Sluigi#endif /* DEV_NETMAP */ 3627228281Sluigi 3628270252Sluigi#if 1 // XXX optimization ? 3629205869Sjfv if (!((current_desc->status) & E1000_RXD_STAT_DD)) { 3630209238Sjfv if (done != NULL) 3631209238Sjfv *done = rx_sent; 3632205869Sjfv EM_RX_UNLOCK(adapter); 3633209238Sjfv return (FALSE); 3634205869Sjfv } 3635270252Sluigi#endif /* 0 */ 3636205869Sjfv 3637214646Sjfv while (count != 0 && ifp->if_drv_flags & IFF_DRV_RUNNING) { 3638205869Sjfv struct mbuf *m = NULL; 3639205869Sjfv 3640214646Sjfv status = current_desc->status; 3641270252Sluigi if ((status & E1000_RXD_STAT_DD) == 0) { 3642270252Sluigi#ifdef NIC_PARAVIRT 3643270252Sluigi if (csb_mode) { 3644270252Sluigi /* buffer not ready yet. Retry a few times before giving up */ 3645270252Sluigi if (++retries <= adapter->rx_retries) { 3646270252Sluigi continue; 3647270252Sluigi } 3648270252Sluigi if (csb->guest_need_rxkick == 0) { 3649270252Sluigi // ND("set guest_rxkick at %d", adapter->next_rx_desc_to_check); 3650270252Sluigi csb->guest_need_rxkick = 1; 3651270252Sluigi // XXX memory barrier, status volatile ? 3652270252Sluigi continue; /* double check */ 3653270252Sluigi } 3654270252Sluigi } 3655270252Sluigi /* no buffer ready, give up */ 3656270252Sluigi#endif /* NIC_PARAVIRT */ 3657214646Sjfv break; 3658270252Sluigi } 3659270252Sluigi#ifdef NIC_PARAVIRT 3660270252Sluigi if (csb_mode) { 3661270252Sluigi if (csb->guest_need_rxkick) 3662270252Sluigi // ND("clear again guest_rxkick at %d", adapter->next_rx_desc_to_check); 3663270252Sluigi csb->guest_need_rxkick = 0; 3664270252Sluigi retries = 0; 3665270252Sluigi } 3666270252Sluigi#endif /* NIC_PARAVIRT */ 3667214646Sjfv 3668205869Sjfv mp = adapter->rx_buffer_area[i].m_head; 3669205869Sjfv /* 3670205869Sjfv * Can't defer bus_dmamap_sync(9) because TBI_ACCEPT 3671205869Sjfv * needs to access the last received byte in the mbuf. 3672205869Sjfv */ 3673205869Sjfv bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map, 3674205869Sjfv BUS_DMASYNC_POSTREAD); 3675205869Sjfv 3676205869Sjfv accept_frame = 1; 3677205869Sjfv prev_len_adj = 0; 3678205869Sjfv desc_len = le16toh(current_desc->length); 3679205869Sjfv if (status & E1000_RXD_STAT_EOP) { 3680205869Sjfv count--; 3681205869Sjfv eop = 1; 3682205869Sjfv if (desc_len < ETHER_CRC_LEN) { 3683205869Sjfv len = 0; 3684205869Sjfv prev_len_adj = ETHER_CRC_LEN - desc_len; 3685205869Sjfv } else 3686205869Sjfv len = desc_len - ETHER_CRC_LEN; 3687205869Sjfv } else { 3688205869Sjfv eop = 0; 3689205869Sjfv len = desc_len; 3690205869Sjfv } 3691205869Sjfv 3692205869Sjfv if (current_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) { 3693205869Sjfv u8 last_byte; 3694205869Sjfv u32 pkt_len = desc_len; 3695205869Sjfv 3696205869Sjfv if (adapter->fmp != NULL) 3697205869Sjfv pkt_len += adapter->fmp->m_pkthdr.len; 3698205869Sjfv 3699205869Sjfv last_byte = *(mtod(mp, caddr_t) + desc_len - 1); 3700205869Sjfv if (TBI_ACCEPT(&adapter->hw, status, 3701205869Sjfv current_desc->errors, pkt_len, last_byte, 3702205869Sjfv adapter->min_frame_size, adapter->max_frame_size)) { 3703205869Sjfv e1000_tbi_adjust_stats_82543(&adapter->hw, 3704205869Sjfv &adapter->stats, pkt_len, 3705205869Sjfv adapter->hw.mac.addr, 3706205869Sjfv adapter->max_frame_size); 3707205869Sjfv if (len > 0) 3708205869Sjfv len--; 3709205869Sjfv } else 3710205869Sjfv accept_frame = 0; 3711205869Sjfv } 3712205869Sjfv 3713205869Sjfv if (accept_frame) { 3714205869Sjfv if (lem_get_buf(adapter, i) != 0) { 3715205869Sjfv ifp->if_iqdrops++; 3716205869Sjfv goto discard; 3717205869Sjfv } 3718205869Sjfv 3719205869Sjfv /* Assign correct length to the current fragment */ 3720205869Sjfv mp->m_len = len; 3721205869Sjfv 3722205869Sjfv if (adapter->fmp == NULL) { 3723205869Sjfv mp->m_pkthdr.len = len; 3724205869Sjfv adapter->fmp = mp; /* Store the first mbuf */ 3725205869Sjfv adapter->lmp = mp; 3726205869Sjfv } else { 3727205869Sjfv /* Chain mbuf's together */ 3728205869Sjfv mp->m_flags &= ~M_PKTHDR; 3729205869Sjfv /* 3730205869Sjfv * Adjust length of previous mbuf in chain if 3731205869Sjfv * we received less than 4 bytes in the last 3732205869Sjfv * descriptor. 3733205869Sjfv */ 3734205869Sjfv if (prev_len_adj > 0) { 3735205869Sjfv adapter->lmp->m_len -= prev_len_adj; 3736205869Sjfv adapter->fmp->m_pkthdr.len -= 3737205869Sjfv prev_len_adj; 3738205869Sjfv } 3739205869Sjfv adapter->lmp->m_next = mp; 3740205869Sjfv adapter->lmp = adapter->lmp->m_next; 3741205869Sjfv adapter->fmp->m_pkthdr.len += len; 3742205869Sjfv } 3743205869Sjfv 3744205869Sjfv if (eop) { 3745205869Sjfv adapter->fmp->m_pkthdr.rcvif = ifp; 3746205869Sjfv ifp->if_ipackets++; 3747205869Sjfv lem_receive_checksum(adapter, current_desc, 3748205869Sjfv adapter->fmp); 3749205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3750205869Sjfv if (adapter->max_frame_size > 3751205869Sjfv (MCLBYTES - ETHER_ALIGN) && 3752205869Sjfv lem_fixup_rx(adapter) != 0) 3753205869Sjfv goto skip; 3754205869Sjfv#endif 3755205869Sjfv if (status & E1000_RXD_STAT_VP) { 3756205869Sjfv adapter->fmp->m_pkthdr.ether_vtag = 3757229606Srwatson le16toh(current_desc->special); 3758205869Sjfv adapter->fmp->m_flags |= M_VLANTAG; 3759205869Sjfv } 3760205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3761205869Sjfvskip: 3762205869Sjfv#endif 3763205869Sjfv m = adapter->fmp; 3764205869Sjfv adapter->fmp = NULL; 3765205869Sjfv adapter->lmp = NULL; 3766205869Sjfv } 3767205869Sjfv } else { 3768240879Ssbruno adapter->dropped_pkts++; 3769205869Sjfvdiscard: 3770205869Sjfv /* Reuse loaded DMA map and just update mbuf chain */ 3771205869Sjfv mp = adapter->rx_buffer_area[i].m_head; 3772205869Sjfv mp->m_len = mp->m_pkthdr.len = MCLBYTES; 3773205869Sjfv mp->m_data = mp->m_ext.ext_buf; 3774205869Sjfv mp->m_next = NULL; 3775205869Sjfv if (adapter->max_frame_size <= 3776205869Sjfv (MCLBYTES - ETHER_ALIGN)) 3777205869Sjfv m_adj(mp, ETHER_ALIGN); 3778205869Sjfv if (adapter->fmp != NULL) { 3779205869Sjfv m_freem(adapter->fmp); 3780205869Sjfv adapter->fmp = NULL; 3781205869Sjfv adapter->lmp = NULL; 3782205869Sjfv } 3783205869Sjfv m = NULL; 3784205869Sjfv } 3785205869Sjfv 3786205869Sjfv /* Zero out the receive descriptors status. */ 3787205869Sjfv current_desc->status = 0; 3788205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3789205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3790205869Sjfv 3791270252Sluigi#ifdef NIC_PARAVIRT 3792270252Sluigi if (csb_mode) { 3793270252Sluigi /* the buffer at i has been already replaced by lem_get_buf() 3794270252Sluigi * so it is safe to set guest_rdt = i and possibly send a kick. 3795270252Sluigi * XXX see if we can optimize it later. 3796270252Sluigi */ 3797270252Sluigi csb->guest_rdt = i; 3798270252Sluigi // XXX memory barrier 3799270252Sluigi if (i == csb->host_rxkick_at) 3800270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); 3801270252Sluigi } 3802270252Sluigi#endif /* NIC_PARAVIRT */ 3803205869Sjfv /* Advance our pointers to the next descriptor. */ 3804205869Sjfv if (++i == adapter->num_rx_desc) 3805205869Sjfv i = 0; 3806205869Sjfv /* Call into the stack */ 3807205869Sjfv if (m != NULL) { 3808270252Sluigi#ifdef BATCH_DISPATCH 3809270252Sluigi if (adapter->batch_enable) { 3810270252Sluigi if (mh == NULL) 3811270252Sluigi mh = mt = m; 3812270252Sluigi else 3813270252Sluigi mt->m_nextpkt = m; 3814270252Sluigi mt = m; 3815270252Sluigi m->m_nextpkt = NULL; 3816270252Sluigi rx_sent++; 3817270252Sluigi current_desc = &adapter->rx_desc_base[i]; 3818270252Sluigi continue; 3819270252Sluigi } 3820270252Sluigi#endif /* BATCH_DISPATCH */ 3821205869Sjfv adapter->next_rx_desc_to_check = i; 3822205869Sjfv EM_RX_UNLOCK(adapter); 3823205869Sjfv (*ifp->if_input)(ifp, m); 3824205869Sjfv EM_RX_LOCK(adapter); 3825205869Sjfv rx_sent++; 3826205869Sjfv i = adapter->next_rx_desc_to_check; 3827205869Sjfv } 3828205869Sjfv current_desc = &adapter->rx_desc_base[i]; 3829205869Sjfv } 3830205869Sjfv adapter->next_rx_desc_to_check = i; 3831270252Sluigi#ifdef BATCH_DISPATCH 3832270252Sluigi if (mh) { 3833270252Sluigi EM_RX_UNLOCK(adapter); 3834270252Sluigi while ( (mt = mh) != NULL) { 3835270252Sluigi mh = mh->m_nextpkt; 3836270252Sluigi mt->m_nextpkt = NULL; 3837270252Sluigi if_input(ifp, mt); 3838270252Sluigi } 3839270252Sluigi EM_RX_LOCK(adapter); 3840270252Sluigi i = adapter->next_rx_desc_to_check; /* in case of interrupts */ 3841270252Sluigi if (count > 0) 3842270252Sluigi goto batch_again; 3843270252Sluigi } 3844270252Sluigi#endif /* BATCH_DISPATCH */ 3845205869Sjfv 3846205869Sjfv /* Advance the E1000's Receive Queue #0 "Tail Pointer". */ 3847205869Sjfv if (--i < 0) 3848205869Sjfv i = adapter->num_rx_desc - 1; 3849270252Sluigi#ifdef NIC_PARAVIRT 3850270252Sluigi if (!csb_mode) /* filter out writes */ 3851270252Sluigi#endif /* NIC_PARAVIRT */ 3852205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); 3853209238Sjfv if (done != NULL) 3854209238Sjfv *done = rx_sent; 3855205869Sjfv EM_RX_UNLOCK(adapter); 3856214646Sjfv return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE); 3857205869Sjfv} 3858205869Sjfv 3859205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3860205869Sjfv/* 3861205869Sjfv * When jumbo frames are enabled we should realign entire payload on 3862205869Sjfv * architecures with strict alignment. This is serious design mistake of 8254x 3863205869Sjfv * as it nullifies DMA operations. 8254x just allows RX buffer size to be 3864205869Sjfv * 2048/4096/8192/16384. What we really want is 2048 - ETHER_ALIGN to align its 3865205869Sjfv * payload. On architecures without strict alignment restrictions 8254x still 3866205869Sjfv * performs unaligned memory access which would reduce the performance too. 3867205869Sjfv * To avoid copying over an entire frame to align, we allocate a new mbuf and 3868205869Sjfv * copy ethernet header to the new mbuf. The new mbuf is prepended into the 3869205869Sjfv * existing mbuf chain. 3870205869Sjfv * 3871205869Sjfv * Be aware, best performance of the 8254x is achived only when jumbo frame is 3872205869Sjfv * not used at all on architectures with strict alignment. 3873205869Sjfv */ 3874205869Sjfvstatic int 3875205869Sjfvlem_fixup_rx(struct adapter *adapter) 3876205869Sjfv{ 3877205869Sjfv struct mbuf *m, *n; 3878205869Sjfv int error; 3879205869Sjfv 3880205869Sjfv error = 0; 3881205869Sjfv m = adapter->fmp; 3882205869Sjfv if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN)) { 3883205869Sjfv bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len); 3884205869Sjfv m->m_data += ETHER_HDR_LEN; 3885205869Sjfv } else { 3886243857Sglebius MGETHDR(n, M_NOWAIT, MT_DATA); 3887205869Sjfv if (n != NULL) { 3888205869Sjfv bcopy(m->m_data, n->m_data, ETHER_HDR_LEN); 3889205869Sjfv m->m_data += ETHER_HDR_LEN; 3890205869Sjfv m->m_len -= ETHER_HDR_LEN; 3891205869Sjfv n->m_len = ETHER_HDR_LEN; 3892205869Sjfv M_MOVE_PKTHDR(n, m); 3893205869Sjfv n->m_next = m; 3894205869Sjfv adapter->fmp = n; 3895205869Sjfv } else { 3896205869Sjfv adapter->dropped_pkts++; 3897205869Sjfv m_freem(adapter->fmp); 3898205869Sjfv adapter->fmp = NULL; 3899205869Sjfv error = ENOMEM; 3900205869Sjfv } 3901205869Sjfv } 3902205869Sjfv 3903205869Sjfv return (error); 3904205869Sjfv} 3905205869Sjfv#endif 3906205869Sjfv 3907205869Sjfv/********************************************************************* 3908205869Sjfv * 3909205869Sjfv * Verify that the hardware indicated that the checksum is valid. 3910205869Sjfv * Inform the stack about the status of checksum so that stack 3911205869Sjfv * doesn't spend time verifying the checksum. 3912205869Sjfv * 3913205869Sjfv *********************************************************************/ 3914205869Sjfvstatic void 3915205869Sjfvlem_receive_checksum(struct adapter *adapter, 3916205869Sjfv struct e1000_rx_desc *rx_desc, struct mbuf *mp) 3917205869Sjfv{ 3918205869Sjfv /* 82543 or newer only */ 3919205869Sjfv if ((adapter->hw.mac.type < e1000_82543) || 3920205869Sjfv /* Ignore Checksum bit is set */ 3921205869Sjfv (rx_desc->status & E1000_RXD_STAT_IXSM)) { 3922205869Sjfv mp->m_pkthdr.csum_flags = 0; 3923205869Sjfv return; 3924205869Sjfv } 3925205869Sjfv 3926205869Sjfv if (rx_desc->status & E1000_RXD_STAT_IPCS) { 3927205869Sjfv /* Did it pass? */ 3928205869Sjfv if (!(rx_desc->errors & E1000_RXD_ERR_IPE)) { 3929205869Sjfv /* IP Checksum Good */ 3930205869Sjfv mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; 3931205869Sjfv mp->m_pkthdr.csum_flags |= CSUM_IP_VALID; 3932205869Sjfv 3933205869Sjfv } else { 3934205869Sjfv mp->m_pkthdr.csum_flags = 0; 3935205869Sjfv } 3936205869Sjfv } 3937205869Sjfv 3938205869Sjfv if (rx_desc->status & E1000_RXD_STAT_TCPCS) { 3939205869Sjfv /* Did it pass? */ 3940205869Sjfv if (!(rx_desc->errors & E1000_RXD_ERR_TCPE)) { 3941205869Sjfv mp->m_pkthdr.csum_flags |= 3942205869Sjfv (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); 3943205869Sjfv mp->m_pkthdr.csum_data = htons(0xffff); 3944205869Sjfv } 3945205869Sjfv } 3946205869Sjfv} 3947205869Sjfv 3948205869Sjfv/* 3949205869Sjfv * This routine is run via an vlan 3950205869Sjfv * config EVENT 3951205869Sjfv */ 3952205869Sjfvstatic void 3953205869Sjfvlem_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3954205869Sjfv{ 3955205869Sjfv struct adapter *adapter = ifp->if_softc; 3956205869Sjfv u32 index, bit; 3957205869Sjfv 3958205869Sjfv if (ifp->if_softc != arg) /* Not our event */ 3959205869Sjfv return; 3960205869Sjfv 3961205869Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid ID */ 3962205869Sjfv return; 3963205869Sjfv 3964214646Sjfv EM_CORE_LOCK(adapter); 3965205869Sjfv index = (vtag >> 5) & 0x7F; 3966205869Sjfv bit = vtag & 0x1F; 3967214646Sjfv adapter->shadow_vfta[index] |= (1 << bit); 3968205869Sjfv ++adapter->num_vlans; 3969205869Sjfv /* Re-init to load the changes */ 3970214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 3971214646Sjfv lem_init_locked(adapter); 3972214646Sjfv EM_CORE_UNLOCK(adapter); 3973205869Sjfv} 3974205869Sjfv 3975205869Sjfv/* 3976205869Sjfv * This routine is run via an vlan 3977205869Sjfv * unconfig EVENT 3978205869Sjfv */ 3979205869Sjfvstatic void 3980205869Sjfvlem_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3981205869Sjfv{ 3982205869Sjfv struct adapter *adapter = ifp->if_softc; 3983205869Sjfv u32 index, bit; 3984205869Sjfv 3985205869Sjfv if (ifp->if_softc != arg) 3986205869Sjfv return; 3987205869Sjfv 3988205869Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 3989205869Sjfv return; 3990205869Sjfv 3991214646Sjfv EM_CORE_LOCK(adapter); 3992205869Sjfv index = (vtag >> 5) & 0x7F; 3993205869Sjfv bit = vtag & 0x1F; 3994214646Sjfv adapter->shadow_vfta[index] &= ~(1 << bit); 3995205869Sjfv --adapter->num_vlans; 3996205869Sjfv /* Re-init to load the changes */ 3997214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 3998214646Sjfv lem_init_locked(adapter); 3999214646Sjfv EM_CORE_UNLOCK(adapter); 4000205869Sjfv} 4001205869Sjfv 4002205869Sjfvstatic void 4003205869Sjfvlem_setup_vlan_hw_support(struct adapter *adapter) 4004205869Sjfv{ 4005205869Sjfv struct e1000_hw *hw = &adapter->hw; 4006205869Sjfv u32 reg; 4007205869Sjfv 4008205869Sjfv /* 4009205869Sjfv ** We get here thru init_locked, meaning 4010205869Sjfv ** a soft reset, this has already cleared 4011205869Sjfv ** the VFTA and other state, so if there 4012205869Sjfv ** have been no vlan's registered do nothing. 4013205869Sjfv */ 4014205869Sjfv if (adapter->num_vlans == 0) 4015205869Sjfv return; 4016205869Sjfv 4017205869Sjfv /* 4018205869Sjfv ** A soft reset zero's out the VFTA, so 4019205869Sjfv ** we need to repopulate it now. 4020205869Sjfv */ 4021205869Sjfv for (int i = 0; i < EM_VFTA_SIZE; i++) 4022214646Sjfv if (adapter->shadow_vfta[i] != 0) 4023205869Sjfv E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, 4024214646Sjfv i, adapter->shadow_vfta[i]); 4025205869Sjfv 4026205869Sjfv reg = E1000_READ_REG(hw, E1000_CTRL); 4027205869Sjfv reg |= E1000_CTRL_VME; 4028205869Sjfv E1000_WRITE_REG(hw, E1000_CTRL, reg); 4029205869Sjfv 4030205869Sjfv /* Enable the Filter Table */ 4031205869Sjfv reg = E1000_READ_REG(hw, E1000_RCTL); 4032205869Sjfv reg &= ~E1000_RCTL_CFIEN; 4033205869Sjfv reg |= E1000_RCTL_VFE; 4034205869Sjfv E1000_WRITE_REG(hw, E1000_RCTL, reg); 4035205869Sjfv} 4036205869Sjfv 4037205869Sjfvstatic void 4038205869Sjfvlem_enable_intr(struct adapter *adapter) 4039205869Sjfv{ 4040205869Sjfv struct e1000_hw *hw = &adapter->hw; 4041205869Sjfv u32 ims_mask = IMS_ENABLE_MASK; 4042205869Sjfv 4043205869Sjfv E1000_WRITE_REG(hw, E1000_IMS, ims_mask); 4044205869Sjfv} 4045205869Sjfv 4046205869Sjfvstatic void 4047205869Sjfvlem_disable_intr(struct adapter *adapter) 4048205869Sjfv{ 4049205869Sjfv struct e1000_hw *hw = &adapter->hw; 4050205869Sjfv 4051238953Sjfv E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 4052205869Sjfv} 4053205869Sjfv 4054205869Sjfv/* 4055205869Sjfv * Bit of a misnomer, what this really means is 4056205869Sjfv * to enable OS management of the system... aka 4057205869Sjfv * to disable special hardware management features 4058205869Sjfv */ 4059205869Sjfvstatic void 4060205869Sjfvlem_init_manageability(struct adapter *adapter) 4061205869Sjfv{ 4062205869Sjfv /* A shared code workaround */ 4063205869Sjfv if (adapter->has_manage) { 4064205869Sjfv int manc = E1000_READ_REG(&adapter->hw, E1000_MANC); 4065205869Sjfv /* disable hardware interception of ARP */ 4066205869Sjfv manc &= ~(E1000_MANC_ARP_EN); 4067205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); 4068205869Sjfv } 4069205869Sjfv} 4070205869Sjfv 4071205869Sjfv/* 4072205869Sjfv * Give control back to hardware management 4073205869Sjfv * controller if there is one. 4074205869Sjfv */ 4075205869Sjfvstatic void 4076205869Sjfvlem_release_manageability(struct adapter *adapter) 4077205869Sjfv{ 4078205869Sjfv if (adapter->has_manage) { 4079205869Sjfv int manc = E1000_READ_REG(&adapter->hw, E1000_MANC); 4080205869Sjfv 4081205869Sjfv /* re-enable hardware interception of ARP */ 4082205869Sjfv manc |= E1000_MANC_ARP_EN; 4083205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); 4084205869Sjfv } 4085205869Sjfv} 4086205869Sjfv 4087205869Sjfv/* 4088205869Sjfv * lem_get_hw_control sets the {CTRL_EXT|FWSM}:DRV_LOAD bit. 4089205869Sjfv * For ASF and Pass Through versions of f/w this means 4090205869Sjfv * that the driver is loaded. For AMT version type f/w 4091205869Sjfv * this means that the network i/f is open. 4092205869Sjfv */ 4093205869Sjfvstatic void 4094205869Sjfvlem_get_hw_control(struct adapter *adapter) 4095205869Sjfv{ 4096205869Sjfv u32 ctrl_ext; 4097205869Sjfv 4098205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 4099205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, 4100205869Sjfv ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); 4101205869Sjfv return; 4102205869Sjfv} 4103205869Sjfv 4104205869Sjfv/* 4105205869Sjfv * lem_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit. 4106205869Sjfv * For ASF and Pass Through versions of f/w this means that 4107205869Sjfv * the driver is no longer loaded. For AMT versions of the 4108205869Sjfv * f/w this means that the network i/f is closed. 4109205869Sjfv */ 4110205869Sjfvstatic void 4111205869Sjfvlem_release_hw_control(struct adapter *adapter) 4112205869Sjfv{ 4113205869Sjfv u32 ctrl_ext; 4114205869Sjfv 4115205869Sjfv if (!adapter->has_manage) 4116205869Sjfv return; 4117205869Sjfv 4118205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 4119205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, 4120205869Sjfv ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); 4121205869Sjfv return; 4122205869Sjfv} 4123205869Sjfv 4124205869Sjfvstatic int 4125205869Sjfvlem_is_valid_ether_addr(u8 *addr) 4126205869Sjfv{ 4127205869Sjfv char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; 4128205869Sjfv 4129205869Sjfv if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) { 4130205869Sjfv return (FALSE); 4131205869Sjfv } 4132205869Sjfv 4133205869Sjfv return (TRUE); 4134205869Sjfv} 4135205869Sjfv 4136205869Sjfv/* 4137205869Sjfv** Parse the interface capabilities with regard 4138205869Sjfv** to both system management and wake-on-lan for 4139205869Sjfv** later use. 4140205869Sjfv*/ 4141205869Sjfvstatic void 4142205869Sjfvlem_get_wakeup(device_t dev) 4143205869Sjfv{ 4144205869Sjfv struct adapter *adapter = device_get_softc(dev); 4145205869Sjfv u16 eeprom_data = 0, device_id, apme_mask; 4146205869Sjfv 4147205869Sjfv adapter->has_manage = e1000_enable_mng_pass_thru(&adapter->hw); 4148205869Sjfv apme_mask = EM_EEPROM_APME; 4149205869Sjfv 4150205869Sjfv switch (adapter->hw.mac.type) { 4151205869Sjfv case e1000_82542: 4152205869Sjfv case e1000_82543: 4153205869Sjfv break; 4154205869Sjfv case e1000_82544: 4155205869Sjfv e1000_read_nvm(&adapter->hw, 4156205869Sjfv NVM_INIT_CONTROL2_REG, 1, &eeprom_data); 4157205869Sjfv apme_mask = EM_82544_APME; 4158205869Sjfv break; 4159205869Sjfv case e1000_82546: 4160205869Sjfv case e1000_82546_rev_3: 4161205869Sjfv if (adapter->hw.bus.func == 1) { 4162205869Sjfv e1000_read_nvm(&adapter->hw, 4163205869Sjfv NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); 4164205869Sjfv break; 4165205869Sjfv } else 4166205869Sjfv e1000_read_nvm(&adapter->hw, 4167205869Sjfv NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); 4168205869Sjfv break; 4169205869Sjfv default: 4170205869Sjfv e1000_read_nvm(&adapter->hw, 4171205869Sjfv NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); 4172205869Sjfv break; 4173205869Sjfv } 4174205869Sjfv if (eeprom_data & apme_mask) 4175205869Sjfv adapter->wol = (E1000_WUFC_MAG | E1000_WUFC_MC); 4176205869Sjfv /* 4177205869Sjfv * We have the eeprom settings, now apply the special cases 4178205869Sjfv * where the eeprom may be wrong or the board won't support 4179205869Sjfv * wake on lan on a particular port 4180205869Sjfv */ 4181205869Sjfv device_id = pci_get_device(dev); 4182205869Sjfv switch (device_id) { 4183205869Sjfv case E1000_DEV_ID_82546GB_PCIE: 4184205869Sjfv adapter->wol = 0; 4185205869Sjfv break; 4186205869Sjfv case E1000_DEV_ID_82546EB_FIBER: 4187205869Sjfv case E1000_DEV_ID_82546GB_FIBER: 4188205869Sjfv /* Wake events only supported on port A for dual fiber 4189205869Sjfv * regardless of eeprom setting */ 4190205869Sjfv if (E1000_READ_REG(&adapter->hw, E1000_STATUS) & 4191205869Sjfv E1000_STATUS_FUNC_1) 4192205869Sjfv adapter->wol = 0; 4193205869Sjfv break; 4194205869Sjfv case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: 4195205869Sjfv /* if quad port adapter, disable WoL on all but port A */ 4196205869Sjfv if (global_quad_port_a != 0) 4197205869Sjfv adapter->wol = 0; 4198205869Sjfv /* Reset for multiple quad port adapters */ 4199205869Sjfv if (++global_quad_port_a == 4) 4200205869Sjfv global_quad_port_a = 0; 4201205869Sjfv break; 4202205869Sjfv } 4203205869Sjfv return; 4204205869Sjfv} 4205205869Sjfv 4206205869Sjfv 4207205869Sjfv/* 4208205869Sjfv * Enable PCI Wake On Lan capability 4209205869Sjfv */ 4210206001Smariusstatic void 4211205869Sjfvlem_enable_wakeup(device_t dev) 4212205869Sjfv{ 4213205869Sjfv struct adapter *adapter = device_get_softc(dev); 4214205869Sjfv struct ifnet *ifp = adapter->ifp; 4215205869Sjfv u32 pmc, ctrl, ctrl_ext, rctl; 4216205869Sjfv u16 status; 4217205869Sjfv 4218219902Sjhb if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0)) 4219205869Sjfv return; 4220205869Sjfv 4221205869Sjfv /* Advertise the wakeup capability */ 4222205869Sjfv ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); 4223205869Sjfv ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); 4224205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); 4225205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); 4226205869Sjfv 4227205869Sjfv /* Keep the laser running on Fiber adapters */ 4228205869Sjfv if (adapter->hw.phy.media_type == e1000_media_type_fiber || 4229205869Sjfv adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { 4230205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 4231205869Sjfv ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; 4232205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext); 4233205869Sjfv } 4234205869Sjfv 4235205869Sjfv /* 4236205869Sjfv ** Determine type of Wakeup: note that wol 4237205869Sjfv ** is set with all bits on by default. 4238205869Sjfv */ 4239205869Sjfv if ((ifp->if_capenable & IFCAP_WOL_MAGIC) == 0) 4240205869Sjfv adapter->wol &= ~E1000_WUFC_MAG; 4241205869Sjfv 4242205869Sjfv if ((ifp->if_capenable & IFCAP_WOL_MCAST) == 0) 4243205869Sjfv adapter->wol &= ~E1000_WUFC_MC; 4244205869Sjfv else { 4245205869Sjfv rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 4246205869Sjfv rctl |= E1000_RCTL_MPE; 4247205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); 4248205869Sjfv } 4249205869Sjfv 4250205869Sjfv if (adapter->hw.mac.type == e1000_pchlan) { 4251205869Sjfv if (lem_enable_phy_wakeup(adapter)) 4252205869Sjfv return; 4253205869Sjfv } else { 4254205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); 4255205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol); 4256205869Sjfv } 4257205869Sjfv 4258205869Sjfv 4259205869Sjfv /* Request PME */ 4260205869Sjfv status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2); 4261205869Sjfv status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); 4262205869Sjfv if (ifp->if_capenable & IFCAP_WOL) 4263205869Sjfv status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; 4264205869Sjfv pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2); 4265205869Sjfv 4266205869Sjfv return; 4267205869Sjfv} 4268205869Sjfv 4269205869Sjfv/* 4270205869Sjfv** WOL in the newer chipset interfaces (pchlan) 4271205869Sjfv** require thing to be copied into the phy 4272205869Sjfv*/ 4273205869Sjfvstatic int 4274205869Sjfvlem_enable_phy_wakeup(struct adapter *adapter) 4275205869Sjfv{ 4276205869Sjfv struct e1000_hw *hw = &adapter->hw; 4277205869Sjfv u32 mreg, ret = 0; 4278205869Sjfv u16 preg; 4279205869Sjfv 4280205869Sjfv /* copy MAC RARs to PHY RARs */ 4281205869Sjfv for (int i = 0; i < adapter->hw.mac.rar_entry_count; i++) { 4282205869Sjfv mreg = E1000_READ_REG(hw, E1000_RAL(i)); 4283205869Sjfv e1000_write_phy_reg(hw, BM_RAR_L(i), (u16)(mreg & 0xFFFF)); 4284205869Sjfv e1000_write_phy_reg(hw, BM_RAR_M(i), 4285205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4286205869Sjfv mreg = E1000_READ_REG(hw, E1000_RAH(i)); 4287205869Sjfv e1000_write_phy_reg(hw, BM_RAR_H(i), (u16)(mreg & 0xFFFF)); 4288205869Sjfv e1000_write_phy_reg(hw, BM_RAR_CTRL(i), 4289205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4290205869Sjfv } 4291205869Sjfv 4292205869Sjfv /* copy MAC MTA to PHY MTA */ 4293205869Sjfv for (int i = 0; i < adapter->hw.mac.mta_reg_count; i++) { 4294205869Sjfv mreg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); 4295205869Sjfv e1000_write_phy_reg(hw, BM_MTA(i), (u16)(mreg & 0xFFFF)); 4296205869Sjfv e1000_write_phy_reg(hw, BM_MTA(i) + 1, 4297205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4298205869Sjfv } 4299205869Sjfv 4300205869Sjfv /* configure PHY Rx Control register */ 4301205869Sjfv e1000_read_phy_reg(&adapter->hw, BM_RCTL, &preg); 4302205869Sjfv mreg = E1000_READ_REG(hw, E1000_RCTL); 4303205869Sjfv if (mreg & E1000_RCTL_UPE) 4304205869Sjfv preg |= BM_RCTL_UPE; 4305205869Sjfv if (mreg & E1000_RCTL_MPE) 4306205869Sjfv preg |= BM_RCTL_MPE; 4307205869Sjfv preg &= ~(BM_RCTL_MO_MASK); 4308205869Sjfv if (mreg & E1000_RCTL_MO_3) 4309205869Sjfv preg |= (((mreg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) 4310205869Sjfv << BM_RCTL_MO_SHIFT); 4311205869Sjfv if (mreg & E1000_RCTL_BAM) 4312205869Sjfv preg |= BM_RCTL_BAM; 4313205869Sjfv if (mreg & E1000_RCTL_PMCF) 4314205869Sjfv preg |= BM_RCTL_PMCF; 4315205869Sjfv mreg = E1000_READ_REG(hw, E1000_CTRL); 4316205869Sjfv if (mreg & E1000_CTRL_RFCE) 4317205869Sjfv preg |= BM_RCTL_RFCE; 4318205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_RCTL, preg); 4319205869Sjfv 4320205869Sjfv /* enable PHY wakeup in MAC register */ 4321205869Sjfv E1000_WRITE_REG(hw, E1000_WUC, 4322205869Sjfv E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); 4323205869Sjfv E1000_WRITE_REG(hw, E1000_WUFC, adapter->wol); 4324205869Sjfv 4325205869Sjfv /* configure and enable PHY wakeup in PHY registers */ 4326205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_WUFC, adapter->wol); 4327205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); 4328205869Sjfv 4329205869Sjfv /* activate PHY wakeup */ 4330205869Sjfv ret = hw->phy.ops.acquire(hw); 4331205869Sjfv if (ret) { 4332205869Sjfv printf("Could not acquire PHY\n"); 4333205869Sjfv return ret; 4334205869Sjfv } 4335205869Sjfv e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 4336205869Sjfv (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); 4337205869Sjfv ret = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &preg); 4338205869Sjfv if (ret) { 4339205869Sjfv printf("Could not read PHY page 769\n"); 4340205869Sjfv goto out; 4341205869Sjfv } 4342205869Sjfv preg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; 4343205869Sjfv ret = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, preg); 4344205869Sjfv if (ret) 4345205869Sjfv printf("Could not set PHY Host Wakeup bit\n"); 4346205869Sjfvout: 4347205869Sjfv hw->phy.ops.release(hw); 4348205869Sjfv 4349205869Sjfv return ret; 4350205869Sjfv} 4351205869Sjfv 4352206001Smariusstatic void 4353206001Smariuslem_led_func(void *arg, int onoff) 4354206001Smarius{ 4355206001Smarius struct adapter *adapter = arg; 4356205869Sjfv 4357206001Smarius EM_CORE_LOCK(adapter); 4358206001Smarius if (onoff) { 4359206001Smarius e1000_setup_led(&adapter->hw); 4360206001Smarius e1000_led_on(&adapter->hw); 4361206001Smarius } else { 4362206001Smarius e1000_led_off(&adapter->hw); 4363206001Smarius e1000_cleanup_led(&adapter->hw); 4364206001Smarius } 4365206001Smarius EM_CORE_UNLOCK(adapter); 4366206001Smarius} 4367206001Smarius 4368205869Sjfv/********************************************************************* 4369205869Sjfv* 82544 Coexistence issue workaround. 4370205869Sjfv* There are 2 issues. 4371205869Sjfv* 1. Transmit Hang issue. 4372205869Sjfv* To detect this issue, following equation can be used... 4373205869Sjfv* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 4374205869Sjfv* If SUM[3:0] is in between 1 to 4, we will have this issue. 4375205869Sjfv* 4376205869Sjfv* 2. DAC issue. 4377205869Sjfv* To detect this issue, following equation can be used... 4378205869Sjfv* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 4379205869Sjfv* If SUM[3:0] is in between 9 to c, we will have this issue. 4380205869Sjfv* 4381205869Sjfv* 4382205869Sjfv* WORKAROUND: 4383205869Sjfv* Make sure we do not have ending address 4384205869Sjfv* as 1,2,3,4(Hang) or 9,a,b,c (DAC) 4385205869Sjfv* 4386205869Sjfv*************************************************************************/ 4387205869Sjfvstatic u32 4388205869Sjfvlem_fill_descriptors (bus_addr_t address, u32 length, 4389205869Sjfv PDESC_ARRAY desc_array) 4390205869Sjfv{ 4391205869Sjfv u32 safe_terminator; 4392205869Sjfv 4393205869Sjfv /* Since issue is sensitive to length and address.*/ 4394205869Sjfv /* Let us first check the address...*/ 4395205869Sjfv if (length <= 4) { 4396205869Sjfv desc_array->descriptor[0].address = address; 4397205869Sjfv desc_array->descriptor[0].length = length; 4398205869Sjfv desc_array->elements = 1; 4399205869Sjfv return (desc_array->elements); 4400205869Sjfv } 4401205869Sjfv safe_terminator = (u32)((((u32)address & 0x7) + 4402205869Sjfv (length & 0xF)) & 0xF); 4403205869Sjfv /* if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then return */ 4404205869Sjfv if (safe_terminator == 0 || 4405205869Sjfv (safe_terminator > 4 && 4406205869Sjfv safe_terminator < 9) || 4407205869Sjfv (safe_terminator > 0xC && 4408205869Sjfv safe_terminator <= 0xF)) { 4409205869Sjfv desc_array->descriptor[0].address = address; 4410205869Sjfv desc_array->descriptor[0].length = length; 4411205869Sjfv desc_array->elements = 1; 4412205869Sjfv return (desc_array->elements); 4413205869Sjfv } 4414205869Sjfv 4415205869Sjfv desc_array->descriptor[0].address = address; 4416205869Sjfv desc_array->descriptor[0].length = length - 4; 4417205869Sjfv desc_array->descriptor[1].address = address + (length - 4); 4418205869Sjfv desc_array->descriptor[1].length = 4; 4419205869Sjfv desc_array->elements = 2; 4420205869Sjfv return (desc_array->elements); 4421205869Sjfv} 4422205869Sjfv 4423205869Sjfv/********************************************************************** 4424205869Sjfv * 4425205869Sjfv * Update the board statistics counters. 4426205869Sjfv * 4427205869Sjfv **********************************************************************/ 4428205869Sjfvstatic void 4429205869Sjfvlem_update_stats_counters(struct adapter *adapter) 4430205869Sjfv{ 4431205869Sjfv struct ifnet *ifp; 4432205869Sjfv 4433205869Sjfv if(adapter->hw.phy.media_type == e1000_media_type_copper || 4434205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_STATUS) & E1000_STATUS_LU)) { 4435205869Sjfv adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, E1000_SYMERRS); 4436205869Sjfv adapter->stats.sec += E1000_READ_REG(&adapter->hw, E1000_SEC); 4437205869Sjfv } 4438205869Sjfv adapter->stats.crcerrs += E1000_READ_REG(&adapter->hw, E1000_CRCERRS); 4439205869Sjfv adapter->stats.mpc += E1000_READ_REG(&adapter->hw, E1000_MPC); 4440205869Sjfv adapter->stats.scc += E1000_READ_REG(&adapter->hw, E1000_SCC); 4441205869Sjfv adapter->stats.ecol += E1000_READ_REG(&adapter->hw, E1000_ECOL); 4442205869Sjfv 4443205869Sjfv adapter->stats.mcc += E1000_READ_REG(&adapter->hw, E1000_MCC); 4444205869Sjfv adapter->stats.latecol += E1000_READ_REG(&adapter->hw, E1000_LATECOL); 4445205869Sjfv adapter->stats.colc += E1000_READ_REG(&adapter->hw, E1000_COLC); 4446205869Sjfv adapter->stats.dc += E1000_READ_REG(&adapter->hw, E1000_DC); 4447205869Sjfv adapter->stats.rlec += E1000_READ_REG(&adapter->hw, E1000_RLEC); 4448205869Sjfv adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, E1000_XONRXC); 4449205869Sjfv adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, E1000_XONTXC); 4450205869Sjfv adapter->stats.xoffrxc += E1000_READ_REG(&adapter->hw, E1000_XOFFRXC); 4451205869Sjfv adapter->stats.xofftxc += E1000_READ_REG(&adapter->hw, E1000_XOFFTXC); 4452205869Sjfv adapter->stats.fcruc += E1000_READ_REG(&adapter->hw, E1000_FCRUC); 4453205869Sjfv adapter->stats.prc64 += E1000_READ_REG(&adapter->hw, E1000_PRC64); 4454205869Sjfv adapter->stats.prc127 += E1000_READ_REG(&adapter->hw, E1000_PRC127); 4455205869Sjfv adapter->stats.prc255 += E1000_READ_REG(&adapter->hw, E1000_PRC255); 4456205869Sjfv adapter->stats.prc511 += E1000_READ_REG(&adapter->hw, E1000_PRC511); 4457205869Sjfv adapter->stats.prc1023 += E1000_READ_REG(&adapter->hw, E1000_PRC1023); 4458205869Sjfv adapter->stats.prc1522 += E1000_READ_REG(&adapter->hw, E1000_PRC1522); 4459205869Sjfv adapter->stats.gprc += E1000_READ_REG(&adapter->hw, E1000_GPRC); 4460205869Sjfv adapter->stats.bprc += E1000_READ_REG(&adapter->hw, E1000_BPRC); 4461205869Sjfv adapter->stats.mprc += E1000_READ_REG(&adapter->hw, E1000_MPRC); 4462205869Sjfv adapter->stats.gptc += E1000_READ_REG(&adapter->hw, E1000_GPTC); 4463205869Sjfv 4464205869Sjfv /* For the 64-bit byte counters the low dword must be read first. */ 4465205869Sjfv /* Both registers clear on the read of the high dword */ 4466205869Sjfv 4467212902Sjhb adapter->stats.gorc += E1000_READ_REG(&adapter->hw, E1000_GORCL) + 4468212902Sjhb ((u64)E1000_READ_REG(&adapter->hw, E1000_GORCH) << 32); 4469212902Sjhb adapter->stats.gotc += E1000_READ_REG(&adapter->hw, E1000_GOTCL) + 4470212902Sjhb ((u64)E1000_READ_REG(&adapter->hw, E1000_GOTCH) << 32); 4471205869Sjfv 4472205869Sjfv adapter->stats.rnbc += E1000_READ_REG(&adapter->hw, E1000_RNBC); 4473205869Sjfv adapter->stats.ruc += E1000_READ_REG(&adapter->hw, E1000_RUC); 4474205869Sjfv adapter->stats.rfc += E1000_READ_REG(&adapter->hw, E1000_RFC); 4475205869Sjfv adapter->stats.roc += E1000_READ_REG(&adapter->hw, E1000_ROC); 4476205869Sjfv adapter->stats.rjc += E1000_READ_REG(&adapter->hw, E1000_RJC); 4477205869Sjfv 4478205869Sjfv adapter->stats.tor += E1000_READ_REG(&adapter->hw, E1000_TORH); 4479205869Sjfv adapter->stats.tot += E1000_READ_REG(&adapter->hw, E1000_TOTH); 4480205869Sjfv 4481205869Sjfv adapter->stats.tpr += E1000_READ_REG(&adapter->hw, E1000_TPR); 4482205869Sjfv adapter->stats.tpt += E1000_READ_REG(&adapter->hw, E1000_TPT); 4483205869Sjfv adapter->stats.ptc64 += E1000_READ_REG(&adapter->hw, E1000_PTC64); 4484205869Sjfv adapter->stats.ptc127 += E1000_READ_REG(&adapter->hw, E1000_PTC127); 4485205869Sjfv adapter->stats.ptc255 += E1000_READ_REG(&adapter->hw, E1000_PTC255); 4486205869Sjfv adapter->stats.ptc511 += E1000_READ_REG(&adapter->hw, E1000_PTC511); 4487205869Sjfv adapter->stats.ptc1023 += E1000_READ_REG(&adapter->hw, E1000_PTC1023); 4488205869Sjfv adapter->stats.ptc1522 += E1000_READ_REG(&adapter->hw, E1000_PTC1522); 4489205869Sjfv adapter->stats.mptc += E1000_READ_REG(&adapter->hw, E1000_MPTC); 4490205869Sjfv adapter->stats.bptc += E1000_READ_REG(&adapter->hw, E1000_BPTC); 4491205869Sjfv 4492205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 4493205869Sjfv adapter->stats.algnerrc += 4494205869Sjfv E1000_READ_REG(&adapter->hw, E1000_ALGNERRC); 4495205869Sjfv adapter->stats.rxerrc += 4496205869Sjfv E1000_READ_REG(&adapter->hw, E1000_RXERRC); 4497205869Sjfv adapter->stats.tncrs += 4498205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TNCRS); 4499205869Sjfv adapter->stats.cexterr += 4500205869Sjfv E1000_READ_REG(&adapter->hw, E1000_CEXTERR); 4501205869Sjfv adapter->stats.tsctc += 4502205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TSCTC); 4503205869Sjfv adapter->stats.tsctfc += 4504205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TSCTFC); 4505205869Sjfv } 4506205869Sjfv ifp = adapter->ifp; 4507205869Sjfv 4508205869Sjfv ifp->if_collisions = adapter->stats.colc; 4509205869Sjfv 4510205869Sjfv /* Rx Errors */ 4511205869Sjfv ifp->if_ierrors = adapter->dropped_pkts + adapter->stats.rxerrc + 4512205869Sjfv adapter->stats.crcerrs + adapter->stats.algnerrc + 4513205869Sjfv adapter->stats.ruc + adapter->stats.roc + 4514205869Sjfv adapter->stats.mpc + adapter->stats.cexterr; 4515205869Sjfv 4516205869Sjfv /* Tx Errors */ 4517205869Sjfv ifp->if_oerrors = adapter->stats.ecol + 4518205869Sjfv adapter->stats.latecol + adapter->watchdog_events; 4519205869Sjfv} 4520205869Sjfv 4521212902Sjhb/* Export a single 32-bit register via a read-only sysctl. */ 4522212902Sjhbstatic int 4523212902Sjhblem_sysctl_reg_handler(SYSCTL_HANDLER_ARGS) 4524205869Sjfv{ 4525212902Sjhb struct adapter *adapter; 4526212902Sjhb u_int val; 4527205869Sjfv 4528212902Sjhb adapter = oidp->oid_arg1; 4529212902Sjhb val = E1000_READ_REG(&adapter->hw, oidp->oid_arg2); 4530212902Sjhb return (sysctl_handle_int(oidp, &val, 0, req)); 4531205869Sjfv} 4532205869Sjfv 4533212902Sjhb/* 4534212902Sjhb * Add sysctl variables, one per statistic, to the system. 4535212902Sjhb */ 4536205869Sjfvstatic void 4537212902Sjhblem_add_hw_stats(struct adapter *adapter) 4538205869Sjfv{ 4539205869Sjfv device_t dev = adapter->dev; 4540205869Sjfv 4541212902Sjhb struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 4542212902Sjhb struct sysctl_oid *tree = device_get_sysctl_tree(dev); 4543212902Sjhb struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 4544212902Sjhb struct e1000_hw_stats *stats = &adapter->stats; 4545212902Sjhb 4546212902Sjhb struct sysctl_oid *stat_node; 4547212902Sjhb struct sysctl_oid_list *stat_list; 4548212902Sjhb 4549212902Sjhb /* Driver Statistics */ 4550212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail", 4551212902Sjhb CTLFLAG_RD, &adapter->mbuf_cluster_failed, 4552212902Sjhb "Std mbuf cluster failed"); 4553294958Smarius SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail", 4554294958Smarius CTLFLAG_RD, &adapter->mbuf_defrag_failed, 4555294958Smarius "Defragmenting mbuf chain failed"); 4556212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 4557212902Sjhb CTLFLAG_RD, &adapter->dropped_pkts, 4558212902Sjhb "Driver dropped packets"); 4559212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail", 4560212902Sjhb CTLFLAG_RD, &adapter->no_tx_dma_setup, 4561212902Sjhb "Driver tx dma failure in xmit"); 4562212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_desc_fail1", 4563212902Sjhb CTLFLAG_RD, &adapter->no_tx_desc_avail1, 4564212902Sjhb "Not enough tx descriptors failure in xmit"); 4565212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_desc_fail2", 4566212902Sjhb CTLFLAG_RD, &adapter->no_tx_desc_avail2, 4567212902Sjhb "Not enough tx descriptors failure in xmit"); 4568212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns", 4569212902Sjhb CTLFLAG_RD, &adapter->rx_overruns, 4570212902Sjhb "RX overruns"); 4571212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_timeouts", 4572212902Sjhb CTLFLAG_RD, &adapter->watchdog_events, 4573212902Sjhb "Watchdog timeouts"); 4574212902Sjhb 4575212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "device_control", 4576217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_CTRL, 4577212902Sjhb lem_sysctl_reg_handler, "IU", 4578212902Sjhb "Device Control Register"); 4579212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_control", 4580217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RCTL, 4581212902Sjhb lem_sysctl_reg_handler, "IU", 4582212902Sjhb "Receiver Control Register"); 4583212902Sjhb SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_high_water", 4584212902Sjhb CTLFLAG_RD, &adapter->hw.fc.high_water, 0, 4585212902Sjhb "Flow Control High Watermark"); 4586212902Sjhb SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_low_water", 4587212902Sjhb CTLFLAG_RD, &adapter->hw.fc.low_water, 0, 4588212902Sjhb "Flow Control Low Watermark"); 4589217318Smdf SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_workaround", 4590212902Sjhb CTLFLAG_RD, &adapter->tx_fifo_wrk_cnt, 4591212902Sjhb "TX FIFO workaround events"); 4592217318Smdf SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_reset", 4593212902Sjhb CTLFLAG_RD, &adapter->tx_fifo_reset_cnt, 4594212902Sjhb "TX FIFO resets"); 4595212902Sjhb 4596212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_head", 4597217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDH(0), 4598212902Sjhb lem_sysctl_reg_handler, "IU", 4599212902Sjhb "Transmit Descriptor Head"); 4600212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_tail", 4601217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDT(0), 4602212902Sjhb lem_sysctl_reg_handler, "IU", 4603212902Sjhb "Transmit Descriptor Tail"); 4604212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_head", 4605217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDH(0), 4606212902Sjhb lem_sysctl_reg_handler, "IU", 4607212902Sjhb "Receive Descriptor Head"); 4608212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_tail", 4609217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDT(0), 4610212902Sjhb lem_sysctl_reg_handler, "IU", 4611212902Sjhb "Receive Descriptor Tail"); 4612212902Sjhb 4613212902Sjhb 4614212902Sjhb /* MAC stats get their own sub node */ 4615212902Sjhb 4616212902Sjhb stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 4617212902Sjhb CTLFLAG_RD, NULL, "Statistics"); 4618212902Sjhb stat_list = SYSCTL_CHILDREN(stat_node); 4619212902Sjhb 4620217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "excess_coll", 4621212902Sjhb CTLFLAG_RD, &stats->ecol, 4622212902Sjhb "Excessive collisions"); 4623217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "single_coll", 4624212902Sjhb CTLFLAG_RD, &stats->scc, 4625212902Sjhb "Single collisions"); 4626217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "multiple_coll", 4627212902Sjhb CTLFLAG_RD, &stats->mcc, 4628212902Sjhb "Multiple collisions"); 4629217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "late_coll", 4630212902Sjhb CTLFLAG_RD, &stats->latecol, 4631212902Sjhb "Late collisions"); 4632217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "collision_count", 4633212902Sjhb CTLFLAG_RD, &stats->colc, 4634212902Sjhb "Collision Count"); 4635217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "symbol_errors", 4636212902Sjhb CTLFLAG_RD, &adapter->stats.symerrs, 4637212902Sjhb "Symbol Errors"); 4638217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "sequence_errors", 4639212902Sjhb CTLFLAG_RD, &adapter->stats.sec, 4640212902Sjhb "Sequence Errors"); 4641217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "defer_count", 4642212902Sjhb CTLFLAG_RD, &adapter->stats.dc, 4643212902Sjhb "Defer Count"); 4644217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "missed_packets", 4645212902Sjhb CTLFLAG_RD, &adapter->stats.mpc, 4646212902Sjhb "Missed Packets"); 4647217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_no_buff", 4648212902Sjhb CTLFLAG_RD, &adapter->stats.rnbc, 4649212902Sjhb "Receive No Buffers"); 4650217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersize", 4651212902Sjhb CTLFLAG_RD, &adapter->stats.ruc, 4652212902Sjhb "Receive Undersize"); 4653217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", 4654212902Sjhb CTLFLAG_RD, &adapter->stats.rfc, 4655212902Sjhb "Fragmented Packets Received "); 4656217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversize", 4657212902Sjhb CTLFLAG_RD, &adapter->stats.roc, 4658212902Sjhb "Oversized Packets Received"); 4659217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabber", 4660212902Sjhb CTLFLAG_RD, &adapter->stats.rjc, 4661212902Sjhb "Recevied Jabber"); 4662217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_errs", 4663212902Sjhb CTLFLAG_RD, &adapter->stats.rxerrc, 4664212902Sjhb "Receive Errors"); 4665217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", 4666212902Sjhb CTLFLAG_RD, &adapter->stats.crcerrs, 4667212902Sjhb "CRC errors"); 4668217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "alignment_errs", 4669212902Sjhb CTLFLAG_RD, &adapter->stats.algnerrc, 4670212902Sjhb "Alignment Errors"); 4671217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs", 4672212902Sjhb CTLFLAG_RD, &adapter->stats.cexterr, 4673212902Sjhb "Collision/Carrier extension errors"); 4674217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", 4675212902Sjhb CTLFLAG_RD, &adapter->stats.xonrxc, 4676212902Sjhb "XON Received"); 4677217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", 4678212902Sjhb CTLFLAG_RD, &adapter->stats.xontxc, 4679212902Sjhb "XON Transmitted"); 4680217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", 4681212902Sjhb CTLFLAG_RD, &adapter->stats.xoffrxc, 4682212902Sjhb "XOFF Received"); 4683217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", 4684212902Sjhb CTLFLAG_RD, &adapter->stats.xofftxc, 4685212902Sjhb "XOFF Transmitted"); 4686212902Sjhb 4687212902Sjhb /* Packet Reception Stats */ 4688217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd", 4689212902Sjhb CTLFLAG_RD, &adapter->stats.tpr, 4690212902Sjhb "Total Packets Received "); 4691217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd", 4692212902Sjhb CTLFLAG_RD, &adapter->stats.gprc, 4693212902Sjhb "Good Packets Received"); 4694217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd", 4695212902Sjhb CTLFLAG_RD, &adapter->stats.bprc, 4696212902Sjhb "Broadcast Packets Received"); 4697217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd", 4698212902Sjhb CTLFLAG_RD, &adapter->stats.mprc, 4699212902Sjhb "Multicast Packets Received"); 4700217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", 4701212902Sjhb CTLFLAG_RD, &adapter->stats.prc64, 4702212902Sjhb "64 byte frames received "); 4703217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", 4704212902Sjhb CTLFLAG_RD, &adapter->stats.prc127, 4705212902Sjhb "65-127 byte frames received"); 4706217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", 4707212902Sjhb CTLFLAG_RD, &adapter->stats.prc255, 4708212902Sjhb "128-255 byte frames received"); 4709217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", 4710212902Sjhb CTLFLAG_RD, &adapter->stats.prc511, 4711212902Sjhb "256-511 byte frames received"); 4712217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", 4713212902Sjhb CTLFLAG_RD, &adapter->stats.prc1023, 4714212902Sjhb "512-1023 byte frames received"); 4715217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", 4716212902Sjhb CTLFLAG_RD, &adapter->stats.prc1522, 4717212902Sjhb "1023-1522 byte frames received"); 4718217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd", 4719212902Sjhb CTLFLAG_RD, &adapter->stats.gorc, 4720212902Sjhb "Good Octets Received"); 4721212902Sjhb 4722212902Sjhb /* Packet Transmission Stats */ 4723217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 4724212902Sjhb CTLFLAG_RD, &adapter->stats.gotc, 4725212902Sjhb "Good Octets Transmitted"); 4726217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", 4727212902Sjhb CTLFLAG_RD, &adapter->stats.tpt, 4728212902Sjhb "Total Packets Transmitted"); 4729217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 4730212902Sjhb CTLFLAG_RD, &adapter->stats.gptc, 4731212902Sjhb "Good Packets Transmitted"); 4732217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 4733212902Sjhb CTLFLAG_RD, &adapter->stats.bptc, 4734212902Sjhb "Broadcast Packets Transmitted"); 4735217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 4736212902Sjhb CTLFLAG_RD, &adapter->stats.mptc, 4737212902Sjhb "Multicast Packets Transmitted"); 4738217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", 4739212902Sjhb CTLFLAG_RD, &adapter->stats.ptc64, 4740212902Sjhb "64 byte frames transmitted "); 4741217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", 4742212902Sjhb CTLFLAG_RD, &adapter->stats.ptc127, 4743212902Sjhb "65-127 byte frames transmitted"); 4744217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", 4745212902Sjhb CTLFLAG_RD, &adapter->stats.ptc255, 4746212902Sjhb "128-255 byte frames transmitted"); 4747217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", 4748212902Sjhb CTLFLAG_RD, &adapter->stats.ptc511, 4749212902Sjhb "256-511 byte frames transmitted"); 4750217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", 4751212902Sjhb CTLFLAG_RD, &adapter->stats.ptc1023, 4752212902Sjhb "512-1023 byte frames transmitted"); 4753217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", 4754212902Sjhb CTLFLAG_RD, &adapter->stats.ptc1522, 4755212902Sjhb "1024-1522 byte frames transmitted"); 4756217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_txd", 4757212902Sjhb CTLFLAG_RD, &adapter->stats.tsctc, 4758212902Sjhb "TSO Contexts Transmitted"); 4759217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail", 4760212902Sjhb CTLFLAG_RD, &adapter->stats.tsctfc, 4761212902Sjhb "TSO Contexts Failed"); 4762205869Sjfv} 4763205869Sjfv 4764205869Sjfv/********************************************************************** 4765205869Sjfv * 4766205869Sjfv * This routine provides a way to dump out the adapter eeprom, 4767205869Sjfv * often a useful debug/service tool. This only dumps the first 4768205869Sjfv * 32 words, stuff that matters is in that extent. 4769205869Sjfv * 4770205869Sjfv **********************************************************************/ 4771205869Sjfv 4772205869Sjfvstatic int 4773212902Sjhblem_sysctl_nvm_info(SYSCTL_HANDLER_ARGS) 4774205869Sjfv{ 4775205869Sjfv struct adapter *adapter; 4776205869Sjfv int error; 4777205869Sjfv int result; 4778205869Sjfv 4779205869Sjfv result = -1; 4780205869Sjfv error = sysctl_handle_int(oidp, &result, 0, req); 4781205869Sjfv 4782205869Sjfv if (error || !req->newptr) 4783205869Sjfv return (error); 4784205869Sjfv 4785205869Sjfv /* 4786205869Sjfv * This value will cause a hex dump of the 4787205869Sjfv * first 32 16-bit words of the EEPROM to 4788205869Sjfv * the screen. 4789205869Sjfv */ 4790212902Sjhb if (result == 1) { 4791205869Sjfv adapter = (struct adapter *)arg1; 4792205869Sjfv lem_print_nvm_info(adapter); 4793205869Sjfv } 4794205869Sjfv 4795205869Sjfv return (error); 4796205869Sjfv} 4797205869Sjfv 4798212902Sjhbstatic void 4799212902Sjhblem_print_nvm_info(struct adapter *adapter) 4800205869Sjfv{ 4801212902Sjhb u16 eeprom_data; 4802212902Sjhb int i, j, row = 0; 4803205869Sjfv 4804212902Sjhb /* Its a bit crude, but it gets the job done */ 4805212902Sjhb printf("\nInterface EEPROM Dump:\n"); 4806212902Sjhb printf("Offset\n0x0000 "); 4807212902Sjhb for (i = 0, j = 0; i < 32; i++, j++) { 4808212902Sjhb if (j == 8) { /* Make the offset block */ 4809212902Sjhb j = 0; ++row; 4810212902Sjhb printf("\n0x00%x0 ",row); 4811212902Sjhb } 4812212902Sjhb e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data); 4813212902Sjhb printf("%04x ", eeprom_data); 4814205869Sjfv } 4815212902Sjhb printf("\n"); 4816205869Sjfv} 4817205869Sjfv 4818205869Sjfvstatic int 4819205869Sjfvlem_sysctl_int_delay(SYSCTL_HANDLER_ARGS) 4820205869Sjfv{ 4821205869Sjfv struct em_int_delay_info *info; 4822205869Sjfv struct adapter *adapter; 4823205869Sjfv u32 regval; 4824205869Sjfv int error; 4825205869Sjfv int usecs; 4826205869Sjfv int ticks; 4827205869Sjfv 4828205869Sjfv info = (struct em_int_delay_info *)arg1; 4829205869Sjfv usecs = info->value; 4830205869Sjfv error = sysctl_handle_int(oidp, &usecs, 0, req); 4831205869Sjfv if (error != 0 || req->newptr == NULL) 4832205869Sjfv return (error); 4833205869Sjfv if (usecs < 0 || usecs > EM_TICKS_TO_USECS(65535)) 4834205869Sjfv return (EINVAL); 4835205869Sjfv info->value = usecs; 4836205869Sjfv ticks = EM_USECS_TO_TICKS(usecs); 4837250414Sluigi if (info->offset == E1000_ITR) /* units are 256ns here */ 4838250414Sluigi ticks *= 4; 4839205869Sjfv 4840205869Sjfv adapter = info->adapter; 4841205869Sjfv 4842205869Sjfv EM_CORE_LOCK(adapter); 4843205869Sjfv regval = E1000_READ_OFFSET(&adapter->hw, info->offset); 4844205869Sjfv regval = (regval & ~0xffff) | (ticks & 0xffff); 4845205869Sjfv /* Handle a few special cases. */ 4846205869Sjfv switch (info->offset) { 4847205869Sjfv case E1000_RDTR: 4848205869Sjfv break; 4849205869Sjfv case E1000_TIDV: 4850205869Sjfv if (ticks == 0) { 4851205869Sjfv adapter->txd_cmd &= ~E1000_TXD_CMD_IDE; 4852205869Sjfv /* Don't write 0 into the TIDV register. */ 4853205869Sjfv regval++; 4854205869Sjfv } else 4855205869Sjfv adapter->txd_cmd |= E1000_TXD_CMD_IDE; 4856205869Sjfv break; 4857205869Sjfv } 4858205869Sjfv E1000_WRITE_OFFSET(&adapter->hw, info->offset, regval); 4859205869Sjfv EM_CORE_UNLOCK(adapter); 4860205869Sjfv return (0); 4861205869Sjfv} 4862205869Sjfv 4863205869Sjfvstatic void 4864205869Sjfvlem_add_int_delay_sysctl(struct adapter *adapter, const char *name, 4865205869Sjfv const char *description, struct em_int_delay_info *info, 4866205869Sjfv int offset, int value) 4867205869Sjfv{ 4868205869Sjfv info->adapter = adapter; 4869205869Sjfv info->offset = offset; 4870205869Sjfv info->value = value; 4871205869Sjfv SYSCTL_ADD_PROC(device_get_sysctl_ctx(adapter->dev), 4872205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4873205869Sjfv OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, 4874205869Sjfv info, 0, lem_sysctl_int_delay, "I", description); 4875205869Sjfv} 4876205869Sjfv 4877214646Sjfvstatic void 4878214646Sjfvlem_set_flow_cntrl(struct adapter *adapter, const char *name, 4879214646Sjfv const char *description, int *limit, int value) 4880214646Sjfv{ 4881214646Sjfv *limit = value; 4882214646Sjfv SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 4883214646Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4884273736Shselasky OID_AUTO, name, CTLFLAG_RW, limit, value, description); 4885214646Sjfv} 4886214646Sjfv 4887205869Sjfvstatic void 4888205869Sjfvlem_add_rx_process_limit(struct adapter *adapter, const char *name, 4889205869Sjfv const char *description, int *limit, int value) 4890205869Sjfv{ 4891205869Sjfv *limit = value; 4892205869Sjfv SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 4893205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4894273736Shselasky OID_AUTO, name, CTLFLAG_RW, limit, value, description); 4895205869Sjfv} 4896