1205869Sjfv/****************************************************************************** 2205869Sjfv 3238953Sjfv Copyright (c) 2001-2012, 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$*/ 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 *********************************************************************/ 98249074Sjfvchar lem_driver_version[] = "1.0.6"; 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 954270252Sluigi if (if_getdrvflags(ifp) & 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; 1050205869Sjfv lem_init_locked(adapter); 1051205869Sjfv EM_CORE_UNLOCK(adapter); 1052205869Sjfv break; 1053205869Sjfv } 1054205869Sjfv case SIOCSIFFLAGS: 1055205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd:\ 1056205869Sjfv SIOCSIFFLAGS (Set Interface Flags)"); 1057205869Sjfv EM_CORE_LOCK(adapter); 1058205869Sjfv if (ifp->if_flags & IFF_UP) { 1059205869Sjfv if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { 1060205869Sjfv if ((ifp->if_flags ^ adapter->if_flags) & 1061205869Sjfv (IFF_PROMISC | IFF_ALLMULTI)) { 1062205869Sjfv lem_disable_promisc(adapter); 1063205869Sjfv lem_set_promisc(adapter); 1064205869Sjfv } 1065205869Sjfv } else 1066205869Sjfv lem_init_locked(adapter); 1067205869Sjfv } else 1068205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1069205869Sjfv EM_TX_LOCK(adapter); 1070205869Sjfv lem_stop(adapter); 1071205869Sjfv EM_TX_UNLOCK(adapter); 1072205869Sjfv } 1073205869Sjfv adapter->if_flags = ifp->if_flags; 1074205869Sjfv EM_CORE_UNLOCK(adapter); 1075205869Sjfv break; 1076205869Sjfv case SIOCADDMULTI: 1077205869Sjfv case SIOCDELMULTI: 1078205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI"); 1079205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1080205869Sjfv EM_CORE_LOCK(adapter); 1081205869Sjfv lem_disable_intr(adapter); 1082205869Sjfv lem_set_multi(adapter); 1083205869Sjfv if (adapter->hw.mac.type == e1000_82542 && 1084205869Sjfv adapter->hw.revision_id == E1000_REVISION_2) { 1085205869Sjfv lem_initialize_receive_unit(adapter); 1086205869Sjfv } 1087205869Sjfv#ifdef DEVICE_POLLING 1088205869Sjfv if (!(ifp->if_capenable & IFCAP_POLLING)) 1089205869Sjfv#endif 1090205869Sjfv lem_enable_intr(adapter); 1091205869Sjfv EM_CORE_UNLOCK(adapter); 1092205869Sjfv } 1093205869Sjfv break; 1094205869Sjfv case SIOCSIFMEDIA: 1095205869Sjfv /* Check SOL/IDER usage */ 1096205869Sjfv EM_CORE_LOCK(adapter); 1097205869Sjfv if (e1000_check_reset_block(&adapter->hw)) { 1098205869Sjfv EM_CORE_UNLOCK(adapter); 1099205869Sjfv device_printf(adapter->dev, "Media change is" 1100205869Sjfv " blocked due to SOL/IDER session.\n"); 1101205869Sjfv break; 1102205869Sjfv } 1103205869Sjfv EM_CORE_UNLOCK(adapter); 1104205869Sjfv case SIOCGIFMEDIA: 1105205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: \ 1106205869Sjfv SIOCxIFMEDIA (Get/Set Interface Media)"); 1107205869Sjfv error = ifmedia_ioctl(ifp, ifr, &adapter->media, command); 1108205869Sjfv break; 1109205869Sjfv case SIOCSIFCAP: 1110205869Sjfv { 1111205869Sjfv int mask, reinit; 1112205869Sjfv 1113205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)"); 1114205869Sjfv reinit = 0; 1115205869Sjfv mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1116205869Sjfv#ifdef DEVICE_POLLING 1117205869Sjfv if (mask & IFCAP_POLLING) { 1118205869Sjfv if (ifr->ifr_reqcap & IFCAP_POLLING) { 1119205869Sjfv error = ether_poll_register(lem_poll, ifp); 1120205869Sjfv if (error) 1121205869Sjfv return (error); 1122205869Sjfv EM_CORE_LOCK(adapter); 1123205869Sjfv lem_disable_intr(adapter); 1124205869Sjfv ifp->if_capenable |= IFCAP_POLLING; 1125205869Sjfv EM_CORE_UNLOCK(adapter); 1126205869Sjfv } else { 1127205869Sjfv error = ether_poll_deregister(ifp); 1128205869Sjfv /* Enable interrupt even in error case */ 1129205869Sjfv EM_CORE_LOCK(adapter); 1130205869Sjfv lem_enable_intr(adapter); 1131205869Sjfv ifp->if_capenable &= ~IFCAP_POLLING; 1132205869Sjfv EM_CORE_UNLOCK(adapter); 1133205869Sjfv } 1134205869Sjfv } 1135205869Sjfv#endif 1136205869Sjfv if (mask & IFCAP_HWCSUM) { 1137205869Sjfv ifp->if_capenable ^= IFCAP_HWCSUM; 1138205869Sjfv reinit = 1; 1139205869Sjfv } 1140205869Sjfv if (mask & IFCAP_VLAN_HWTAGGING) { 1141205869Sjfv ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 1142205869Sjfv reinit = 1; 1143205869Sjfv } 1144205869Sjfv if ((mask & IFCAP_WOL) && 1145205869Sjfv (ifp->if_capabilities & IFCAP_WOL) != 0) { 1146205869Sjfv if (mask & IFCAP_WOL_MCAST) 1147205869Sjfv ifp->if_capenable ^= IFCAP_WOL_MCAST; 1148205869Sjfv if (mask & IFCAP_WOL_MAGIC) 1149205869Sjfv ifp->if_capenable ^= IFCAP_WOL_MAGIC; 1150205869Sjfv } 1151205869Sjfv if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING)) 1152205869Sjfv lem_init(adapter); 1153205869Sjfv VLAN_CAPABILITIES(ifp); 1154205869Sjfv break; 1155205869Sjfv } 1156205869Sjfv 1157205869Sjfv default: 1158205869Sjfv error = ether_ioctl(ifp, command, data); 1159205869Sjfv break; 1160205869Sjfv } 1161205869Sjfv 1162205869Sjfv return (error); 1163205869Sjfv} 1164205869Sjfv 1165205869Sjfv 1166205869Sjfv/********************************************************************* 1167205869Sjfv * Init entry point 1168205869Sjfv * 1169205869Sjfv * This routine is used in two ways. It is used by the stack as 1170205869Sjfv * init entry point in network interface structure. It is also used 1171205869Sjfv * by the driver as a hw/sw initialization routine to get to a 1172205869Sjfv * consistent state. 1173205869Sjfv * 1174205869Sjfv * return 0 on success, positive on failure 1175205869Sjfv **********************************************************************/ 1176205869Sjfv 1177205869Sjfvstatic void 1178205869Sjfvlem_init_locked(struct adapter *adapter) 1179205869Sjfv{ 1180205869Sjfv struct ifnet *ifp = adapter->ifp; 1181205869Sjfv device_t dev = adapter->dev; 1182205869Sjfv u32 pba; 1183205869Sjfv 1184205869Sjfv INIT_DEBUGOUT("lem_init: begin"); 1185205869Sjfv 1186205869Sjfv EM_CORE_LOCK_ASSERT(adapter); 1187205869Sjfv 1188205869Sjfv EM_TX_LOCK(adapter); 1189205869Sjfv lem_stop(adapter); 1190205869Sjfv EM_TX_UNLOCK(adapter); 1191205869Sjfv 1192205869Sjfv /* 1193205869Sjfv * Packet Buffer Allocation (PBA) 1194205869Sjfv * Writing PBA sets the receive portion of the buffer 1195205869Sjfv * the remainder is used for the transmit buffer. 1196205869Sjfv * 1197205869Sjfv * Devices before the 82547 had a Packet Buffer of 64K. 1198205869Sjfv * Default allocation: PBA=48K for Rx, leaving 16K for Tx. 1199205869Sjfv * After the 82547 the buffer was reduced to 40K. 1200205869Sjfv * Default allocation: PBA=30K for Rx, leaving 10K for Tx. 1201205869Sjfv * Note: default does not leave enough room for Jumbo Frame >10k. 1202205869Sjfv */ 1203205869Sjfv switch (adapter->hw.mac.type) { 1204205869Sjfv case e1000_82547: 1205205869Sjfv case e1000_82547_rev_2: /* 82547: Total Packet Buffer is 40K */ 1206205869Sjfv if (adapter->max_frame_size > 8192) 1207205869Sjfv pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */ 1208205869Sjfv else 1209205869Sjfv pba = E1000_PBA_30K; /* 30K for Rx, 10K for Tx */ 1210205869Sjfv adapter->tx_fifo_head = 0; 1211205869Sjfv adapter->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT; 1212205869Sjfv adapter->tx_fifo_size = 1213205869Sjfv (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT; 1214205869Sjfv break; 1215205869Sjfv default: 1216205869Sjfv /* Devices before 82547 had a Packet Buffer of 64K. */ 1217205869Sjfv if (adapter->max_frame_size > 8192) 1218205869Sjfv pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */ 1219205869Sjfv else 1220205869Sjfv pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */ 1221205869Sjfv } 1222205869Sjfv 1223205869Sjfv INIT_DEBUGOUT1("lem_init: pba=%dK",pba); 1224205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_PBA, pba); 1225205869Sjfv 1226205869Sjfv /* Get the latest mac address, User can use a LAA */ 1227205869Sjfv bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr, 1228205869Sjfv ETHER_ADDR_LEN); 1229205869Sjfv 1230205869Sjfv /* Put the address into the Receive Address Array */ 1231205869Sjfv e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); 1232205869Sjfv 1233205869Sjfv /* Initialize the hardware */ 1234205869Sjfv if (lem_hardware_init(adapter)) { 1235205869Sjfv device_printf(dev, "Unable to initialize the hardware\n"); 1236205869Sjfv return; 1237205869Sjfv } 1238205869Sjfv lem_update_link_status(adapter); 1239205869Sjfv 1240205869Sjfv /* Setup VLAN support, basic and offload if available */ 1241205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN); 1242205869Sjfv 1243205869Sjfv /* Set hardware offload abilities */ 1244205869Sjfv ifp->if_hwassist = 0; 1245205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 1246205869Sjfv if (ifp->if_capenable & IFCAP_TXCSUM) 1247205869Sjfv ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); 1248205869Sjfv } 1249205869Sjfv 1250205869Sjfv /* Configure for OS presence */ 1251205869Sjfv lem_init_manageability(adapter); 1252205869Sjfv 1253205869Sjfv /* Prepare transmit descriptors and buffers */ 1254205869Sjfv lem_setup_transmit_structures(adapter); 1255205869Sjfv lem_initialize_transmit_unit(adapter); 1256205869Sjfv 1257205869Sjfv /* Setup Multicast table */ 1258205869Sjfv lem_set_multi(adapter); 1259205869Sjfv 1260205869Sjfv /* Prepare receive descriptors and buffers */ 1261205869Sjfv if (lem_setup_receive_structures(adapter)) { 1262205869Sjfv device_printf(dev, "Could not setup receive structures\n"); 1263205869Sjfv EM_TX_LOCK(adapter); 1264205869Sjfv lem_stop(adapter); 1265205869Sjfv EM_TX_UNLOCK(adapter); 1266205869Sjfv return; 1267205869Sjfv } 1268205869Sjfv lem_initialize_receive_unit(adapter); 1269205869Sjfv 1270214646Sjfv /* Use real VLAN Filter support? */ 1271214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { 1272214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 1273214646Sjfv /* Use real VLAN Filter support */ 1274214646Sjfv lem_setup_vlan_hw_support(adapter); 1275214646Sjfv else { 1276214646Sjfv u32 ctrl; 1277214646Sjfv ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); 1278214646Sjfv ctrl |= E1000_CTRL_VME; 1279214646Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); 1280214646Sjfv } 1281214646Sjfv } 1282214646Sjfv 1283205869Sjfv /* Don't lose promiscuous settings */ 1284205869Sjfv lem_set_promisc(adapter); 1285205869Sjfv 1286205869Sjfv ifp->if_drv_flags |= IFF_DRV_RUNNING; 1287205869Sjfv ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1288205869Sjfv 1289205869Sjfv callout_reset(&adapter->timer, hz, lem_local_timer, adapter); 1290205869Sjfv e1000_clear_hw_cntrs_base_generic(&adapter->hw); 1291205869Sjfv 1292205869Sjfv#ifdef DEVICE_POLLING 1293205869Sjfv /* 1294205869Sjfv * Only enable interrupts if we are not polling, make sure 1295205869Sjfv * they are off otherwise. 1296205869Sjfv */ 1297205869Sjfv if (ifp->if_capenable & IFCAP_POLLING) 1298205869Sjfv lem_disable_intr(adapter); 1299205869Sjfv else 1300205869Sjfv#endif /* DEVICE_POLLING */ 1301205869Sjfv lem_enable_intr(adapter); 1302205869Sjfv 1303205869Sjfv /* AMT based hardware can now take control from firmware */ 1304205869Sjfv if (adapter->has_manage && adapter->has_amt) 1305205869Sjfv lem_get_hw_control(adapter); 1306205869Sjfv} 1307205869Sjfv 1308205869Sjfvstatic void 1309205869Sjfvlem_init(void *arg) 1310205869Sjfv{ 1311205869Sjfv struct adapter *adapter = arg; 1312205869Sjfv 1313205869Sjfv EM_CORE_LOCK(adapter); 1314205869Sjfv lem_init_locked(adapter); 1315205869Sjfv EM_CORE_UNLOCK(adapter); 1316205869Sjfv} 1317205869Sjfv 1318205869Sjfv 1319205869Sjfv#ifdef DEVICE_POLLING 1320205869Sjfv/********************************************************************* 1321205869Sjfv * 1322205869Sjfv * Legacy polling routine 1323205869Sjfv * 1324205869Sjfv *********************************************************************/ 1325205869Sjfvstatic int 1326205869Sjfvlem_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 1327205869Sjfv{ 1328205869Sjfv struct adapter *adapter = ifp->if_softc; 1329205869Sjfv u32 reg_icr, rx_done = 0; 1330205869Sjfv 1331205869Sjfv EM_CORE_LOCK(adapter); 1332205869Sjfv if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1333205869Sjfv EM_CORE_UNLOCK(adapter); 1334205869Sjfv return (rx_done); 1335205869Sjfv } 1336205869Sjfv 1337205869Sjfv if (cmd == POLL_AND_CHECK_STATUS) { 1338205869Sjfv reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); 1339205869Sjfv if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 1340205869Sjfv callout_stop(&adapter->timer); 1341205869Sjfv adapter->hw.mac.get_link_status = 1; 1342205869Sjfv lem_update_link_status(adapter); 1343205869Sjfv callout_reset(&adapter->timer, hz, 1344205869Sjfv lem_local_timer, adapter); 1345205869Sjfv } 1346205869Sjfv } 1347205869Sjfv EM_CORE_UNLOCK(adapter); 1348205869Sjfv 1349209238Sjfv lem_rxeof(adapter, count, &rx_done); 1350205869Sjfv 1351205869Sjfv EM_TX_LOCK(adapter); 1352205869Sjfv lem_txeof(adapter); 1353205869Sjfv if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1354205869Sjfv lem_start_locked(ifp); 1355205869Sjfv EM_TX_UNLOCK(adapter); 1356205869Sjfv return (rx_done); 1357205869Sjfv} 1358205869Sjfv#endif /* DEVICE_POLLING */ 1359205869Sjfv 1360205869Sjfv/********************************************************************* 1361205869Sjfv * 1362205869Sjfv * Legacy Interrupt Service routine 1363205869Sjfv * 1364205869Sjfv *********************************************************************/ 1365205869Sjfvstatic void 1366205869Sjfvlem_intr(void *arg) 1367205869Sjfv{ 1368205869Sjfv struct adapter *adapter = arg; 1369205869Sjfv struct ifnet *ifp = adapter->ifp; 1370205869Sjfv u32 reg_icr; 1371205869Sjfv 1372205869Sjfv 1373238953Sjfv if ((ifp->if_capenable & IFCAP_POLLING) || 1374238953Sjfv ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)) 1375205869Sjfv return; 1376205869Sjfv 1377205869Sjfv EM_CORE_LOCK(adapter); 1378205869Sjfv reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); 1379205869Sjfv if (reg_icr & E1000_ICR_RXO) 1380205869Sjfv adapter->rx_overruns++; 1381205869Sjfv 1382238953Sjfv if ((reg_icr == 0xffffffff) || (reg_icr == 0)) { 1383238953Sjfv EM_CORE_UNLOCK(adapter); 1384238953Sjfv return; 1385238953Sjfv } 1386205869Sjfv 1387205869Sjfv if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 1388205869Sjfv callout_stop(&adapter->timer); 1389205869Sjfv adapter->hw.mac.get_link_status = 1; 1390205869Sjfv lem_update_link_status(adapter); 1391205869Sjfv /* Deal with TX cruft when link lost */ 1392205869Sjfv lem_tx_purge(adapter); 1393205869Sjfv callout_reset(&adapter->timer, hz, 1394205869Sjfv lem_local_timer, adapter); 1395238953Sjfv EM_CORE_UNLOCK(adapter); 1396238953Sjfv return; 1397205869Sjfv } 1398205869Sjfv 1399238953Sjfv EM_CORE_UNLOCK(adapter); 1400238953Sjfv lem_rxeof(adapter, -1, NULL); 1401238953Sjfv 1402205869Sjfv EM_TX_LOCK(adapter); 1403205869Sjfv lem_txeof(adapter); 1404205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING && 1405205869Sjfv !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1406205869Sjfv lem_start_locked(ifp); 1407205869Sjfv EM_TX_UNLOCK(adapter); 1408205869Sjfv return; 1409205869Sjfv} 1410205869Sjfv 1411205869Sjfv 1412205869Sjfvstatic void 1413205869Sjfvlem_handle_link(void *context, int pending) 1414205869Sjfv{ 1415205869Sjfv struct adapter *adapter = context; 1416205869Sjfv struct ifnet *ifp = adapter->ifp; 1417205869Sjfv 1418205869Sjfv if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 1419205869Sjfv return; 1420205869Sjfv 1421205869Sjfv EM_CORE_LOCK(adapter); 1422205869Sjfv callout_stop(&adapter->timer); 1423205869Sjfv lem_update_link_status(adapter); 1424205869Sjfv /* Deal with TX cruft when link lost */ 1425205869Sjfv lem_tx_purge(adapter); 1426205869Sjfv callout_reset(&adapter->timer, hz, lem_local_timer, adapter); 1427205869Sjfv EM_CORE_UNLOCK(adapter); 1428205869Sjfv} 1429205869Sjfv 1430205869Sjfv 1431205869Sjfv/* Combined RX/TX handler, used by Legacy and MSI */ 1432205869Sjfvstatic void 1433205869Sjfvlem_handle_rxtx(void *context, int pending) 1434205869Sjfv{ 1435205869Sjfv struct adapter *adapter = context; 1436205869Sjfv struct ifnet *ifp = adapter->ifp; 1437205869Sjfv 1438205869Sjfv 1439205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1440250414Sluigi bool more = lem_rxeof(adapter, adapter->rx_process_limit, NULL); 1441205869Sjfv EM_TX_LOCK(adapter); 1442205869Sjfv lem_txeof(adapter); 1443205869Sjfv if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1444205869Sjfv lem_start_locked(ifp); 1445205869Sjfv EM_TX_UNLOCK(adapter); 1446250414Sluigi if (more) { 1447250414Sluigi taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); 1448250414Sluigi return; 1449250414Sluigi } 1450205869Sjfv } 1451205869Sjfv 1452214646Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1453214646Sjfv lem_enable_intr(adapter); 1454205869Sjfv} 1455205869Sjfv 1456205869Sjfv/********************************************************************* 1457205869Sjfv * 1458205869Sjfv * Fast Legacy/MSI Combined Interrupt Service routine 1459205869Sjfv * 1460205869Sjfv *********************************************************************/ 1461205869Sjfvstatic int 1462205869Sjfvlem_irq_fast(void *arg) 1463205869Sjfv{ 1464205869Sjfv struct adapter *adapter = arg; 1465205869Sjfv struct ifnet *ifp; 1466205869Sjfv u32 reg_icr; 1467205869Sjfv 1468205869Sjfv ifp = adapter->ifp; 1469205869Sjfv 1470205869Sjfv reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); 1471205869Sjfv 1472205869Sjfv /* Hot eject? */ 1473205869Sjfv if (reg_icr == 0xffffffff) 1474205869Sjfv return FILTER_STRAY; 1475205869Sjfv 1476205869Sjfv /* Definitely not our interrupt. */ 1477205869Sjfv if (reg_icr == 0x0) 1478205869Sjfv return FILTER_STRAY; 1479205869Sjfv 1480205869Sjfv /* 1481205869Sjfv * Mask interrupts until the taskqueue is finished running. This is 1482205869Sjfv * cheap, just assume that it is needed. This also works around the 1483205869Sjfv * MSI message reordering errata on certain systems. 1484205869Sjfv */ 1485205869Sjfv lem_disable_intr(adapter); 1486205869Sjfv taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); 1487205869Sjfv 1488205869Sjfv /* Link status change */ 1489205869Sjfv if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 1490205869Sjfv adapter->hw.mac.get_link_status = 1; 1491205869Sjfv taskqueue_enqueue(taskqueue_fast, &adapter->link_task); 1492205869Sjfv } 1493205869Sjfv 1494205869Sjfv if (reg_icr & E1000_ICR_RXO) 1495205869Sjfv adapter->rx_overruns++; 1496205869Sjfv return FILTER_HANDLED; 1497205869Sjfv} 1498205869Sjfv 1499205869Sjfv 1500205869Sjfv/********************************************************************* 1501205869Sjfv * 1502205869Sjfv * Media Ioctl callback 1503205869Sjfv * 1504205869Sjfv * This routine is called whenever the user queries the status of 1505205869Sjfv * the interface using ifconfig. 1506205869Sjfv * 1507205869Sjfv **********************************************************************/ 1508205869Sjfvstatic void 1509205869Sjfvlem_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 1510205869Sjfv{ 1511205869Sjfv struct adapter *adapter = ifp->if_softc; 1512205869Sjfv u_char fiber_type = IFM_1000_SX; 1513205869Sjfv 1514205869Sjfv INIT_DEBUGOUT("lem_media_status: begin"); 1515205869Sjfv 1516205869Sjfv EM_CORE_LOCK(adapter); 1517205869Sjfv lem_update_link_status(adapter); 1518205869Sjfv 1519205869Sjfv ifmr->ifm_status = IFM_AVALID; 1520205869Sjfv ifmr->ifm_active = IFM_ETHER; 1521205869Sjfv 1522205869Sjfv if (!adapter->link_active) { 1523205869Sjfv EM_CORE_UNLOCK(adapter); 1524205869Sjfv return; 1525205869Sjfv } 1526205869Sjfv 1527205869Sjfv ifmr->ifm_status |= IFM_ACTIVE; 1528205869Sjfv 1529205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 1530205869Sjfv (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) { 1531205869Sjfv if (adapter->hw.mac.type == e1000_82545) 1532205869Sjfv fiber_type = IFM_1000_LX; 1533205869Sjfv ifmr->ifm_active |= fiber_type | IFM_FDX; 1534205869Sjfv } else { 1535205869Sjfv switch (adapter->link_speed) { 1536205869Sjfv case 10: 1537205869Sjfv ifmr->ifm_active |= IFM_10_T; 1538205869Sjfv break; 1539205869Sjfv case 100: 1540205869Sjfv ifmr->ifm_active |= IFM_100_TX; 1541205869Sjfv break; 1542205869Sjfv case 1000: 1543205869Sjfv ifmr->ifm_active |= IFM_1000_T; 1544205869Sjfv break; 1545205869Sjfv } 1546205869Sjfv if (adapter->link_duplex == FULL_DUPLEX) 1547205869Sjfv ifmr->ifm_active |= IFM_FDX; 1548205869Sjfv else 1549205869Sjfv ifmr->ifm_active |= IFM_HDX; 1550205869Sjfv } 1551205869Sjfv EM_CORE_UNLOCK(adapter); 1552205869Sjfv} 1553205869Sjfv 1554205869Sjfv/********************************************************************* 1555205869Sjfv * 1556205869Sjfv * Media Ioctl callback 1557205869Sjfv * 1558205869Sjfv * This routine is called when the user changes speed/duplex using 1559205869Sjfv * media/mediopt option with ifconfig. 1560205869Sjfv * 1561205869Sjfv **********************************************************************/ 1562205869Sjfvstatic int 1563205869Sjfvlem_media_change(struct ifnet *ifp) 1564205869Sjfv{ 1565205869Sjfv struct adapter *adapter = ifp->if_softc; 1566205869Sjfv struct ifmedia *ifm = &adapter->media; 1567205869Sjfv 1568205869Sjfv INIT_DEBUGOUT("lem_media_change: begin"); 1569205869Sjfv 1570205869Sjfv if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1571205869Sjfv return (EINVAL); 1572205869Sjfv 1573205869Sjfv EM_CORE_LOCK(adapter); 1574205869Sjfv switch (IFM_SUBTYPE(ifm->ifm_media)) { 1575205869Sjfv case IFM_AUTO: 1576205869Sjfv adapter->hw.mac.autoneg = DO_AUTO_NEG; 1577205869Sjfv adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; 1578205869Sjfv break; 1579205869Sjfv case IFM_1000_LX: 1580205869Sjfv case IFM_1000_SX: 1581205869Sjfv case IFM_1000_T: 1582205869Sjfv adapter->hw.mac.autoneg = DO_AUTO_NEG; 1583205869Sjfv adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; 1584205869Sjfv break; 1585205869Sjfv case IFM_100_TX: 1586205869Sjfv adapter->hw.mac.autoneg = FALSE; 1587205869Sjfv adapter->hw.phy.autoneg_advertised = 0; 1588205869Sjfv if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1589205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_FULL; 1590205869Sjfv else 1591205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_HALF; 1592205869Sjfv break; 1593205869Sjfv case IFM_10_T: 1594205869Sjfv adapter->hw.mac.autoneg = FALSE; 1595205869Sjfv adapter->hw.phy.autoneg_advertised = 0; 1596205869Sjfv if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1597205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_FULL; 1598205869Sjfv else 1599205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_HALF; 1600205869Sjfv break; 1601205869Sjfv default: 1602205869Sjfv device_printf(adapter->dev, "Unsupported media type\n"); 1603205869Sjfv } 1604205869Sjfv 1605205869Sjfv lem_init_locked(adapter); 1606205869Sjfv EM_CORE_UNLOCK(adapter); 1607205869Sjfv 1608205869Sjfv return (0); 1609205869Sjfv} 1610205869Sjfv 1611205869Sjfv/********************************************************************* 1612205869Sjfv * 1613205869Sjfv * This routine maps the mbufs to tx descriptors. 1614205869Sjfv * 1615205869Sjfv * return 0 on success, positive on failure 1616205869Sjfv **********************************************************************/ 1617205869Sjfv 1618205869Sjfvstatic int 1619205869Sjfvlem_xmit(struct adapter *adapter, struct mbuf **m_headp) 1620205869Sjfv{ 1621205869Sjfv bus_dma_segment_t segs[EM_MAX_SCATTER]; 1622205869Sjfv bus_dmamap_t map; 1623205869Sjfv struct em_buffer *tx_buffer, *tx_buffer_mapped; 1624205869Sjfv struct e1000_tx_desc *ctxd = NULL; 1625205869Sjfv struct mbuf *m_head; 1626205869Sjfv u32 txd_upper, txd_lower, txd_used, txd_saved; 1627205869Sjfv int error, nsegs, i, j, first, last = 0; 1628214646Sjfv 1629205869Sjfv m_head = *m_headp; 1630205869Sjfv txd_upper = txd_lower = txd_used = txd_saved = 0; 1631205869Sjfv 1632205869Sjfv /* 1633209959Sjfv ** When doing checksum offload, it is critical to 1634209959Sjfv ** make sure the first mbuf has more than header, 1635209959Sjfv ** because that routine expects data to be present. 1636209959Sjfv */ 1637209959Sjfv if ((m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) && 1638209959Sjfv (m_head->m_len < ETHER_HDR_LEN + sizeof(struct ip))) { 1639209959Sjfv m_head = m_pullup(m_head, ETHER_HDR_LEN + sizeof(struct ip)); 1640209959Sjfv *m_headp = m_head; 1641209959Sjfv if (m_head == NULL) 1642209959Sjfv return (ENOBUFS); 1643209959Sjfv } 1644209959Sjfv 1645209959Sjfv /* 1646205869Sjfv * Map the packet for DMA 1647205869Sjfv * 1648205869Sjfv * Capture the first descriptor index, 1649205869Sjfv * this descriptor will have the index 1650205869Sjfv * of the EOP which is the only one that 1651205869Sjfv * now gets a DONE bit writeback. 1652205869Sjfv */ 1653205869Sjfv first = adapter->next_avail_tx_desc; 1654205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 1655205869Sjfv tx_buffer_mapped = tx_buffer; 1656205869Sjfv map = tx_buffer->map; 1657205869Sjfv 1658205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, 1659205869Sjfv *m_headp, segs, &nsegs, BUS_DMA_NOWAIT); 1660205869Sjfv 1661205869Sjfv /* 1662205869Sjfv * There are two types of errors we can (try) to handle: 1663205869Sjfv * - EFBIG means the mbuf chain was too long and bus_dma ran 1664205869Sjfv * out of segments. Defragment the mbuf chain and try again. 1665205869Sjfv * - ENOMEM means bus_dma could not obtain enough bounce buffers 1666205869Sjfv * at this point in time. Defer sending and try again later. 1667205869Sjfv * All other errors, in particular EINVAL, are fatal and prevent the 1668205869Sjfv * mbuf chain from ever going through. Drop it and report error. 1669205869Sjfv */ 1670205869Sjfv if (error == EFBIG) { 1671205869Sjfv struct mbuf *m; 1672205869Sjfv 1673243857Sglebius m = m_defrag(*m_headp, M_NOWAIT); 1674205869Sjfv if (m == NULL) { 1675205869Sjfv adapter->mbuf_alloc_failed++; 1676205869Sjfv m_freem(*m_headp); 1677205869Sjfv *m_headp = NULL; 1678205869Sjfv return (ENOBUFS); 1679205869Sjfv } 1680205869Sjfv *m_headp = m; 1681205869Sjfv 1682205869Sjfv /* Try it again */ 1683205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, 1684205869Sjfv *m_headp, segs, &nsegs, BUS_DMA_NOWAIT); 1685205869Sjfv 1686205869Sjfv if (error) { 1687205869Sjfv adapter->no_tx_dma_setup++; 1688205869Sjfv m_freem(*m_headp); 1689205869Sjfv *m_headp = NULL; 1690205869Sjfv return (error); 1691205869Sjfv } 1692205869Sjfv } else if (error != 0) { 1693205869Sjfv adapter->no_tx_dma_setup++; 1694205869Sjfv return (error); 1695205869Sjfv } 1696205869Sjfv 1697205869Sjfv if (nsegs > (adapter->num_tx_desc_avail - 2)) { 1698205869Sjfv adapter->no_tx_desc_avail2++; 1699205869Sjfv bus_dmamap_unload(adapter->txtag, map); 1700205869Sjfv return (ENOBUFS); 1701205869Sjfv } 1702205869Sjfv m_head = *m_headp; 1703205869Sjfv 1704205869Sjfv /* Do hardware assists */ 1705205869Sjfv if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) 1706205869Sjfv lem_transmit_checksum_setup(adapter, m_head, 1707205869Sjfv &txd_upper, &txd_lower); 1708205869Sjfv 1709205869Sjfv i = adapter->next_avail_tx_desc; 1710205869Sjfv if (adapter->pcix_82544) 1711205869Sjfv txd_saved = i; 1712205869Sjfv 1713205869Sjfv /* Set up our transmit descriptors */ 1714205869Sjfv for (j = 0; j < nsegs; j++) { 1715205869Sjfv bus_size_t seg_len; 1716205869Sjfv bus_addr_t seg_addr; 1717205869Sjfv /* If adapter is 82544 and on PCIX bus */ 1718205869Sjfv if(adapter->pcix_82544) { 1719205869Sjfv DESC_ARRAY desc_array; 1720205869Sjfv u32 array_elements, counter; 1721205869Sjfv /* 1722205869Sjfv * Check the Address and Length combination and 1723205869Sjfv * split the data accordingly 1724205869Sjfv */ 1725205869Sjfv array_elements = lem_fill_descriptors(segs[j].ds_addr, 1726205869Sjfv segs[j].ds_len, &desc_array); 1727205869Sjfv for (counter = 0; counter < array_elements; counter++) { 1728205869Sjfv if (txd_used == adapter->num_tx_desc_avail) { 1729205869Sjfv adapter->next_avail_tx_desc = txd_saved; 1730205869Sjfv adapter->no_tx_desc_avail2++; 1731205869Sjfv bus_dmamap_unload(adapter->txtag, map); 1732205869Sjfv return (ENOBUFS); 1733205869Sjfv } 1734205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 1735205869Sjfv ctxd = &adapter->tx_desc_base[i]; 1736205869Sjfv ctxd->buffer_addr = htole64( 1737205869Sjfv desc_array.descriptor[counter].address); 1738205869Sjfv ctxd->lower.data = htole32( 1739205869Sjfv (adapter->txd_cmd | txd_lower | (u16) 1740205869Sjfv desc_array.descriptor[counter].length)); 1741205869Sjfv ctxd->upper.data = 1742205869Sjfv htole32((txd_upper)); 1743205869Sjfv last = i; 1744205869Sjfv if (++i == adapter->num_tx_desc) 1745205869Sjfv i = 0; 1746205869Sjfv tx_buffer->m_head = NULL; 1747205869Sjfv tx_buffer->next_eop = -1; 1748205869Sjfv txd_used++; 1749205869Sjfv } 1750205869Sjfv } else { 1751205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 1752205869Sjfv ctxd = &adapter->tx_desc_base[i]; 1753205869Sjfv seg_addr = segs[j].ds_addr; 1754205869Sjfv seg_len = segs[j].ds_len; 1755205869Sjfv ctxd->buffer_addr = htole64(seg_addr); 1756205869Sjfv ctxd->lower.data = htole32( 1757205869Sjfv adapter->txd_cmd | txd_lower | seg_len); 1758205869Sjfv ctxd->upper.data = 1759205869Sjfv htole32(txd_upper); 1760205869Sjfv last = i; 1761205869Sjfv if (++i == adapter->num_tx_desc) 1762205869Sjfv i = 0; 1763205869Sjfv tx_buffer->m_head = NULL; 1764205869Sjfv tx_buffer->next_eop = -1; 1765205869Sjfv } 1766205869Sjfv } 1767205869Sjfv 1768205869Sjfv adapter->next_avail_tx_desc = i; 1769205869Sjfv 1770205869Sjfv if (adapter->pcix_82544) 1771205869Sjfv adapter->num_tx_desc_avail -= txd_used; 1772205869Sjfv else 1773205869Sjfv adapter->num_tx_desc_avail -= nsegs; 1774205869Sjfv 1775205869Sjfv if (m_head->m_flags & M_VLANTAG) { 1776205869Sjfv /* Set the vlan id. */ 1777205869Sjfv ctxd->upper.fields.special = 1778205869Sjfv htole16(m_head->m_pkthdr.ether_vtag); 1779205869Sjfv /* Tell hardware to add tag */ 1780205869Sjfv ctxd->lower.data |= htole32(E1000_TXD_CMD_VLE); 1781205869Sjfv } 1782205869Sjfv 1783205869Sjfv tx_buffer->m_head = m_head; 1784205869Sjfv tx_buffer_mapped->map = tx_buffer->map; 1785205869Sjfv tx_buffer->map = map; 1786205869Sjfv bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE); 1787205869Sjfv 1788205869Sjfv /* 1789205869Sjfv * Last Descriptor of Packet 1790205869Sjfv * needs End Of Packet (EOP) 1791205869Sjfv * and Report Status (RS) 1792205869Sjfv */ 1793205869Sjfv ctxd->lower.data |= 1794205869Sjfv htole32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS); 1795205869Sjfv /* 1796205869Sjfv * Keep track in the first buffer which 1797205869Sjfv * descriptor will be written back 1798205869Sjfv */ 1799205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 1800205869Sjfv tx_buffer->next_eop = last; 1801213234Sjfv adapter->watchdog_time = ticks; 1802205869Sjfv 1803205869Sjfv /* 1804205869Sjfv * Advance the Transmit Descriptor Tail (TDT), this tells the E1000 1805205869Sjfv * that this frame is available to transmit. 1806205869Sjfv */ 1807205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 1808205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1809270252Sluigi 1810270252Sluigi#ifdef NIC_PARAVIRT 1811270252Sluigi if (adapter->csb) { 1812270252Sluigi adapter->csb->guest_tdt = i; 1813270252Sluigi /* XXX memory barrier ? */ 1814270252Sluigi if (adapter->csb->guest_csb_on && 1815270252Sluigi !(adapter->csb->host_need_txkick & 1)) { 1816270252Sluigi /* XXX maybe useless 1817270252Sluigi * clean the ring. maybe do it before ? 1818270252Sluigi * maybe a little bit of histeresys ? 1819270252Sluigi */ 1820270252Sluigi if (adapter->num_tx_desc_avail <= 64) {// XXX 1821270252Sluigi lem_txeof(adapter); 1822270252Sluigi } 1823270252Sluigi return (0); 1824270252Sluigi } 1825270252Sluigi } 1826270252Sluigi#endif /* NIC_PARAVIRT */ 1827270252Sluigi 1828270252Sluigi#ifdef NIC_SEND_COMBINING 1829270252Sluigi if (adapter->sc_enable) { 1830270252Sluigi if (adapter->shadow_tdt & MIT_PENDING_INT) { 1831270252Sluigi /* signal intr and data pending */ 1832270252Sluigi adapter->shadow_tdt = MIT_PENDING_TDT | (i & 0xffff); 1833270252Sluigi return (0); 1834270252Sluigi } else { 1835270252Sluigi adapter->shadow_tdt = MIT_PENDING_INT; 1836270252Sluigi } 1837270252Sluigi } 1838270252Sluigi#endif /* NIC_SEND_COMBINING */ 1839270252Sluigi 1840205869Sjfv if (adapter->hw.mac.type == e1000_82547 && 1841205869Sjfv adapter->link_duplex == HALF_DUPLEX) 1842205869Sjfv lem_82547_move_tail(adapter); 1843205869Sjfv else { 1844205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), i); 1845205869Sjfv if (adapter->hw.mac.type == e1000_82547) 1846205869Sjfv lem_82547_update_fifo_head(adapter, 1847205869Sjfv m_head->m_pkthdr.len); 1848205869Sjfv } 1849205869Sjfv 1850205869Sjfv return (0); 1851205869Sjfv} 1852205869Sjfv 1853205869Sjfv/********************************************************************* 1854205869Sjfv * 1855205869Sjfv * 82547 workaround to avoid controller hang in half-duplex environment. 1856205869Sjfv * The workaround is to avoid queuing a large packet that would span 1857205869Sjfv * the internal Tx FIFO ring boundary. We need to reset the FIFO pointers 1858205869Sjfv * in this case. We do that only when FIFO is quiescent. 1859205869Sjfv * 1860205869Sjfv **********************************************************************/ 1861205869Sjfvstatic void 1862205869Sjfvlem_82547_move_tail(void *arg) 1863205869Sjfv{ 1864205869Sjfv struct adapter *adapter = arg; 1865205869Sjfv struct e1000_tx_desc *tx_desc; 1866205869Sjfv u16 hw_tdt, sw_tdt, length = 0; 1867205869Sjfv bool eop = 0; 1868205869Sjfv 1869205869Sjfv EM_TX_LOCK_ASSERT(adapter); 1870205869Sjfv 1871205869Sjfv hw_tdt = E1000_READ_REG(&adapter->hw, E1000_TDT(0)); 1872205869Sjfv sw_tdt = adapter->next_avail_tx_desc; 1873205869Sjfv 1874205869Sjfv while (hw_tdt != sw_tdt) { 1875205869Sjfv tx_desc = &adapter->tx_desc_base[hw_tdt]; 1876205869Sjfv length += tx_desc->lower.flags.length; 1877205869Sjfv eop = tx_desc->lower.data & E1000_TXD_CMD_EOP; 1878205869Sjfv if (++hw_tdt == adapter->num_tx_desc) 1879205869Sjfv hw_tdt = 0; 1880205869Sjfv 1881205869Sjfv if (eop) { 1882205869Sjfv if (lem_82547_fifo_workaround(adapter, length)) { 1883205869Sjfv adapter->tx_fifo_wrk_cnt++; 1884205869Sjfv callout_reset(&adapter->tx_fifo_timer, 1, 1885205869Sjfv lem_82547_move_tail, adapter); 1886205869Sjfv break; 1887205869Sjfv } 1888205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), hw_tdt); 1889205869Sjfv lem_82547_update_fifo_head(adapter, length); 1890205869Sjfv length = 0; 1891205869Sjfv } 1892205869Sjfv } 1893205869Sjfv} 1894205869Sjfv 1895205869Sjfvstatic int 1896205869Sjfvlem_82547_fifo_workaround(struct adapter *adapter, int len) 1897205869Sjfv{ 1898205869Sjfv int fifo_space, fifo_pkt_len; 1899205869Sjfv 1900205869Sjfv fifo_pkt_len = roundup2(len + EM_FIFO_HDR, EM_FIFO_HDR); 1901205869Sjfv 1902205869Sjfv if (adapter->link_duplex == HALF_DUPLEX) { 1903205869Sjfv fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; 1904205869Sjfv 1905205869Sjfv if (fifo_pkt_len >= (EM_82547_PKT_THRESH + fifo_space)) { 1906205869Sjfv if (lem_82547_tx_fifo_reset(adapter)) 1907205869Sjfv return (0); 1908205869Sjfv else 1909205869Sjfv return (1); 1910205869Sjfv } 1911205869Sjfv } 1912205869Sjfv 1913205869Sjfv return (0); 1914205869Sjfv} 1915205869Sjfv 1916205869Sjfvstatic void 1917205869Sjfvlem_82547_update_fifo_head(struct adapter *adapter, int len) 1918205869Sjfv{ 1919205869Sjfv int fifo_pkt_len = roundup2(len + EM_FIFO_HDR, EM_FIFO_HDR); 1920205869Sjfv 1921205869Sjfv /* tx_fifo_head is always 16 byte aligned */ 1922205869Sjfv adapter->tx_fifo_head += fifo_pkt_len; 1923205869Sjfv if (adapter->tx_fifo_head >= adapter->tx_fifo_size) { 1924205869Sjfv adapter->tx_fifo_head -= adapter->tx_fifo_size; 1925205869Sjfv } 1926205869Sjfv} 1927205869Sjfv 1928205869Sjfv 1929205869Sjfvstatic int 1930205869Sjfvlem_82547_tx_fifo_reset(struct adapter *adapter) 1931205869Sjfv{ 1932205869Sjfv u32 tctl; 1933205869Sjfv 1934205869Sjfv if ((E1000_READ_REG(&adapter->hw, E1000_TDT(0)) == 1935205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDH(0))) && 1936205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_TDFT) == 1937205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDFH)) && 1938205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_TDFTS) == 1939205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDFHS)) && 1940205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_TDFPC) == 0)) { 1941205869Sjfv /* Disable TX unit */ 1942205869Sjfv tctl = E1000_READ_REG(&adapter->hw, E1000_TCTL); 1943205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, 1944205869Sjfv tctl & ~E1000_TCTL_EN); 1945205869Sjfv 1946205869Sjfv /* Reset FIFO pointers */ 1947205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFT, 1948205869Sjfv adapter->tx_head_addr); 1949205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFH, 1950205869Sjfv adapter->tx_head_addr); 1951205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFTS, 1952205869Sjfv adapter->tx_head_addr); 1953205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFHS, 1954205869Sjfv adapter->tx_head_addr); 1955205869Sjfv 1956205869Sjfv /* Re-enable TX unit */ 1957205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); 1958205869Sjfv E1000_WRITE_FLUSH(&adapter->hw); 1959205869Sjfv 1960205869Sjfv adapter->tx_fifo_head = 0; 1961205869Sjfv adapter->tx_fifo_reset_cnt++; 1962205869Sjfv 1963205869Sjfv return (TRUE); 1964205869Sjfv } 1965205869Sjfv else { 1966205869Sjfv return (FALSE); 1967205869Sjfv } 1968205869Sjfv} 1969205869Sjfv 1970205869Sjfvstatic void 1971205869Sjfvlem_set_promisc(struct adapter *adapter) 1972205869Sjfv{ 1973205869Sjfv struct ifnet *ifp = adapter->ifp; 1974205869Sjfv u32 reg_rctl; 1975205869Sjfv 1976205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 1977205869Sjfv 1978205869Sjfv if (ifp->if_flags & IFF_PROMISC) { 1979205869Sjfv reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); 1980205869Sjfv /* Turn this on if you want to see bad packets */ 1981205869Sjfv if (lem_debug_sbp) 1982205869Sjfv reg_rctl |= E1000_RCTL_SBP; 1983205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1984205869Sjfv } else if (ifp->if_flags & IFF_ALLMULTI) { 1985205869Sjfv reg_rctl |= E1000_RCTL_MPE; 1986205869Sjfv reg_rctl &= ~E1000_RCTL_UPE; 1987205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1988205869Sjfv } 1989205869Sjfv} 1990205869Sjfv 1991205869Sjfvstatic void 1992205869Sjfvlem_disable_promisc(struct adapter *adapter) 1993205869Sjfv{ 1994249074Sjfv struct ifnet *ifp = adapter->ifp; 1995249074Sjfv u32 reg_rctl; 1996249074Sjfv int mcnt = 0; 1997205869Sjfv 1998205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 1999205869Sjfv reg_rctl &= (~E1000_RCTL_UPE); 2000249074Sjfv if (ifp->if_flags & IFF_ALLMULTI) 2001249074Sjfv mcnt = MAX_NUM_MULTICAST_ADDRESSES; 2002249074Sjfv else { 2003249074Sjfv struct ifmultiaddr *ifma; 2004249074Sjfv#if __FreeBSD_version < 800000 2005249074Sjfv IF_ADDR_LOCK(ifp); 2006249074Sjfv#else 2007249074Sjfv if_maddr_rlock(ifp); 2008249074Sjfv#endif 2009249074Sjfv TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2010249074Sjfv if (ifma->ifma_addr->sa_family != AF_LINK) 2011249074Sjfv continue; 2012249074Sjfv if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 2013249074Sjfv break; 2014249074Sjfv mcnt++; 2015249074Sjfv } 2016249074Sjfv#if __FreeBSD_version < 800000 2017249074Sjfv IF_ADDR_UNLOCK(ifp); 2018249074Sjfv#else 2019249074Sjfv if_maddr_runlock(ifp); 2020249074Sjfv#endif 2021249074Sjfv } 2022249074Sjfv /* Don't disable if in MAX groups */ 2023249074Sjfv if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) 2024249074Sjfv reg_rctl &= (~E1000_RCTL_MPE); 2025205869Sjfv reg_rctl &= (~E1000_RCTL_SBP); 2026205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 2027205869Sjfv} 2028205869Sjfv 2029205869Sjfv 2030205869Sjfv/********************************************************************* 2031205869Sjfv * Multicast Update 2032205869Sjfv * 2033205869Sjfv * This routine is called whenever multicast address list is updated. 2034205869Sjfv * 2035205869Sjfv **********************************************************************/ 2036205869Sjfv 2037205869Sjfvstatic void 2038205869Sjfvlem_set_multi(struct adapter *adapter) 2039205869Sjfv{ 2040205869Sjfv struct ifnet *ifp = adapter->ifp; 2041205869Sjfv struct ifmultiaddr *ifma; 2042205869Sjfv u32 reg_rctl = 0; 2043205869Sjfv u8 *mta; /* Multicast array memory */ 2044205869Sjfv int mcnt = 0; 2045205869Sjfv 2046205869Sjfv IOCTL_DEBUGOUT("lem_set_multi: begin"); 2047205869Sjfv 2048211913Syongari mta = adapter->mta; 2049211913Syongari bzero(mta, sizeof(u8) * ETH_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES); 2050211913Syongari 2051205869Sjfv if (adapter->hw.mac.type == e1000_82542 && 2052205869Sjfv adapter->hw.revision_id == E1000_REVISION_2) { 2053205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 2054205869Sjfv if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) 2055205869Sjfv e1000_pci_clear_mwi(&adapter->hw); 2056205869Sjfv reg_rctl |= E1000_RCTL_RST; 2057205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 2058205869Sjfv msec_delay(5); 2059205869Sjfv } 2060205869Sjfv 2061205869Sjfv#if __FreeBSD_version < 800000 2062205869Sjfv IF_ADDR_LOCK(ifp); 2063205869Sjfv#else 2064205869Sjfv if_maddr_rlock(ifp); 2065205869Sjfv#endif 2066205869Sjfv TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2067205869Sjfv if (ifma->ifma_addr->sa_family != AF_LINK) 2068205869Sjfv continue; 2069205869Sjfv 2070205869Sjfv if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 2071205869Sjfv break; 2072205869Sjfv 2073205869Sjfv bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 2074205869Sjfv &mta[mcnt * ETH_ADDR_LEN], ETH_ADDR_LEN); 2075205869Sjfv mcnt++; 2076205869Sjfv } 2077205869Sjfv#if __FreeBSD_version < 800000 2078205869Sjfv IF_ADDR_UNLOCK(ifp); 2079205869Sjfv#else 2080205869Sjfv if_maddr_runlock(ifp); 2081205869Sjfv#endif 2082205869Sjfv if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) { 2083205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 2084205869Sjfv reg_rctl |= E1000_RCTL_MPE; 2085205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 2086205869Sjfv } else 2087205869Sjfv e1000_update_mc_addr_list(&adapter->hw, mta, mcnt); 2088205869Sjfv 2089205869Sjfv if (adapter->hw.mac.type == e1000_82542 && 2090205869Sjfv adapter->hw.revision_id == E1000_REVISION_2) { 2091205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 2092205869Sjfv reg_rctl &= ~E1000_RCTL_RST; 2093205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 2094205869Sjfv msec_delay(5); 2095205869Sjfv if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) 2096205869Sjfv e1000_pci_set_mwi(&adapter->hw); 2097205869Sjfv } 2098205869Sjfv} 2099205869Sjfv 2100205869Sjfv 2101205869Sjfv/********************************************************************* 2102205869Sjfv * Timer routine 2103205869Sjfv * 2104205869Sjfv * This routine checks for link status and updates statistics. 2105205869Sjfv * 2106205869Sjfv **********************************************************************/ 2107205869Sjfv 2108205869Sjfvstatic void 2109205869Sjfvlem_local_timer(void *arg) 2110205869Sjfv{ 2111205869Sjfv struct adapter *adapter = arg; 2112205869Sjfv 2113205869Sjfv EM_CORE_LOCK_ASSERT(adapter); 2114205869Sjfv 2115205869Sjfv lem_update_link_status(adapter); 2116205869Sjfv lem_update_stats_counters(adapter); 2117205869Sjfv 2118205869Sjfv lem_smartspeed(adapter); 2119205869Sjfv 2120270252Sluigi#ifdef NIC_PARAVIRT 2121270252Sluigi /* recover space if needed */ 2122270252Sluigi if (adapter->csb && adapter->csb->guest_csb_on && 2123270252Sluigi (adapter->watchdog_check == TRUE) && 2124270252Sluigi (ticks - adapter->watchdog_time > EM_WATCHDOG) && 2125270252Sluigi (adapter->num_tx_desc_avail != adapter->num_tx_desc) ) { 2126270252Sluigi lem_txeof(adapter); 2127270252Sluigi /* 2128270252Sluigi * lem_txeof() normally (except when space in the queue 2129270252Sluigi * runs low XXX) cleans watchdog_check so that 2130270252Sluigi * we do not hung. 2131270252Sluigi */ 2132270252Sluigi } 2133270252Sluigi#endif /* NIC_PARAVIRT */ 2134205869Sjfv /* 2135205869Sjfv * We check the watchdog: the time since 2136205869Sjfv * the last TX descriptor was cleaned. 2137205869Sjfv * This implies a functional TX engine. 2138205869Sjfv */ 2139205869Sjfv if ((adapter->watchdog_check == TRUE) && 2140205869Sjfv (ticks - adapter->watchdog_time > EM_WATCHDOG)) 2141205869Sjfv goto hung; 2142205869Sjfv 2143205869Sjfv callout_reset(&adapter->timer, hz, lem_local_timer, adapter); 2144205869Sjfv return; 2145205869Sjfvhung: 2146205869Sjfv device_printf(adapter->dev, "Watchdog timeout -- resetting\n"); 2147205869Sjfv adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 2148205869Sjfv adapter->watchdog_events++; 2149205869Sjfv lem_init_locked(adapter); 2150205869Sjfv} 2151205869Sjfv 2152205869Sjfvstatic void 2153205869Sjfvlem_update_link_status(struct adapter *adapter) 2154205869Sjfv{ 2155205869Sjfv struct e1000_hw *hw = &adapter->hw; 2156205869Sjfv struct ifnet *ifp = adapter->ifp; 2157205869Sjfv device_t dev = adapter->dev; 2158205869Sjfv u32 link_check = 0; 2159205869Sjfv 2160205869Sjfv /* Get the cached link value or read phy for real */ 2161205869Sjfv switch (hw->phy.media_type) { 2162205869Sjfv case e1000_media_type_copper: 2163205869Sjfv if (hw->mac.get_link_status) { 2164205869Sjfv /* Do the work to read phy */ 2165205869Sjfv e1000_check_for_link(hw); 2166205869Sjfv link_check = !hw->mac.get_link_status; 2167205869Sjfv if (link_check) /* ESB2 fix */ 2168205869Sjfv e1000_cfg_on_link_up(hw); 2169205869Sjfv } else 2170205869Sjfv link_check = TRUE; 2171205869Sjfv break; 2172205869Sjfv case e1000_media_type_fiber: 2173205869Sjfv e1000_check_for_link(hw); 2174205869Sjfv link_check = (E1000_READ_REG(hw, E1000_STATUS) & 2175205869Sjfv E1000_STATUS_LU); 2176205869Sjfv break; 2177205869Sjfv case e1000_media_type_internal_serdes: 2178205869Sjfv e1000_check_for_link(hw); 2179205869Sjfv link_check = adapter->hw.mac.serdes_has_link; 2180205869Sjfv break; 2181205869Sjfv default: 2182205869Sjfv case e1000_media_type_unknown: 2183205869Sjfv break; 2184205869Sjfv } 2185205869Sjfv 2186205869Sjfv /* Now check for a transition */ 2187205869Sjfv if (link_check && (adapter->link_active == 0)) { 2188205869Sjfv e1000_get_speed_and_duplex(hw, &adapter->link_speed, 2189205869Sjfv &adapter->link_duplex); 2190205869Sjfv if (bootverbose) 2191205869Sjfv device_printf(dev, "Link is up %d Mbps %s\n", 2192205869Sjfv adapter->link_speed, 2193205869Sjfv ((adapter->link_duplex == FULL_DUPLEX) ? 2194205869Sjfv "Full Duplex" : "Half Duplex")); 2195205869Sjfv adapter->link_active = 1; 2196205869Sjfv adapter->smartspeed = 0; 2197205869Sjfv ifp->if_baudrate = adapter->link_speed * 1000000; 2198205869Sjfv if_link_state_change(ifp, LINK_STATE_UP); 2199205869Sjfv } else if (!link_check && (adapter->link_active == 1)) { 2200205869Sjfv ifp->if_baudrate = adapter->link_speed = 0; 2201205869Sjfv adapter->link_duplex = 0; 2202205869Sjfv if (bootverbose) 2203205869Sjfv device_printf(dev, "Link is Down\n"); 2204205869Sjfv adapter->link_active = 0; 2205205869Sjfv /* Link down, disable watchdog */ 2206205869Sjfv adapter->watchdog_check = FALSE; 2207205869Sjfv if_link_state_change(ifp, LINK_STATE_DOWN); 2208205869Sjfv } 2209205869Sjfv} 2210205869Sjfv 2211205869Sjfv/********************************************************************* 2212205869Sjfv * 2213205869Sjfv * This routine disables all traffic on the adapter by issuing a 2214205869Sjfv * global reset on the MAC and deallocates TX/RX buffers. 2215205869Sjfv * 2216205869Sjfv * This routine should always be called with BOTH the CORE 2217205869Sjfv * and TX locks. 2218205869Sjfv **********************************************************************/ 2219205869Sjfv 2220205869Sjfvstatic void 2221205869Sjfvlem_stop(void *arg) 2222205869Sjfv{ 2223205869Sjfv struct adapter *adapter = arg; 2224205869Sjfv struct ifnet *ifp = adapter->ifp; 2225205869Sjfv 2226205869Sjfv EM_CORE_LOCK_ASSERT(adapter); 2227205869Sjfv EM_TX_LOCK_ASSERT(adapter); 2228205869Sjfv 2229205869Sjfv INIT_DEBUGOUT("lem_stop: begin"); 2230205869Sjfv 2231205869Sjfv lem_disable_intr(adapter); 2232205869Sjfv callout_stop(&adapter->timer); 2233205869Sjfv callout_stop(&adapter->tx_fifo_timer); 2234205869Sjfv 2235205869Sjfv /* Tell the stack that the interface is no longer active */ 2236205869Sjfv ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2237205869Sjfv 2238205869Sjfv e1000_reset_hw(&adapter->hw); 2239205869Sjfv if (adapter->hw.mac.type >= e1000_82544) 2240205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0); 2241206001Smarius 2242206001Smarius e1000_led_off(&adapter->hw); 2243206001Smarius e1000_cleanup_led(&adapter->hw); 2244205869Sjfv} 2245205869Sjfv 2246205869Sjfv 2247205869Sjfv/********************************************************************* 2248205869Sjfv * 2249205869Sjfv * Determine hardware revision. 2250205869Sjfv * 2251205869Sjfv **********************************************************************/ 2252205869Sjfvstatic void 2253205869Sjfvlem_identify_hardware(struct adapter *adapter) 2254205869Sjfv{ 2255205869Sjfv device_t dev = adapter->dev; 2256205869Sjfv 2257205869Sjfv /* Make sure our PCI config space has the necessary stuff set */ 2258254263Sscottl pci_enable_busmaster(dev); 2259205869Sjfv adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); 2260205869Sjfv 2261205869Sjfv /* Save off the information about this board */ 2262205869Sjfv adapter->hw.vendor_id = pci_get_vendor(dev); 2263205869Sjfv adapter->hw.device_id = pci_get_device(dev); 2264205869Sjfv adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1); 2265205869Sjfv adapter->hw.subsystem_vendor_id = 2266205869Sjfv pci_read_config(dev, PCIR_SUBVEND_0, 2); 2267205869Sjfv adapter->hw.subsystem_device_id = 2268205869Sjfv pci_read_config(dev, PCIR_SUBDEV_0, 2); 2269205869Sjfv 2270205869Sjfv /* Do Shared Code Init and Setup */ 2271205869Sjfv if (e1000_set_mac_type(&adapter->hw)) { 2272205869Sjfv device_printf(dev, "Setup init failure\n"); 2273205869Sjfv return; 2274205869Sjfv } 2275205869Sjfv} 2276205869Sjfv 2277205869Sjfvstatic int 2278205869Sjfvlem_allocate_pci_resources(struct adapter *adapter) 2279205869Sjfv{ 2280205869Sjfv device_t dev = adapter->dev; 2281205869Sjfv int val, rid, error = E1000_SUCCESS; 2282205869Sjfv 2283205869Sjfv rid = PCIR_BAR(0); 2284205869Sjfv adapter->memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 2285205869Sjfv &rid, RF_ACTIVE); 2286205869Sjfv if (adapter->memory == NULL) { 2287205869Sjfv device_printf(dev, "Unable to allocate bus resource: memory\n"); 2288205869Sjfv return (ENXIO); 2289205869Sjfv } 2290205869Sjfv adapter->osdep.mem_bus_space_tag = 2291205869Sjfv rman_get_bustag(adapter->memory); 2292205869Sjfv adapter->osdep.mem_bus_space_handle = 2293205869Sjfv rman_get_bushandle(adapter->memory); 2294205869Sjfv adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; 2295205869Sjfv 2296205869Sjfv /* Only older adapters use IO mapping */ 2297205869Sjfv if (adapter->hw.mac.type > e1000_82543) { 2298205869Sjfv /* Figure our where our IO BAR is ? */ 2299205869Sjfv for (rid = PCIR_BAR(0); rid < PCIR_CIS;) { 2300205869Sjfv val = pci_read_config(dev, rid, 4); 2301205869Sjfv if (EM_BAR_TYPE(val) == EM_BAR_TYPE_IO) { 2302205869Sjfv adapter->io_rid = rid; 2303205869Sjfv break; 2304205869Sjfv } 2305205869Sjfv rid += 4; 2306205869Sjfv /* check for 64bit BAR */ 2307205869Sjfv if (EM_BAR_MEM_TYPE(val) == EM_BAR_MEM_TYPE_64BIT) 2308205869Sjfv rid += 4; 2309205869Sjfv } 2310205869Sjfv if (rid >= PCIR_CIS) { 2311205869Sjfv device_printf(dev, "Unable to locate IO BAR\n"); 2312205869Sjfv return (ENXIO); 2313205869Sjfv } 2314205869Sjfv adapter->ioport = bus_alloc_resource_any(dev, 2315205869Sjfv SYS_RES_IOPORT, &adapter->io_rid, RF_ACTIVE); 2316205869Sjfv if (adapter->ioport == NULL) { 2317205869Sjfv device_printf(dev, "Unable to allocate bus resource: " 2318205869Sjfv "ioport\n"); 2319205869Sjfv return (ENXIO); 2320205869Sjfv } 2321205869Sjfv adapter->hw.io_base = 0; 2322205869Sjfv adapter->osdep.io_bus_space_tag = 2323205869Sjfv rman_get_bustag(adapter->ioport); 2324205869Sjfv adapter->osdep.io_bus_space_handle = 2325205869Sjfv rman_get_bushandle(adapter->ioport); 2326205869Sjfv } 2327205869Sjfv 2328205869Sjfv adapter->hw.back = &adapter->osdep; 2329205869Sjfv 2330205869Sjfv return (error); 2331205869Sjfv} 2332205869Sjfv 2333205869Sjfv/********************************************************************* 2334205869Sjfv * 2335205869Sjfv * Setup the Legacy or MSI Interrupt handler 2336205869Sjfv * 2337205869Sjfv **********************************************************************/ 2338205869Sjfvint 2339205869Sjfvlem_allocate_irq(struct adapter *adapter) 2340205869Sjfv{ 2341205869Sjfv device_t dev = adapter->dev; 2342205869Sjfv int error, rid = 0; 2343205869Sjfv 2344205869Sjfv /* Manually turn off all interrupts */ 2345205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff); 2346205869Sjfv 2347205869Sjfv /* We allocate a single interrupt resource */ 2348205869Sjfv adapter->res[0] = bus_alloc_resource_any(dev, 2349205869Sjfv SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); 2350205869Sjfv if (adapter->res[0] == NULL) { 2351205869Sjfv device_printf(dev, "Unable to allocate bus resource: " 2352205869Sjfv "interrupt\n"); 2353205869Sjfv return (ENXIO); 2354205869Sjfv } 2355205869Sjfv 2356238953Sjfv /* Do Legacy setup? */ 2357238953Sjfv if (lem_use_legacy_irq) { 2358238953Sjfv if ((error = bus_setup_intr(dev, adapter->res[0], 2359238953Sjfv INTR_TYPE_NET | INTR_MPSAFE, NULL, lem_intr, adapter, 2360238953Sjfv &adapter->tag[0])) != 0) { 2361238953Sjfv device_printf(dev, 2362238953Sjfv "Failed to register interrupt handler"); 2363238953Sjfv return (error); 2364238953Sjfv } 2365238953Sjfv return (0); 2366205869Sjfv } 2367205869Sjfv 2368205869Sjfv /* 2369238953Sjfv * Use a Fast interrupt and the associated 2370238953Sjfv * deferred processing contexts. 2371205869Sjfv */ 2372205869Sjfv TASK_INIT(&adapter->rxtx_task, 0, lem_handle_rxtx, adapter); 2373205869Sjfv TASK_INIT(&adapter->link_task, 0, lem_handle_link, adapter); 2374205869Sjfv adapter->tq = taskqueue_create_fast("lem_taskq", M_NOWAIT, 2375205869Sjfv taskqueue_thread_enqueue, &adapter->tq); 2376205869Sjfv taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq", 2377205869Sjfv device_get_nameunit(adapter->dev)); 2378205869Sjfv if ((error = bus_setup_intr(dev, adapter->res[0], 2379205869Sjfv INTR_TYPE_NET, lem_irq_fast, NULL, adapter, 2380205869Sjfv &adapter->tag[0])) != 0) { 2381205869Sjfv device_printf(dev, "Failed to register fast interrupt " 2382205869Sjfv "handler: %d\n", error); 2383205869Sjfv taskqueue_free(adapter->tq); 2384205869Sjfv adapter->tq = NULL; 2385205869Sjfv return (error); 2386205869Sjfv } 2387205869Sjfv 2388205869Sjfv return (0); 2389205869Sjfv} 2390205869Sjfv 2391205869Sjfv 2392205869Sjfvstatic void 2393205869Sjfvlem_free_pci_resources(struct adapter *adapter) 2394205869Sjfv{ 2395205869Sjfv device_t dev = adapter->dev; 2396205869Sjfv 2397205869Sjfv 2398205869Sjfv if (adapter->tag[0] != NULL) { 2399205869Sjfv bus_teardown_intr(dev, adapter->res[0], 2400205869Sjfv adapter->tag[0]); 2401205869Sjfv adapter->tag[0] = NULL; 2402205869Sjfv } 2403205869Sjfv 2404205869Sjfv if (adapter->res[0] != NULL) { 2405205869Sjfv bus_release_resource(dev, SYS_RES_IRQ, 2406205869Sjfv 0, adapter->res[0]); 2407205869Sjfv } 2408205869Sjfv 2409205869Sjfv if (adapter->memory != NULL) 2410205869Sjfv bus_release_resource(dev, SYS_RES_MEMORY, 2411205869Sjfv PCIR_BAR(0), adapter->memory); 2412205869Sjfv 2413205869Sjfv if (adapter->ioport != NULL) 2414205869Sjfv bus_release_resource(dev, SYS_RES_IOPORT, 2415205869Sjfv adapter->io_rid, adapter->ioport); 2416205869Sjfv} 2417205869Sjfv 2418205869Sjfv 2419205869Sjfv/********************************************************************* 2420205869Sjfv * 2421205869Sjfv * Initialize the hardware to a configuration 2422205869Sjfv * as specified by the adapter structure. 2423205869Sjfv * 2424205869Sjfv **********************************************************************/ 2425205869Sjfvstatic int 2426205869Sjfvlem_hardware_init(struct adapter *adapter) 2427205869Sjfv{ 2428205869Sjfv device_t dev = adapter->dev; 2429205869Sjfv u16 rx_buffer_size; 2430205869Sjfv 2431205869Sjfv INIT_DEBUGOUT("lem_hardware_init: begin"); 2432205869Sjfv 2433205869Sjfv /* Issue a global reset */ 2434205869Sjfv e1000_reset_hw(&adapter->hw); 2435205869Sjfv 2436205869Sjfv /* When hardware is reset, fifo_head is also reset */ 2437205869Sjfv adapter->tx_fifo_head = 0; 2438205869Sjfv 2439205869Sjfv /* 2440205869Sjfv * These parameters control the automatic generation (Tx) and 2441205869Sjfv * response (Rx) to Ethernet PAUSE frames. 2442205869Sjfv * - High water mark should allow for at least two frames to be 2443205869Sjfv * received after sending an XOFF. 2444205869Sjfv * - Low water mark works best when it is very near the high water mark. 2445205869Sjfv * This allows the receiver to restart by sending XON when it has 2446205869Sjfv * drained a bit. Here we use an arbitary value of 1500 which will 2447205869Sjfv * restart after one full frame is pulled from the buffer. There 2448205869Sjfv * could be several smaller frames in the buffer and if so they will 2449205869Sjfv * not trigger the XON until their total number reduces the buffer 2450205869Sjfv * by 1500. 2451205869Sjfv * - The pause time is fairly large at 1000 x 512ns = 512 usec. 2452205869Sjfv */ 2453205869Sjfv rx_buffer_size = ((E1000_READ_REG(&adapter->hw, E1000_PBA) & 2454205869Sjfv 0xffff) << 10 ); 2455205869Sjfv 2456205869Sjfv adapter->hw.fc.high_water = rx_buffer_size - 2457205869Sjfv roundup2(adapter->max_frame_size, 1024); 2458205869Sjfv adapter->hw.fc.low_water = adapter->hw.fc.high_water - 1500; 2459205869Sjfv 2460205869Sjfv adapter->hw.fc.pause_time = EM_FC_PAUSE_TIME; 2461205869Sjfv adapter->hw.fc.send_xon = TRUE; 2462205869Sjfv 2463205869Sjfv /* Set Flow control, use the tunable location if sane */ 2464214646Sjfv if ((lem_fc_setting >= 0) && (lem_fc_setting < 4)) 2465205869Sjfv adapter->hw.fc.requested_mode = lem_fc_setting; 2466205869Sjfv else 2467205869Sjfv adapter->hw.fc.requested_mode = e1000_fc_none; 2468205869Sjfv 2469205869Sjfv if (e1000_init_hw(&adapter->hw) < 0) { 2470205869Sjfv device_printf(dev, "Hardware Initialization Failed\n"); 2471205869Sjfv return (EIO); 2472205869Sjfv } 2473205869Sjfv 2474205869Sjfv e1000_check_for_link(&adapter->hw); 2475205869Sjfv 2476205869Sjfv return (0); 2477205869Sjfv} 2478205869Sjfv 2479205869Sjfv/********************************************************************* 2480205869Sjfv * 2481205869Sjfv * Setup networking device structure and register an interface. 2482205869Sjfv * 2483205869Sjfv **********************************************************************/ 2484211907Syongaristatic int 2485205869Sjfvlem_setup_interface(device_t dev, struct adapter *adapter) 2486205869Sjfv{ 2487205869Sjfv struct ifnet *ifp; 2488205869Sjfv 2489205869Sjfv INIT_DEBUGOUT("lem_setup_interface: begin"); 2490205869Sjfv 2491205869Sjfv ifp = adapter->ifp = if_alloc(IFT_ETHER); 2492211907Syongari if (ifp == NULL) { 2493211907Syongari device_printf(dev, "can not allocate ifnet structure\n"); 2494211907Syongari return (-1); 2495211907Syongari } 2496205869Sjfv if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 2497205869Sjfv ifp->if_init = lem_init; 2498205869Sjfv ifp->if_softc = adapter; 2499205869Sjfv ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 2500205869Sjfv ifp->if_ioctl = lem_ioctl; 2501205869Sjfv ifp->if_start = lem_start; 2502205869Sjfv IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1); 2503205869Sjfv ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1; 2504205869Sjfv IFQ_SET_READY(&ifp->if_snd); 2505205869Sjfv 2506205869Sjfv ether_ifattach(ifp, adapter->hw.mac.addr); 2507205869Sjfv 2508205869Sjfv ifp->if_capabilities = ifp->if_capenable = 0; 2509205869Sjfv 2510205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 2511214646Sjfv ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; 2512214646Sjfv ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; 2513205869Sjfv } 2514205869Sjfv 2515205869Sjfv /* 2516205869Sjfv * Tell the upper layer(s) we support long frames. 2517205869Sjfv */ 2518205869Sjfv ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 2519205869Sjfv ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 2520205869Sjfv ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 2521205869Sjfv 2522214646Sjfv /* 2523214646Sjfv ** Dont turn this on by default, if vlans are 2524214646Sjfv ** created on another pseudo device (eg. lagg) 2525214646Sjfv ** then vlan events are not passed thru, breaking 2526214646Sjfv ** operation, but with HW FILTER off it works. If 2527214646Sjfv ** using vlans directly on the em driver you can 2528214646Sjfv ** enable this and get full hardware tag filtering. 2529214646Sjfv */ 2530214646Sjfv ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; 2531214646Sjfv 2532205869Sjfv#ifdef DEVICE_POLLING 2533205869Sjfv ifp->if_capabilities |= IFCAP_POLLING; 2534205869Sjfv#endif 2535205869Sjfv 2536208103Sjfv /* Enable only WOL MAGIC by default */ 2537205869Sjfv if (adapter->wol) { 2538205869Sjfv ifp->if_capabilities |= IFCAP_WOL; 2539208103Sjfv ifp->if_capenable |= IFCAP_WOL_MAGIC; 2540205869Sjfv } 2541205869Sjfv 2542205869Sjfv /* 2543205869Sjfv * Specify the media types supported by this adapter and register 2544205869Sjfv * callbacks to update media and link information 2545205869Sjfv */ 2546205869Sjfv ifmedia_init(&adapter->media, IFM_IMASK, 2547205869Sjfv lem_media_change, lem_media_status); 2548205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 2549205869Sjfv (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) { 2550205869Sjfv u_char fiber_type = IFM_1000_SX; /* default type */ 2551205869Sjfv 2552205869Sjfv if (adapter->hw.mac.type == e1000_82545) 2553205869Sjfv fiber_type = IFM_1000_LX; 2554205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | fiber_type | IFM_FDX, 2555205869Sjfv 0, NULL); 2556205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | fiber_type, 0, NULL); 2557205869Sjfv } else { 2558205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); 2559205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX, 2560205869Sjfv 0, NULL); 2561205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, 2562205869Sjfv 0, NULL); 2563205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 2564205869Sjfv 0, NULL); 2565205869Sjfv if (adapter->hw.phy.type != e1000_phy_ife) { 2566205869Sjfv ifmedia_add(&adapter->media, 2567205869Sjfv IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); 2568205869Sjfv ifmedia_add(&adapter->media, 2569205869Sjfv IFM_ETHER | IFM_1000_T, 0, NULL); 2570205869Sjfv } 2571205869Sjfv } 2572205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); 2573205869Sjfv ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); 2574211907Syongari return (0); 2575205869Sjfv} 2576205869Sjfv 2577205869Sjfv 2578205869Sjfv/********************************************************************* 2579205869Sjfv * 2580205869Sjfv * Workaround for SmartSpeed on 82541 and 82547 controllers 2581205869Sjfv * 2582205869Sjfv **********************************************************************/ 2583205869Sjfvstatic void 2584205869Sjfvlem_smartspeed(struct adapter *adapter) 2585205869Sjfv{ 2586205869Sjfv u16 phy_tmp; 2587205869Sjfv 2588205869Sjfv if (adapter->link_active || (adapter->hw.phy.type != e1000_phy_igp) || 2589205869Sjfv adapter->hw.mac.autoneg == 0 || 2590205869Sjfv (adapter->hw.phy.autoneg_advertised & ADVERTISE_1000_FULL) == 0) 2591205869Sjfv return; 2592205869Sjfv 2593205869Sjfv if (adapter->smartspeed == 0) { 2594205869Sjfv /* If Master/Slave config fault is asserted twice, 2595205869Sjfv * we assume back-to-back */ 2596205869Sjfv e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp); 2597205869Sjfv if (!(phy_tmp & SR_1000T_MS_CONFIG_FAULT)) 2598205869Sjfv return; 2599205869Sjfv e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp); 2600205869Sjfv if (phy_tmp & SR_1000T_MS_CONFIG_FAULT) { 2601205869Sjfv e1000_read_phy_reg(&adapter->hw, 2602205869Sjfv PHY_1000T_CTRL, &phy_tmp); 2603205869Sjfv if(phy_tmp & CR_1000T_MS_ENABLE) { 2604205869Sjfv phy_tmp &= ~CR_1000T_MS_ENABLE; 2605205869Sjfv e1000_write_phy_reg(&adapter->hw, 2606205869Sjfv PHY_1000T_CTRL, phy_tmp); 2607205869Sjfv adapter->smartspeed++; 2608205869Sjfv if(adapter->hw.mac.autoneg && 2609205869Sjfv !e1000_copper_link_autoneg(&adapter->hw) && 2610205869Sjfv !e1000_read_phy_reg(&adapter->hw, 2611205869Sjfv PHY_CONTROL, &phy_tmp)) { 2612205869Sjfv phy_tmp |= (MII_CR_AUTO_NEG_EN | 2613205869Sjfv MII_CR_RESTART_AUTO_NEG); 2614205869Sjfv e1000_write_phy_reg(&adapter->hw, 2615205869Sjfv PHY_CONTROL, phy_tmp); 2616205869Sjfv } 2617205869Sjfv } 2618205869Sjfv } 2619205869Sjfv return; 2620205869Sjfv } else if(adapter->smartspeed == EM_SMARTSPEED_DOWNSHIFT) { 2621205869Sjfv /* If still no link, perhaps using 2/3 pair cable */ 2622205869Sjfv e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_tmp); 2623205869Sjfv phy_tmp |= CR_1000T_MS_ENABLE; 2624205869Sjfv e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_tmp); 2625205869Sjfv if(adapter->hw.mac.autoneg && 2626205869Sjfv !e1000_copper_link_autoneg(&adapter->hw) && 2627205869Sjfv !e1000_read_phy_reg(&adapter->hw, PHY_CONTROL, &phy_tmp)) { 2628205869Sjfv phy_tmp |= (MII_CR_AUTO_NEG_EN | 2629205869Sjfv MII_CR_RESTART_AUTO_NEG); 2630205869Sjfv e1000_write_phy_reg(&adapter->hw, PHY_CONTROL, phy_tmp); 2631205869Sjfv } 2632205869Sjfv } 2633205869Sjfv /* Restart process after EM_SMARTSPEED_MAX iterations */ 2634205869Sjfv if(adapter->smartspeed++ == EM_SMARTSPEED_MAX) 2635205869Sjfv adapter->smartspeed = 0; 2636205869Sjfv} 2637205869Sjfv 2638205869Sjfv 2639205869Sjfv/* 2640205869Sjfv * Manage DMA'able memory. 2641205869Sjfv */ 2642205869Sjfvstatic void 2643205869Sjfvlem_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2644205869Sjfv{ 2645205869Sjfv if (error) 2646205869Sjfv return; 2647205869Sjfv *(bus_addr_t *) arg = segs[0].ds_addr; 2648205869Sjfv} 2649205869Sjfv 2650205869Sjfvstatic int 2651205869Sjfvlem_dma_malloc(struct adapter *adapter, bus_size_t size, 2652205869Sjfv struct em_dma_alloc *dma, int mapflags) 2653205869Sjfv{ 2654205869Sjfv int error; 2655205869Sjfv 2656205869Sjfv error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */ 2657205869Sjfv EM_DBA_ALIGN, 0, /* alignment, bounds */ 2658205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 2659205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 2660205869Sjfv NULL, NULL, /* filter, filterarg */ 2661205869Sjfv size, /* maxsize */ 2662205869Sjfv 1, /* nsegments */ 2663205869Sjfv size, /* maxsegsize */ 2664205869Sjfv 0, /* flags */ 2665205869Sjfv NULL, /* lockfunc */ 2666205869Sjfv NULL, /* lockarg */ 2667205869Sjfv &dma->dma_tag); 2668205869Sjfv if (error) { 2669205869Sjfv device_printf(adapter->dev, 2670205869Sjfv "%s: bus_dma_tag_create failed: %d\n", 2671205869Sjfv __func__, error); 2672205869Sjfv goto fail_0; 2673205869Sjfv } 2674205869Sjfv 2675205869Sjfv error = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr, 2676205869Sjfv BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map); 2677205869Sjfv if (error) { 2678205869Sjfv device_printf(adapter->dev, 2679205869Sjfv "%s: bus_dmamem_alloc(%ju) failed: %d\n", 2680205869Sjfv __func__, (uintmax_t)size, error); 2681205869Sjfv goto fail_2; 2682205869Sjfv } 2683205869Sjfv 2684205869Sjfv dma->dma_paddr = 0; 2685205869Sjfv error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, 2686205869Sjfv size, lem_dmamap_cb, &dma->dma_paddr, mapflags | BUS_DMA_NOWAIT); 2687205869Sjfv if (error || dma->dma_paddr == 0) { 2688205869Sjfv device_printf(adapter->dev, 2689205869Sjfv "%s: bus_dmamap_load failed: %d\n", 2690205869Sjfv __func__, error); 2691205869Sjfv goto fail_3; 2692205869Sjfv } 2693205869Sjfv 2694205869Sjfv return (0); 2695205869Sjfv 2696205869Sjfvfail_3: 2697205869Sjfv bus_dmamap_unload(dma->dma_tag, dma->dma_map); 2698205869Sjfvfail_2: 2699205869Sjfv bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 2700205869Sjfv bus_dma_tag_destroy(dma->dma_tag); 2701205869Sjfvfail_0: 2702205869Sjfv dma->dma_map = NULL; 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; 2713205869Sjfv if (dma->dma_map != NULL) { 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); 2717205869Sjfv bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 2718205869Sjfv dma->dma_map = NULL; 2719205869Sjfv } 2720205869Sjfv bus_dma_tag_destroy(dma->dma_tag); 2721205869Sjfv dma->dma_tag = NULL; 2722205869Sjfv} 2723205869Sjfv 2724205869Sjfv 2725205869Sjfv/********************************************************************* 2726205869Sjfv * 2727205869Sjfv * Allocate memory for tx_buffer structures. The tx_buffer stores all 2728205869Sjfv * the information needed to transmit a packet on the wire. 2729205869Sjfv * 2730205869Sjfv **********************************************************************/ 2731205869Sjfvstatic int 2732205869Sjfvlem_allocate_transmit_structures(struct adapter *adapter) 2733205869Sjfv{ 2734205869Sjfv device_t dev = adapter->dev; 2735205869Sjfv struct em_buffer *tx_buffer; 2736205869Sjfv int error; 2737205869Sjfv 2738205869Sjfv /* 2739205869Sjfv * Create DMA tags for tx descriptors 2740205869Sjfv */ 2741205869Sjfv if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 2742205869Sjfv 1, 0, /* alignment, bounds */ 2743205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 2744205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 2745205869Sjfv NULL, NULL, /* filter, filterarg */ 2746214646Sjfv MCLBYTES * EM_MAX_SCATTER, /* maxsize */ 2747205869Sjfv EM_MAX_SCATTER, /* nsegments */ 2748214646Sjfv MCLBYTES, /* maxsegsize */ 2749205869Sjfv 0, /* flags */ 2750214646Sjfv NULL, /* lockfunc */ 2751214646Sjfv NULL, /* lockarg */ 2752205869Sjfv &adapter->txtag)) != 0) { 2753205869Sjfv device_printf(dev, "Unable to allocate TX DMA tag\n"); 2754205869Sjfv goto fail; 2755205869Sjfv } 2756205869Sjfv 2757205869Sjfv adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) * 2758205869Sjfv adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); 2759205869Sjfv if (adapter->tx_buffer_area == NULL) { 2760205869Sjfv device_printf(dev, "Unable to allocate tx_buffer memory\n"); 2761205869Sjfv error = ENOMEM; 2762205869Sjfv goto fail; 2763205869Sjfv } 2764205869Sjfv 2765205869Sjfv /* Create the descriptor buffer dma maps */ 2766205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++) { 2767205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2768205869Sjfv error = bus_dmamap_create(adapter->txtag, 0, &tx_buffer->map); 2769205869Sjfv if (error != 0) { 2770205869Sjfv device_printf(dev, "Unable to create TX DMA map\n"); 2771205869Sjfv goto fail; 2772205869Sjfv } 2773205869Sjfv tx_buffer->next_eop = -1; 2774205869Sjfv } 2775205869Sjfv 2776205869Sjfv return (0); 2777205869Sjfvfail: 2778205869Sjfv lem_free_transmit_structures(adapter); 2779205869Sjfv return (error); 2780205869Sjfv} 2781205869Sjfv 2782205869Sjfv/********************************************************************* 2783205869Sjfv * 2784205869Sjfv * (Re)Initialize transmit structures. 2785205869Sjfv * 2786205869Sjfv **********************************************************************/ 2787205869Sjfvstatic void 2788205869Sjfvlem_setup_transmit_structures(struct adapter *adapter) 2789205869Sjfv{ 2790205869Sjfv struct em_buffer *tx_buffer; 2791228281Sluigi#ifdef DEV_NETMAP 2792228281Sluigi /* we are already locked */ 2793228281Sluigi struct netmap_adapter *na = NA(adapter->ifp); 2794228281Sluigi struct netmap_slot *slot = netmap_reset(na, NR_TX, 0, 0); 2795228281Sluigi#endif /* DEV_NETMAP */ 2796205869Sjfv 2797205869Sjfv /* Clear the old ring contents */ 2798205869Sjfv bzero(adapter->tx_desc_base, 2799205869Sjfv (sizeof(struct e1000_tx_desc)) * adapter->num_tx_desc); 2800205869Sjfv 2801205869Sjfv /* Free any existing TX buffers */ 2802205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) { 2803205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2804205869Sjfv bus_dmamap_sync(adapter->txtag, tx_buffer->map, 2805205869Sjfv BUS_DMASYNC_POSTWRITE); 2806205869Sjfv bus_dmamap_unload(adapter->txtag, tx_buffer->map); 2807205869Sjfv m_freem(tx_buffer->m_head); 2808205869Sjfv tx_buffer->m_head = NULL; 2809228281Sluigi#ifdef DEV_NETMAP 2810228281Sluigi if (slot) { 2811231796Sluigi /* the i-th NIC entry goes to slot si */ 2812232238Sluigi int si = netmap_idx_n2k(&na->tx_rings[0], i); 2813229939Sluigi uint64_t paddr; 2814228281Sluigi void *addr; 2815228281Sluigi 2816270252Sluigi addr = PNMB(na, slot + si, &paddr); 2817270235Sluigi adapter->tx_desc_base[i].buffer_addr = htole64(paddr); 2818228281Sluigi /* reload the map for netmap mode */ 2819270252Sluigi netmap_load_map(na, adapter->txtag, tx_buffer->map, addr); 2820228281Sluigi } 2821228281Sluigi#endif /* DEV_NETMAP */ 2822205869Sjfv tx_buffer->next_eop = -1; 2823205869Sjfv } 2824205869Sjfv 2825205869Sjfv /* Reset state */ 2826225640Srstone adapter->last_hw_offload = 0; 2827205869Sjfv adapter->next_avail_tx_desc = 0; 2828205869Sjfv adapter->next_tx_to_clean = 0; 2829205869Sjfv adapter->num_tx_desc_avail = adapter->num_tx_desc; 2830205869Sjfv 2831205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 2832205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2833205869Sjfv 2834205869Sjfv return; 2835205869Sjfv} 2836205869Sjfv 2837205869Sjfv/********************************************************************* 2838205869Sjfv * 2839205869Sjfv * Enable transmit unit. 2840205869Sjfv * 2841205869Sjfv **********************************************************************/ 2842205869Sjfvstatic void 2843205869Sjfvlem_initialize_transmit_unit(struct adapter *adapter) 2844205869Sjfv{ 2845205869Sjfv u32 tctl, tipg = 0; 2846205869Sjfv u64 bus_addr; 2847205869Sjfv 2848205869Sjfv INIT_DEBUGOUT("lem_initialize_transmit_unit: begin"); 2849205869Sjfv /* Setup the Base and Length of the Tx Descriptor Ring */ 2850205869Sjfv bus_addr = adapter->txdma.dma_paddr; 2851205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDLEN(0), 2852205869Sjfv adapter->num_tx_desc * sizeof(struct e1000_tx_desc)); 2853205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDBAH(0), 2854205869Sjfv (u32)(bus_addr >> 32)); 2855205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDBAL(0), 2856205869Sjfv (u32)bus_addr); 2857205869Sjfv /* Setup the HW Tx Head and Tail descriptor pointers */ 2858205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0); 2859205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDH(0), 0); 2860205869Sjfv 2861205869Sjfv HW_DEBUGOUT2("Base = %x, Length = %x\n", 2862205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDBAL(0)), 2863205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDLEN(0))); 2864205869Sjfv 2865205869Sjfv /* Set the default values for the Tx Inter Packet Gap timer */ 2866205869Sjfv switch (adapter->hw.mac.type) { 2867205869Sjfv case e1000_82542: 2868205869Sjfv tipg = DEFAULT_82542_TIPG_IPGT; 2869205869Sjfv tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 2870205869Sjfv tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 2871205869Sjfv break; 2872205869Sjfv default: 2873205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 2874205869Sjfv (adapter->hw.phy.media_type == 2875205869Sjfv e1000_media_type_internal_serdes)) 2876205869Sjfv tipg = DEFAULT_82543_TIPG_IPGT_FIBER; 2877205869Sjfv else 2878205869Sjfv tipg = DEFAULT_82543_TIPG_IPGT_COPPER; 2879205869Sjfv tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 2880205869Sjfv tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 2881205869Sjfv } 2882205869Sjfv 2883205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TIPG, tipg); 2884205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TIDV, adapter->tx_int_delay.value); 2885205869Sjfv if(adapter->hw.mac.type >= e1000_82540) 2886205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TADV, 2887205869Sjfv adapter->tx_abs_int_delay.value); 2888205869Sjfv 2889205869Sjfv /* Program the Transmit Control Register */ 2890205869Sjfv tctl = E1000_READ_REG(&adapter->hw, E1000_TCTL); 2891205869Sjfv tctl &= ~E1000_TCTL_CT; 2892205869Sjfv tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN | 2893205869Sjfv (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); 2894205869Sjfv 2895205869Sjfv /* This write will effectively turn on the transmit unit. */ 2896205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); 2897205869Sjfv 2898205869Sjfv /* Setup Transmit Descriptor Base Settings */ 2899205869Sjfv adapter->txd_cmd = E1000_TXD_CMD_IFCS; 2900205869Sjfv 2901205869Sjfv if (adapter->tx_int_delay.value > 0) 2902205869Sjfv adapter->txd_cmd |= E1000_TXD_CMD_IDE; 2903205869Sjfv} 2904205869Sjfv 2905205869Sjfv/********************************************************************* 2906205869Sjfv * 2907205869Sjfv * Free all transmit related data structures. 2908205869Sjfv * 2909205869Sjfv **********************************************************************/ 2910205869Sjfvstatic void 2911205869Sjfvlem_free_transmit_structures(struct adapter *adapter) 2912205869Sjfv{ 2913205869Sjfv struct em_buffer *tx_buffer; 2914205869Sjfv 2915205869Sjfv INIT_DEBUGOUT("free_transmit_structures: begin"); 2916205869Sjfv 2917205869Sjfv if (adapter->tx_buffer_area != NULL) { 2918205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++) { 2919205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2920205869Sjfv if (tx_buffer->m_head != NULL) { 2921205869Sjfv bus_dmamap_sync(adapter->txtag, tx_buffer->map, 2922205869Sjfv BUS_DMASYNC_POSTWRITE); 2923205869Sjfv bus_dmamap_unload(adapter->txtag, 2924205869Sjfv tx_buffer->map); 2925205869Sjfv m_freem(tx_buffer->m_head); 2926205869Sjfv tx_buffer->m_head = NULL; 2927205869Sjfv } else if (tx_buffer->map != NULL) 2928205869Sjfv bus_dmamap_unload(adapter->txtag, 2929205869Sjfv tx_buffer->map); 2930205869Sjfv if (tx_buffer->map != NULL) { 2931205869Sjfv bus_dmamap_destroy(adapter->txtag, 2932205869Sjfv tx_buffer->map); 2933205869Sjfv tx_buffer->map = NULL; 2934205869Sjfv } 2935205869Sjfv } 2936205869Sjfv } 2937205869Sjfv if (adapter->tx_buffer_area != NULL) { 2938205869Sjfv free(adapter->tx_buffer_area, M_DEVBUF); 2939205869Sjfv adapter->tx_buffer_area = NULL; 2940205869Sjfv } 2941205869Sjfv if (adapter->txtag != NULL) { 2942205869Sjfv bus_dma_tag_destroy(adapter->txtag); 2943205869Sjfv adapter->txtag = NULL; 2944205869Sjfv } 2945205869Sjfv#if __FreeBSD_version >= 800000 2946205869Sjfv if (adapter->br != NULL) 2947205869Sjfv buf_ring_free(adapter->br, M_DEVBUF); 2948205869Sjfv#endif 2949205869Sjfv} 2950205869Sjfv 2951205869Sjfv/********************************************************************* 2952205869Sjfv * 2953205869Sjfv * The offload context needs to be set when we transfer the first 2954205869Sjfv * packet of a particular protocol (TCP/UDP). This routine has been 2955205869Sjfv * enhanced to deal with inserted VLAN headers, and IPV6 (not complete) 2956205869Sjfv * 2957205869Sjfv * Added back the old method of keeping the current context type 2958205869Sjfv * and not setting if unnecessary, as this is reported to be a 2959205869Sjfv * big performance win. -jfv 2960205869Sjfv **********************************************************************/ 2961205869Sjfvstatic void 2962205869Sjfvlem_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp, 2963205869Sjfv u32 *txd_upper, u32 *txd_lower) 2964205869Sjfv{ 2965205869Sjfv struct e1000_context_desc *TXD = NULL; 2966205869Sjfv struct em_buffer *tx_buffer; 2967205869Sjfv struct ether_vlan_header *eh; 2968205869Sjfv struct ip *ip = NULL; 2969205869Sjfv struct ip6_hdr *ip6; 2970205869Sjfv int curr_txd, ehdrlen; 2971205869Sjfv u32 cmd, hdr_len, ip_hlen; 2972205869Sjfv u16 etype; 2973205869Sjfv u8 ipproto; 2974205869Sjfv 2975205869Sjfv 2976205869Sjfv cmd = hdr_len = ipproto = 0; 2977209959Sjfv *txd_upper = *txd_lower = 0; 2978205869Sjfv curr_txd = adapter->next_avail_tx_desc; 2979205869Sjfv 2980205869Sjfv /* 2981205869Sjfv * Determine where frame payload starts. 2982205869Sjfv * Jump over vlan headers if already present, 2983205869Sjfv * helpful for QinQ too. 2984205869Sjfv */ 2985205869Sjfv eh = mtod(mp, struct ether_vlan_header *); 2986205869Sjfv if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 2987205869Sjfv etype = ntohs(eh->evl_proto); 2988205869Sjfv ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 2989205869Sjfv } else { 2990205869Sjfv etype = ntohs(eh->evl_encap_proto); 2991205869Sjfv ehdrlen = ETHER_HDR_LEN; 2992205869Sjfv } 2993205869Sjfv 2994205869Sjfv /* 2995205869Sjfv * We only support TCP/UDP for IPv4 and IPv6 for the moment. 2996205869Sjfv * TODO: Support SCTP too when it hits the tree. 2997205869Sjfv */ 2998205869Sjfv switch (etype) { 2999205869Sjfv case ETHERTYPE_IP: 3000205869Sjfv ip = (struct ip *)(mp->m_data + ehdrlen); 3001205869Sjfv ip_hlen = ip->ip_hl << 2; 3002205869Sjfv 3003205869Sjfv /* Setup of IP header checksum. */ 3004205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_IP) { 3005205869Sjfv /* 3006205869Sjfv * Start offset for header checksum calculation. 3007205869Sjfv * End offset for header checksum calculation. 3008205869Sjfv * Offset of place to put the checksum. 3009205869Sjfv */ 3010205869Sjfv TXD = (struct e1000_context_desc *) 3011205869Sjfv &adapter->tx_desc_base[curr_txd]; 3012205869Sjfv TXD->lower_setup.ip_fields.ipcss = ehdrlen; 3013205869Sjfv TXD->lower_setup.ip_fields.ipcse = 3014205869Sjfv htole16(ehdrlen + ip_hlen); 3015205869Sjfv TXD->lower_setup.ip_fields.ipcso = 3016205869Sjfv ehdrlen + offsetof(struct ip, ip_sum); 3017205869Sjfv cmd |= E1000_TXD_CMD_IP; 3018205869Sjfv *txd_upper |= E1000_TXD_POPTS_IXSM << 8; 3019205869Sjfv } 3020205869Sjfv 3021205869Sjfv hdr_len = ehdrlen + ip_hlen; 3022205869Sjfv ipproto = ip->ip_p; 3023205869Sjfv 3024205869Sjfv break; 3025205869Sjfv case ETHERTYPE_IPV6: 3026205869Sjfv ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 3027205869Sjfv ip_hlen = sizeof(struct ip6_hdr); /* XXX: No header stacking. */ 3028205869Sjfv 3029205869Sjfv /* IPv6 doesn't have a header checksum. */ 3030205869Sjfv 3031205869Sjfv hdr_len = ehdrlen + ip_hlen; 3032205869Sjfv ipproto = ip6->ip6_nxt; 3033209959Sjfv break; 3034205869Sjfv 3035205869Sjfv default: 3036205869Sjfv return; 3037205869Sjfv } 3038205869Sjfv 3039205869Sjfv switch (ipproto) { 3040205869Sjfv case IPPROTO_TCP: 3041205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_TCP) { 3042205869Sjfv *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 3043205869Sjfv *txd_upper |= E1000_TXD_POPTS_TXSM << 8; 3044205869Sjfv /* no need for context if already set */ 3045205869Sjfv if (adapter->last_hw_offload == CSUM_TCP) 3046205869Sjfv return; 3047205869Sjfv adapter->last_hw_offload = CSUM_TCP; 3048205869Sjfv /* 3049205869Sjfv * Start offset for payload checksum calculation. 3050205869Sjfv * End offset for payload checksum calculation. 3051205869Sjfv * Offset of place to put the checksum. 3052205869Sjfv */ 3053205869Sjfv TXD = (struct e1000_context_desc *) 3054205869Sjfv &adapter->tx_desc_base[curr_txd]; 3055205869Sjfv TXD->upper_setup.tcp_fields.tucss = hdr_len; 3056205869Sjfv TXD->upper_setup.tcp_fields.tucse = htole16(0); 3057205869Sjfv TXD->upper_setup.tcp_fields.tucso = 3058205869Sjfv hdr_len + offsetof(struct tcphdr, th_sum); 3059205869Sjfv cmd |= E1000_TXD_CMD_TCP; 3060205869Sjfv } 3061205869Sjfv break; 3062205869Sjfv case IPPROTO_UDP: 3063205869Sjfv { 3064205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_UDP) { 3065205869Sjfv *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 3066205869Sjfv *txd_upper |= E1000_TXD_POPTS_TXSM << 8; 3067205869Sjfv /* no need for context if already set */ 3068205869Sjfv if (adapter->last_hw_offload == CSUM_UDP) 3069205869Sjfv return; 3070205869Sjfv adapter->last_hw_offload = CSUM_UDP; 3071205869Sjfv /* 3072205869Sjfv * Start offset for header checksum calculation. 3073205869Sjfv * End offset for header checksum calculation. 3074205869Sjfv * Offset of place to put the checksum. 3075205869Sjfv */ 3076205869Sjfv TXD = (struct e1000_context_desc *) 3077205869Sjfv &adapter->tx_desc_base[curr_txd]; 3078205869Sjfv TXD->upper_setup.tcp_fields.tucss = hdr_len; 3079205869Sjfv TXD->upper_setup.tcp_fields.tucse = htole16(0); 3080205869Sjfv TXD->upper_setup.tcp_fields.tucso = 3081205869Sjfv hdr_len + offsetof(struct udphdr, uh_sum); 3082205869Sjfv } 3083205869Sjfv /* Fall Thru */ 3084205869Sjfv } 3085205869Sjfv default: 3086205869Sjfv break; 3087205869Sjfv } 3088205869Sjfv 3089209959Sjfv if (TXD == NULL) 3090209959Sjfv return; 3091205869Sjfv TXD->tcp_seg_setup.data = htole32(0); 3092205869Sjfv TXD->cmd_and_length = 3093205869Sjfv htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd); 3094205869Sjfv tx_buffer = &adapter->tx_buffer_area[curr_txd]; 3095205869Sjfv tx_buffer->m_head = NULL; 3096205869Sjfv tx_buffer->next_eop = -1; 3097205869Sjfv 3098205869Sjfv if (++curr_txd == adapter->num_tx_desc) 3099205869Sjfv curr_txd = 0; 3100205869Sjfv 3101205869Sjfv adapter->num_tx_desc_avail--; 3102205869Sjfv adapter->next_avail_tx_desc = curr_txd; 3103205869Sjfv} 3104205869Sjfv 3105205869Sjfv 3106205869Sjfv/********************************************************************** 3107205869Sjfv * 3108205869Sjfv * Examine each tx_buffer in the used queue. If the hardware is done 3109205869Sjfv * processing the packet then free associated resources. The 3110205869Sjfv * tx_buffer is put back on the free queue. 3111205869Sjfv * 3112205869Sjfv **********************************************************************/ 3113205869Sjfvstatic void 3114205869Sjfvlem_txeof(struct adapter *adapter) 3115205869Sjfv{ 3116205869Sjfv int first, last, done, num_avail; 3117205869Sjfv struct em_buffer *tx_buffer; 3118205869Sjfv struct e1000_tx_desc *tx_desc, *eop_desc; 3119205869Sjfv struct ifnet *ifp = adapter->ifp; 3120205869Sjfv 3121205869Sjfv EM_TX_LOCK_ASSERT(adapter); 3122205869Sjfv 3123228281Sluigi#ifdef DEV_NETMAP 3124262151Sluigi if (netmap_tx_irq(ifp, 0)) 3125228281Sluigi return; 3126228281Sluigi#endif /* DEV_NETMAP */ 3127205869Sjfv if (adapter->num_tx_desc_avail == adapter->num_tx_desc) 3128205869Sjfv return; 3129205869Sjfv 3130205869Sjfv num_avail = adapter->num_tx_desc_avail; 3131205869Sjfv first = adapter->next_tx_to_clean; 3132205869Sjfv tx_desc = &adapter->tx_desc_base[first]; 3133205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 3134205869Sjfv last = tx_buffer->next_eop; 3135205869Sjfv eop_desc = &adapter->tx_desc_base[last]; 3136205869Sjfv 3137205869Sjfv /* 3138205869Sjfv * What this does is get the index of the 3139205869Sjfv * first descriptor AFTER the EOP of the 3140205869Sjfv * first packet, that way we can do the 3141205869Sjfv * simple comparison on the inner while loop. 3142205869Sjfv */ 3143205869Sjfv if (++last == adapter->num_tx_desc) 3144205869Sjfv last = 0; 3145205869Sjfv done = last; 3146205869Sjfv 3147205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 3148205869Sjfv BUS_DMASYNC_POSTREAD); 3149205869Sjfv 3150205869Sjfv while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) { 3151205869Sjfv /* We clean the range of the packet */ 3152205869Sjfv while (first != done) { 3153205869Sjfv tx_desc->upper.data = 0; 3154205869Sjfv tx_desc->lower.data = 0; 3155205869Sjfv tx_desc->buffer_addr = 0; 3156205869Sjfv ++num_avail; 3157205869Sjfv 3158205869Sjfv if (tx_buffer->m_head) { 3159205869Sjfv ifp->if_opackets++; 3160205869Sjfv bus_dmamap_sync(adapter->txtag, 3161205869Sjfv tx_buffer->map, 3162205869Sjfv BUS_DMASYNC_POSTWRITE); 3163205869Sjfv bus_dmamap_unload(adapter->txtag, 3164205869Sjfv tx_buffer->map); 3165205869Sjfv 3166205869Sjfv m_freem(tx_buffer->m_head); 3167205869Sjfv tx_buffer->m_head = NULL; 3168205869Sjfv } 3169205869Sjfv tx_buffer->next_eop = -1; 3170205869Sjfv adapter->watchdog_time = ticks; 3171205869Sjfv 3172205869Sjfv if (++first == adapter->num_tx_desc) 3173205869Sjfv first = 0; 3174205869Sjfv 3175205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 3176205869Sjfv tx_desc = &adapter->tx_desc_base[first]; 3177205869Sjfv } 3178205869Sjfv /* See if we can continue to the next packet */ 3179205869Sjfv last = tx_buffer->next_eop; 3180205869Sjfv if (last != -1) { 3181205869Sjfv eop_desc = &adapter->tx_desc_base[last]; 3182205869Sjfv /* Get new done point */ 3183205869Sjfv if (++last == adapter->num_tx_desc) last = 0; 3184205869Sjfv done = last; 3185205869Sjfv } else 3186205869Sjfv break; 3187205869Sjfv } 3188205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 3189205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3190205869Sjfv 3191205869Sjfv adapter->next_tx_to_clean = first; 3192214646Sjfv adapter->num_tx_desc_avail = num_avail; 3193205869Sjfv 3194270252Sluigi#ifdef NIC_SEND_COMBINING 3195270252Sluigi if ((adapter->shadow_tdt & MIT_PENDING_TDT) == MIT_PENDING_TDT) { 3196270252Sluigi /* a tdt write is pending, do it */ 3197270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 3198270252Sluigi 0xffff & adapter->shadow_tdt); 3199270252Sluigi adapter->shadow_tdt = MIT_PENDING_INT; 3200270252Sluigi } else { 3201270252Sluigi adapter->shadow_tdt = 0; // disable 3202270252Sluigi } 3203270252Sluigi#endif /* NIC_SEND_COMBINING */ 3204205869Sjfv /* 3205205869Sjfv * If we have enough room, clear IFF_DRV_OACTIVE to 3206205869Sjfv * tell the stack that it is OK to send packets. 3207205869Sjfv * If there are no pending descriptors, clear the watchdog. 3208205869Sjfv */ 3209214646Sjfv if (adapter->num_tx_desc_avail > EM_TX_CLEANUP_THRESHOLD) { 3210205869Sjfv ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 3211270252Sluigi#ifdef NIC_PARAVIRT 3212270252Sluigi if (adapter->csb) { // XXX also csb_on ? 3213270252Sluigi adapter->csb->guest_need_txkick = 2; /* acked */ 3214270252Sluigi // XXX memory barrier 3215270252Sluigi } 3216270252Sluigi#endif /* NIC_PARAVIRT */ 3217214646Sjfv if (adapter->num_tx_desc_avail == adapter->num_tx_desc) { 3218205869Sjfv adapter->watchdog_check = FALSE; 3219205869Sjfv return; 3220205869Sjfv } 3221205869Sjfv } 3222205869Sjfv} 3223205869Sjfv 3224205869Sjfv/********************************************************************* 3225205869Sjfv * 3226205869Sjfv * When Link is lost sometimes there is work still in the TX ring 3227205869Sjfv * which may result in a watchdog, rather than allow that we do an 3228205869Sjfv * attempted cleanup and then reinit here. Note that this has been 3229205869Sjfv * seens mostly with fiber adapters. 3230205869Sjfv * 3231205869Sjfv **********************************************************************/ 3232205869Sjfvstatic void 3233205869Sjfvlem_tx_purge(struct adapter *adapter) 3234205869Sjfv{ 3235205869Sjfv if ((!adapter->link_active) && (adapter->watchdog_check)) { 3236205869Sjfv EM_TX_LOCK(adapter); 3237205869Sjfv lem_txeof(adapter); 3238205869Sjfv EM_TX_UNLOCK(adapter); 3239205869Sjfv if (adapter->watchdog_check) /* Still outstanding? */ 3240205869Sjfv lem_init_locked(adapter); 3241205869Sjfv } 3242205869Sjfv} 3243205869Sjfv 3244205869Sjfv/********************************************************************* 3245205869Sjfv * 3246205869Sjfv * Get a buffer from system mbuf buffer pool. 3247205869Sjfv * 3248205869Sjfv **********************************************************************/ 3249205869Sjfvstatic int 3250205869Sjfvlem_get_buf(struct adapter *adapter, int i) 3251205869Sjfv{ 3252205869Sjfv struct mbuf *m; 3253205869Sjfv bus_dma_segment_t segs[1]; 3254205869Sjfv bus_dmamap_t map; 3255205869Sjfv struct em_buffer *rx_buffer; 3256205869Sjfv int error, nsegs; 3257205869Sjfv 3258243857Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 3259205869Sjfv if (m == NULL) { 3260205869Sjfv adapter->mbuf_cluster_failed++; 3261205869Sjfv return (ENOBUFS); 3262205869Sjfv } 3263205869Sjfv m->m_len = m->m_pkthdr.len = MCLBYTES; 3264205869Sjfv 3265205869Sjfv if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN)) 3266205869Sjfv m_adj(m, ETHER_ALIGN); 3267205869Sjfv 3268205869Sjfv /* 3269205869Sjfv * Using memory from the mbuf cluster pool, invoke the 3270205869Sjfv * bus_dma machinery to arrange the memory mapping. 3271205869Sjfv */ 3272205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->rxtag, 3273205869Sjfv adapter->rx_sparemap, m, segs, &nsegs, BUS_DMA_NOWAIT); 3274205869Sjfv if (error != 0) { 3275205869Sjfv m_free(m); 3276205869Sjfv return (error); 3277205869Sjfv } 3278205869Sjfv 3279205869Sjfv /* If nsegs is wrong then the stack is corrupt. */ 3280205869Sjfv KASSERT(nsegs == 1, ("Too many segments returned!")); 3281205869Sjfv 3282205869Sjfv rx_buffer = &adapter->rx_buffer_area[i]; 3283205869Sjfv if (rx_buffer->m_head != NULL) 3284205869Sjfv bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 3285205869Sjfv 3286205869Sjfv map = rx_buffer->map; 3287205869Sjfv rx_buffer->map = adapter->rx_sparemap; 3288205869Sjfv adapter->rx_sparemap = map; 3289205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD); 3290205869Sjfv rx_buffer->m_head = m; 3291205869Sjfv 3292205869Sjfv adapter->rx_desc_base[i].buffer_addr = htole64(segs[0].ds_addr); 3293205869Sjfv return (0); 3294205869Sjfv} 3295205869Sjfv 3296205869Sjfv/********************************************************************* 3297205869Sjfv * 3298205869Sjfv * Allocate memory for rx_buffer structures. Since we use one 3299205869Sjfv * rx_buffer per received packet, the maximum number of rx_buffer's 3300205869Sjfv * that we'll need is equal to the number of receive descriptors 3301205869Sjfv * that we've allocated. 3302205869Sjfv * 3303205869Sjfv **********************************************************************/ 3304205869Sjfvstatic int 3305205869Sjfvlem_allocate_receive_structures(struct adapter *adapter) 3306205869Sjfv{ 3307205869Sjfv device_t dev = adapter->dev; 3308205869Sjfv struct em_buffer *rx_buffer; 3309205869Sjfv int i, error; 3310205869Sjfv 3311205869Sjfv adapter->rx_buffer_area = malloc(sizeof(struct em_buffer) * 3312205869Sjfv adapter->num_rx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); 3313205869Sjfv if (adapter->rx_buffer_area == NULL) { 3314205869Sjfv device_printf(dev, "Unable to allocate rx_buffer memory\n"); 3315205869Sjfv return (ENOMEM); 3316205869Sjfv } 3317205869Sjfv 3318205869Sjfv error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 3319205869Sjfv 1, 0, /* alignment, bounds */ 3320205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 3321205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 3322205869Sjfv NULL, NULL, /* filter, filterarg */ 3323205869Sjfv MCLBYTES, /* maxsize */ 3324205869Sjfv 1, /* nsegments */ 3325205869Sjfv MCLBYTES, /* maxsegsize */ 3326205869Sjfv 0, /* flags */ 3327205869Sjfv NULL, /* lockfunc */ 3328205869Sjfv NULL, /* lockarg */ 3329205869Sjfv &adapter->rxtag); 3330205869Sjfv if (error) { 3331205869Sjfv device_printf(dev, "%s: bus_dma_tag_create failed %d\n", 3332205869Sjfv __func__, error); 3333205869Sjfv goto fail; 3334205869Sjfv } 3335205869Sjfv 3336205869Sjfv /* Create the spare map (used by getbuf) */ 3337259508Skib error = bus_dmamap_create(adapter->rxtag, 0, &adapter->rx_sparemap); 3338205869Sjfv if (error) { 3339205869Sjfv device_printf(dev, "%s: bus_dmamap_create failed: %d\n", 3340205869Sjfv __func__, error); 3341205869Sjfv goto fail; 3342205869Sjfv } 3343205869Sjfv 3344205869Sjfv rx_buffer = adapter->rx_buffer_area; 3345205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3346259508Skib error = bus_dmamap_create(adapter->rxtag, 0, &rx_buffer->map); 3347205869Sjfv if (error) { 3348205869Sjfv device_printf(dev, "%s: bus_dmamap_create failed: %d\n", 3349205869Sjfv __func__, error); 3350205869Sjfv goto fail; 3351205869Sjfv } 3352205869Sjfv } 3353205869Sjfv 3354205869Sjfv return (0); 3355205869Sjfv 3356205869Sjfvfail: 3357205869Sjfv lem_free_receive_structures(adapter); 3358205869Sjfv return (error); 3359205869Sjfv} 3360205869Sjfv 3361205869Sjfv/********************************************************************* 3362205869Sjfv * 3363205869Sjfv * (Re)initialize receive structures. 3364205869Sjfv * 3365205869Sjfv **********************************************************************/ 3366205869Sjfvstatic int 3367205869Sjfvlem_setup_receive_structures(struct adapter *adapter) 3368205869Sjfv{ 3369205869Sjfv struct em_buffer *rx_buffer; 3370205869Sjfv int i, error; 3371228281Sluigi#ifdef DEV_NETMAP 3372228281Sluigi /* we are already under lock */ 3373228281Sluigi struct netmap_adapter *na = NA(adapter->ifp); 3374228281Sluigi struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0); 3375228281Sluigi#endif 3376205869Sjfv 3377205869Sjfv /* Reset descriptor ring */ 3378205869Sjfv bzero(adapter->rx_desc_base, 3379205869Sjfv (sizeof(struct e1000_rx_desc)) * adapter->num_rx_desc); 3380205869Sjfv 3381205869Sjfv /* Free current RX buffers. */ 3382205869Sjfv rx_buffer = adapter->rx_buffer_area; 3383205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3384205869Sjfv if (rx_buffer->m_head != NULL) { 3385205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, 3386205869Sjfv BUS_DMASYNC_POSTREAD); 3387205869Sjfv bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 3388205869Sjfv m_freem(rx_buffer->m_head); 3389205869Sjfv rx_buffer->m_head = NULL; 3390205869Sjfv } 3391205869Sjfv } 3392205869Sjfv 3393205869Sjfv /* Allocate new ones. */ 3394205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++) { 3395228281Sluigi#ifdef DEV_NETMAP 3396228281Sluigi if (slot) { 3397231796Sluigi /* the i-th NIC entry goes to slot si */ 3398232238Sluigi int si = netmap_idx_n2k(&na->rx_rings[0], i); 3399229939Sluigi uint64_t paddr; 3400228281Sluigi void *addr; 3401228281Sluigi 3402270252Sluigi addr = PNMB(na, slot + si, &paddr); 3403270252Sluigi netmap_load_map(na, adapter->rxtag, rx_buffer->map, addr); 3404228281Sluigi /* Update descriptor */ 3405229939Sluigi adapter->rx_desc_base[i].buffer_addr = htole64(paddr); 3406228281Sluigi continue; 3407228281Sluigi } 3408228281Sluigi#endif /* DEV_NETMAP */ 3409205869Sjfv error = lem_get_buf(adapter, i); 3410205869Sjfv if (error) 3411205869Sjfv return (error); 3412205869Sjfv } 3413205869Sjfv 3414205869Sjfv /* Setup our descriptor pointers */ 3415205869Sjfv adapter->next_rx_desc_to_check = 0; 3416205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3417205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3418205869Sjfv 3419205869Sjfv return (0); 3420205869Sjfv} 3421205869Sjfv 3422205869Sjfv/********************************************************************* 3423205869Sjfv * 3424205869Sjfv * Enable receive unit. 3425205869Sjfv * 3426205869Sjfv **********************************************************************/ 3427205869Sjfv 3428205869Sjfvstatic void 3429205869Sjfvlem_initialize_receive_unit(struct adapter *adapter) 3430205869Sjfv{ 3431205869Sjfv struct ifnet *ifp = adapter->ifp; 3432205869Sjfv u64 bus_addr; 3433205869Sjfv u32 rctl, rxcsum; 3434205869Sjfv 3435205869Sjfv INIT_DEBUGOUT("lem_initialize_receive_unit: begin"); 3436205869Sjfv 3437205869Sjfv /* 3438205869Sjfv * Make sure receives are disabled while setting 3439205869Sjfv * up the descriptor ring 3440205869Sjfv */ 3441205869Sjfv rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 3442205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); 3443205869Sjfv 3444205869Sjfv if (adapter->hw.mac.type >= e1000_82540) { 3445205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RADV, 3446205869Sjfv adapter->rx_abs_int_delay.value); 3447205869Sjfv /* 3448205869Sjfv * Set the interrupt throttling rate. Value is calculated 3449205869Sjfv * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) 3450205869Sjfv */ 3451205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_ITR, DEFAULT_ITR); 3452205869Sjfv } 3453205869Sjfv 3454205869Sjfv /* Setup the Base and Length of the Rx Descriptor Ring */ 3455205869Sjfv bus_addr = adapter->rxdma.dma_paddr; 3456205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0), 3457205869Sjfv adapter->num_rx_desc * sizeof(struct e1000_rx_desc)); 3458205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDBAH(0), 3459205869Sjfv (u32)(bus_addr >> 32)); 3460205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDBAL(0), 3461205869Sjfv (u32)bus_addr); 3462205869Sjfv 3463205869Sjfv /* Setup the Receive Control Register */ 3464205869Sjfv rctl &= ~(3 << E1000_RCTL_MO_SHIFT); 3465205869Sjfv rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | 3466205869Sjfv E1000_RCTL_RDMTS_HALF | 3467205869Sjfv (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); 3468205869Sjfv 3469205869Sjfv /* Make sure VLAN Filters are off */ 3470205869Sjfv rctl &= ~E1000_RCTL_VFE; 3471205869Sjfv 3472205869Sjfv if (e1000_tbi_sbp_enabled_82543(&adapter->hw)) 3473205869Sjfv rctl |= E1000_RCTL_SBP; 3474205869Sjfv else 3475205869Sjfv rctl &= ~E1000_RCTL_SBP; 3476205869Sjfv 3477205869Sjfv switch (adapter->rx_buffer_len) { 3478205869Sjfv default: 3479205869Sjfv case 2048: 3480205869Sjfv rctl |= E1000_RCTL_SZ_2048; 3481205869Sjfv break; 3482205869Sjfv case 4096: 3483205869Sjfv rctl |= E1000_RCTL_SZ_4096 | 3484205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3485205869Sjfv break; 3486205869Sjfv case 8192: 3487205869Sjfv rctl |= E1000_RCTL_SZ_8192 | 3488205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3489205869Sjfv break; 3490205869Sjfv case 16384: 3491205869Sjfv rctl |= E1000_RCTL_SZ_16384 | 3492205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3493205869Sjfv break; 3494205869Sjfv } 3495205869Sjfv 3496205869Sjfv if (ifp->if_mtu > ETHERMTU) 3497205869Sjfv rctl |= E1000_RCTL_LPE; 3498205869Sjfv else 3499205869Sjfv rctl &= ~E1000_RCTL_LPE; 3500205869Sjfv 3501205869Sjfv /* Enable 82543 Receive Checksum Offload for TCP and UDP */ 3502205869Sjfv if ((adapter->hw.mac.type >= e1000_82543) && 3503205869Sjfv (ifp->if_capenable & IFCAP_RXCSUM)) { 3504205869Sjfv rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM); 3505205869Sjfv rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); 3506205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum); 3507205869Sjfv } 3508205869Sjfv 3509205869Sjfv /* Enable Receives */ 3510205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); 3511205869Sjfv 3512205869Sjfv /* 3513205869Sjfv * Setup the HW Rx Head and 3514205869Sjfv * Tail Descriptor Pointers 3515205869Sjfv */ 3516205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0); 3517250413Sluigi rctl = adapter->num_rx_desc - 1; /* default RDT value */ 3518228281Sluigi#ifdef DEV_NETMAP 3519228281Sluigi /* preserve buffers already made available to clients */ 3520250413Sluigi if (ifp->if_capenable & IFCAP_NETMAP) 3521262151Sluigi rctl -= nm_kr_rxspace(&NA(adapter->ifp)->rx_rings[0]); 3522228281Sluigi#endif /* DEV_NETMAP */ 3523250413Sluigi E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), rctl); 3524205869Sjfv 3525205869Sjfv return; 3526205869Sjfv} 3527205869Sjfv 3528205869Sjfv/********************************************************************* 3529205869Sjfv * 3530205869Sjfv * Free receive related data structures. 3531205869Sjfv * 3532205869Sjfv **********************************************************************/ 3533205869Sjfvstatic void 3534205869Sjfvlem_free_receive_structures(struct adapter *adapter) 3535205869Sjfv{ 3536205869Sjfv struct em_buffer *rx_buffer; 3537205869Sjfv int i; 3538205869Sjfv 3539205869Sjfv INIT_DEBUGOUT("free_receive_structures: begin"); 3540205869Sjfv 3541205869Sjfv if (adapter->rx_sparemap) { 3542205869Sjfv bus_dmamap_destroy(adapter->rxtag, adapter->rx_sparemap); 3543205869Sjfv adapter->rx_sparemap = NULL; 3544205869Sjfv } 3545205869Sjfv 3546205869Sjfv /* Cleanup any existing buffers */ 3547205869Sjfv if (adapter->rx_buffer_area != NULL) { 3548205869Sjfv rx_buffer = adapter->rx_buffer_area; 3549205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3550205869Sjfv if (rx_buffer->m_head != NULL) { 3551205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, 3552205869Sjfv BUS_DMASYNC_POSTREAD); 3553205869Sjfv bus_dmamap_unload(adapter->rxtag, 3554205869Sjfv rx_buffer->map); 3555205869Sjfv m_freem(rx_buffer->m_head); 3556205869Sjfv rx_buffer->m_head = NULL; 3557205869Sjfv } else if (rx_buffer->map != NULL) 3558205869Sjfv bus_dmamap_unload(adapter->rxtag, 3559205869Sjfv rx_buffer->map); 3560205869Sjfv if (rx_buffer->map != NULL) { 3561205869Sjfv bus_dmamap_destroy(adapter->rxtag, 3562205869Sjfv rx_buffer->map); 3563205869Sjfv rx_buffer->map = NULL; 3564205869Sjfv } 3565205869Sjfv } 3566205869Sjfv } 3567205869Sjfv 3568205869Sjfv if (adapter->rx_buffer_area != NULL) { 3569205869Sjfv free(adapter->rx_buffer_area, M_DEVBUF); 3570205869Sjfv adapter->rx_buffer_area = NULL; 3571205869Sjfv } 3572205869Sjfv 3573205869Sjfv if (adapter->rxtag != NULL) { 3574205869Sjfv bus_dma_tag_destroy(adapter->rxtag); 3575205869Sjfv adapter->rxtag = NULL; 3576205869Sjfv } 3577205869Sjfv} 3578205869Sjfv 3579205869Sjfv/********************************************************************* 3580205869Sjfv * 3581205869Sjfv * This routine executes in interrupt context. It replenishes 3582205869Sjfv * the mbufs in the descriptor and sends data which has been 3583205869Sjfv * dma'ed into host memory to upper layer. 3584205869Sjfv * 3585205869Sjfv * We loop at most count times if count is > 0, or until done if 3586205869Sjfv * count < 0. 3587205869Sjfv * 3588205869Sjfv * For polling we also now return the number of cleaned packets 3589205869Sjfv *********************************************************************/ 3590209238Sjfvstatic bool 3591209238Sjfvlem_rxeof(struct adapter *adapter, int count, int *done) 3592205869Sjfv{ 3593241844Seadler struct ifnet *ifp = adapter->ifp; 3594205869Sjfv struct mbuf *mp; 3595214646Sjfv u8 status = 0, accept_frame = 0, eop = 0; 3596205869Sjfv u16 len, desc_len, prev_len_adj; 3597205869Sjfv int i, rx_sent = 0; 3598205869Sjfv struct e1000_rx_desc *current_desc; 3599205869Sjfv 3600270252Sluigi#ifdef BATCH_DISPATCH 3601270252Sluigi struct mbuf *mh = NULL, *mt = NULL; 3602270252Sluigi#endif /* BATCH_DISPATCH */ 3603270252Sluigi#ifdef NIC_PARAVIRT 3604270252Sluigi int retries = 0; 3605270252Sluigi struct paravirt_csb* csb = adapter->csb; 3606270252Sluigi int csb_mode = csb && csb->guest_csb_on; 3607270252Sluigi 3608270252Sluigi //ND("clear guest_rxkick at %d", adapter->next_rx_desc_to_check); 3609270252Sluigi if (csb_mode && csb->guest_need_rxkick) 3610270252Sluigi csb->guest_need_rxkick = 0; 3611270252Sluigi#endif /* NIC_PARAVIRT */ 3612205869Sjfv EM_RX_LOCK(adapter); 3613270252Sluigi 3614270252Sluigi#ifdef BATCH_DISPATCH 3615270252Sluigi batch_again: 3616270252Sluigi#endif /* BATCH_DISPATCH */ 3617205869Sjfv i = adapter->next_rx_desc_to_check; 3618205869Sjfv current_desc = &adapter->rx_desc_base[i]; 3619205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3620205869Sjfv BUS_DMASYNC_POSTREAD); 3621205869Sjfv 3622228281Sluigi#ifdef DEV_NETMAP 3623262151Sluigi if (netmap_rx_irq(ifp, 0, &rx_sent)) { 3624262151Sluigi EM_RX_UNLOCK(adapter); 3625250109Sluigi return (FALSE); 3626262151Sluigi } 3627228281Sluigi#endif /* DEV_NETMAP */ 3628228281Sluigi 3629270252Sluigi#if 1 // XXX optimization ? 3630205869Sjfv if (!((current_desc->status) & E1000_RXD_STAT_DD)) { 3631209238Sjfv if (done != NULL) 3632209238Sjfv *done = rx_sent; 3633205869Sjfv EM_RX_UNLOCK(adapter); 3634209238Sjfv return (FALSE); 3635205869Sjfv } 3636270252Sluigi#endif /* 0 */ 3637205869Sjfv 3638214646Sjfv while (count != 0 && ifp->if_drv_flags & IFF_DRV_RUNNING) { 3639205869Sjfv struct mbuf *m = NULL; 3640205869Sjfv 3641214646Sjfv status = current_desc->status; 3642270252Sluigi if ((status & E1000_RXD_STAT_DD) == 0) { 3643270252Sluigi#ifdef NIC_PARAVIRT 3644270252Sluigi if (csb_mode) { 3645270252Sluigi /* buffer not ready yet. Retry a few times before giving up */ 3646270252Sluigi if (++retries <= adapter->rx_retries) { 3647270252Sluigi continue; 3648270252Sluigi } 3649270252Sluigi if (csb->guest_need_rxkick == 0) { 3650270252Sluigi // ND("set guest_rxkick at %d", adapter->next_rx_desc_to_check); 3651270252Sluigi csb->guest_need_rxkick = 1; 3652270252Sluigi // XXX memory barrier, status volatile ? 3653270252Sluigi continue; /* double check */ 3654270252Sluigi } 3655270252Sluigi } 3656270252Sluigi /* no buffer ready, give up */ 3657270252Sluigi#endif /* NIC_PARAVIRT */ 3658214646Sjfv break; 3659270252Sluigi } 3660270252Sluigi#ifdef NIC_PARAVIRT 3661270252Sluigi if (csb_mode) { 3662270252Sluigi if (csb->guest_need_rxkick) 3663270252Sluigi // ND("clear again guest_rxkick at %d", adapter->next_rx_desc_to_check); 3664270252Sluigi csb->guest_need_rxkick = 0; 3665270252Sluigi retries = 0; 3666270252Sluigi } 3667270252Sluigi#endif /* NIC_PARAVIRT */ 3668214646Sjfv 3669205869Sjfv mp = adapter->rx_buffer_area[i].m_head; 3670205869Sjfv /* 3671205869Sjfv * Can't defer bus_dmamap_sync(9) because TBI_ACCEPT 3672205869Sjfv * needs to access the last received byte in the mbuf. 3673205869Sjfv */ 3674205869Sjfv bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map, 3675205869Sjfv BUS_DMASYNC_POSTREAD); 3676205869Sjfv 3677205869Sjfv accept_frame = 1; 3678205869Sjfv prev_len_adj = 0; 3679205869Sjfv desc_len = le16toh(current_desc->length); 3680205869Sjfv if (status & E1000_RXD_STAT_EOP) { 3681205869Sjfv count--; 3682205869Sjfv eop = 1; 3683205869Sjfv if (desc_len < ETHER_CRC_LEN) { 3684205869Sjfv len = 0; 3685205869Sjfv prev_len_adj = ETHER_CRC_LEN - desc_len; 3686205869Sjfv } else 3687205869Sjfv len = desc_len - ETHER_CRC_LEN; 3688205869Sjfv } else { 3689205869Sjfv eop = 0; 3690205869Sjfv len = desc_len; 3691205869Sjfv } 3692205869Sjfv 3693205869Sjfv if (current_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) { 3694205869Sjfv u8 last_byte; 3695205869Sjfv u32 pkt_len = desc_len; 3696205869Sjfv 3697205869Sjfv if (adapter->fmp != NULL) 3698205869Sjfv pkt_len += adapter->fmp->m_pkthdr.len; 3699205869Sjfv 3700205869Sjfv last_byte = *(mtod(mp, caddr_t) + desc_len - 1); 3701205869Sjfv if (TBI_ACCEPT(&adapter->hw, status, 3702205869Sjfv current_desc->errors, pkt_len, last_byte, 3703205869Sjfv adapter->min_frame_size, adapter->max_frame_size)) { 3704205869Sjfv e1000_tbi_adjust_stats_82543(&adapter->hw, 3705205869Sjfv &adapter->stats, pkt_len, 3706205869Sjfv adapter->hw.mac.addr, 3707205869Sjfv adapter->max_frame_size); 3708205869Sjfv if (len > 0) 3709205869Sjfv len--; 3710205869Sjfv } else 3711205869Sjfv accept_frame = 0; 3712205869Sjfv } 3713205869Sjfv 3714205869Sjfv if (accept_frame) { 3715205869Sjfv if (lem_get_buf(adapter, i) != 0) { 3716205869Sjfv ifp->if_iqdrops++; 3717205869Sjfv goto discard; 3718205869Sjfv } 3719205869Sjfv 3720205869Sjfv /* Assign correct length to the current fragment */ 3721205869Sjfv mp->m_len = len; 3722205869Sjfv 3723205869Sjfv if (adapter->fmp == NULL) { 3724205869Sjfv mp->m_pkthdr.len = len; 3725205869Sjfv adapter->fmp = mp; /* Store the first mbuf */ 3726205869Sjfv adapter->lmp = mp; 3727205869Sjfv } else { 3728205869Sjfv /* Chain mbuf's together */ 3729205869Sjfv mp->m_flags &= ~M_PKTHDR; 3730205869Sjfv /* 3731205869Sjfv * Adjust length of previous mbuf in chain if 3732205869Sjfv * we received less than 4 bytes in the last 3733205869Sjfv * descriptor. 3734205869Sjfv */ 3735205869Sjfv if (prev_len_adj > 0) { 3736205869Sjfv adapter->lmp->m_len -= prev_len_adj; 3737205869Sjfv adapter->fmp->m_pkthdr.len -= 3738205869Sjfv prev_len_adj; 3739205869Sjfv } 3740205869Sjfv adapter->lmp->m_next = mp; 3741205869Sjfv adapter->lmp = adapter->lmp->m_next; 3742205869Sjfv adapter->fmp->m_pkthdr.len += len; 3743205869Sjfv } 3744205869Sjfv 3745205869Sjfv if (eop) { 3746205869Sjfv adapter->fmp->m_pkthdr.rcvif = ifp; 3747205869Sjfv ifp->if_ipackets++; 3748205869Sjfv lem_receive_checksum(adapter, current_desc, 3749205869Sjfv adapter->fmp); 3750205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3751205869Sjfv if (adapter->max_frame_size > 3752205869Sjfv (MCLBYTES - ETHER_ALIGN) && 3753205869Sjfv lem_fixup_rx(adapter) != 0) 3754205869Sjfv goto skip; 3755205869Sjfv#endif 3756205869Sjfv if (status & E1000_RXD_STAT_VP) { 3757205869Sjfv adapter->fmp->m_pkthdr.ether_vtag = 3758229606Srwatson le16toh(current_desc->special); 3759205869Sjfv adapter->fmp->m_flags |= M_VLANTAG; 3760205869Sjfv } 3761205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3762205869Sjfvskip: 3763205869Sjfv#endif 3764205869Sjfv m = adapter->fmp; 3765205869Sjfv adapter->fmp = NULL; 3766205869Sjfv adapter->lmp = NULL; 3767205869Sjfv } 3768205869Sjfv } else { 3769240879Ssbruno adapter->dropped_pkts++; 3770205869Sjfvdiscard: 3771205869Sjfv /* Reuse loaded DMA map and just update mbuf chain */ 3772205869Sjfv mp = adapter->rx_buffer_area[i].m_head; 3773205869Sjfv mp->m_len = mp->m_pkthdr.len = MCLBYTES; 3774205869Sjfv mp->m_data = mp->m_ext.ext_buf; 3775205869Sjfv mp->m_next = NULL; 3776205869Sjfv if (adapter->max_frame_size <= 3777205869Sjfv (MCLBYTES - ETHER_ALIGN)) 3778205869Sjfv m_adj(mp, ETHER_ALIGN); 3779205869Sjfv if (adapter->fmp != NULL) { 3780205869Sjfv m_freem(adapter->fmp); 3781205869Sjfv adapter->fmp = NULL; 3782205869Sjfv adapter->lmp = NULL; 3783205869Sjfv } 3784205869Sjfv m = NULL; 3785205869Sjfv } 3786205869Sjfv 3787205869Sjfv /* Zero out the receive descriptors status. */ 3788205869Sjfv current_desc->status = 0; 3789205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3790205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3791205869Sjfv 3792270252Sluigi#ifdef NIC_PARAVIRT 3793270252Sluigi if (csb_mode) { 3794270252Sluigi /* the buffer at i has been already replaced by lem_get_buf() 3795270252Sluigi * so it is safe to set guest_rdt = i and possibly send a kick. 3796270252Sluigi * XXX see if we can optimize it later. 3797270252Sluigi */ 3798270252Sluigi csb->guest_rdt = i; 3799270252Sluigi // XXX memory barrier 3800270252Sluigi if (i == csb->host_rxkick_at) 3801270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); 3802270252Sluigi } 3803270252Sluigi#endif /* NIC_PARAVIRT */ 3804205869Sjfv /* Advance our pointers to the next descriptor. */ 3805205869Sjfv if (++i == adapter->num_rx_desc) 3806205869Sjfv i = 0; 3807205869Sjfv /* Call into the stack */ 3808205869Sjfv if (m != NULL) { 3809270252Sluigi#ifdef BATCH_DISPATCH 3810270252Sluigi if (adapter->batch_enable) { 3811270252Sluigi if (mh == NULL) 3812270252Sluigi mh = mt = m; 3813270252Sluigi else 3814270252Sluigi mt->m_nextpkt = m; 3815270252Sluigi mt = m; 3816270252Sluigi m->m_nextpkt = NULL; 3817270252Sluigi rx_sent++; 3818270252Sluigi current_desc = &adapter->rx_desc_base[i]; 3819270252Sluigi continue; 3820270252Sluigi } 3821270252Sluigi#endif /* BATCH_DISPATCH */ 3822205869Sjfv adapter->next_rx_desc_to_check = i; 3823205869Sjfv EM_RX_UNLOCK(adapter); 3824205869Sjfv (*ifp->if_input)(ifp, m); 3825205869Sjfv EM_RX_LOCK(adapter); 3826205869Sjfv rx_sent++; 3827205869Sjfv i = adapter->next_rx_desc_to_check; 3828205869Sjfv } 3829205869Sjfv current_desc = &adapter->rx_desc_base[i]; 3830205869Sjfv } 3831205869Sjfv adapter->next_rx_desc_to_check = i; 3832270252Sluigi#ifdef BATCH_DISPATCH 3833270252Sluigi if (mh) { 3834270252Sluigi EM_RX_UNLOCK(adapter); 3835270252Sluigi while ( (mt = mh) != NULL) { 3836270252Sluigi mh = mh->m_nextpkt; 3837270252Sluigi mt->m_nextpkt = NULL; 3838270252Sluigi if_input(ifp, mt); 3839270252Sluigi } 3840270252Sluigi EM_RX_LOCK(adapter); 3841270252Sluigi i = adapter->next_rx_desc_to_check; /* in case of interrupts */ 3842270252Sluigi if (count > 0) 3843270252Sluigi goto batch_again; 3844270252Sluigi } 3845270252Sluigi#endif /* BATCH_DISPATCH */ 3846205869Sjfv 3847205869Sjfv /* Advance the E1000's Receive Queue #0 "Tail Pointer". */ 3848205869Sjfv if (--i < 0) 3849205869Sjfv i = adapter->num_rx_desc - 1; 3850270252Sluigi#ifdef NIC_PARAVIRT 3851270252Sluigi if (!csb_mode) /* filter out writes */ 3852270252Sluigi#endif /* NIC_PARAVIRT */ 3853205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); 3854209238Sjfv if (done != NULL) 3855209238Sjfv *done = rx_sent; 3856205869Sjfv EM_RX_UNLOCK(adapter); 3857214646Sjfv return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE); 3858205869Sjfv} 3859205869Sjfv 3860205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3861205869Sjfv/* 3862205869Sjfv * When jumbo frames are enabled we should realign entire payload on 3863205869Sjfv * architecures with strict alignment. This is serious design mistake of 8254x 3864205869Sjfv * as it nullifies DMA operations. 8254x just allows RX buffer size to be 3865205869Sjfv * 2048/4096/8192/16384. What we really want is 2048 - ETHER_ALIGN to align its 3866205869Sjfv * payload. On architecures without strict alignment restrictions 8254x still 3867205869Sjfv * performs unaligned memory access which would reduce the performance too. 3868205869Sjfv * To avoid copying over an entire frame to align, we allocate a new mbuf and 3869205869Sjfv * copy ethernet header to the new mbuf. The new mbuf is prepended into the 3870205869Sjfv * existing mbuf chain. 3871205869Sjfv * 3872205869Sjfv * Be aware, best performance of the 8254x is achived only when jumbo frame is 3873205869Sjfv * not used at all on architectures with strict alignment. 3874205869Sjfv */ 3875205869Sjfvstatic int 3876205869Sjfvlem_fixup_rx(struct adapter *adapter) 3877205869Sjfv{ 3878205869Sjfv struct mbuf *m, *n; 3879205869Sjfv int error; 3880205869Sjfv 3881205869Sjfv error = 0; 3882205869Sjfv m = adapter->fmp; 3883205869Sjfv if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN)) { 3884205869Sjfv bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len); 3885205869Sjfv m->m_data += ETHER_HDR_LEN; 3886205869Sjfv } else { 3887243857Sglebius MGETHDR(n, M_NOWAIT, MT_DATA); 3888205869Sjfv if (n != NULL) { 3889205869Sjfv bcopy(m->m_data, n->m_data, ETHER_HDR_LEN); 3890205869Sjfv m->m_data += ETHER_HDR_LEN; 3891205869Sjfv m->m_len -= ETHER_HDR_LEN; 3892205869Sjfv n->m_len = ETHER_HDR_LEN; 3893205869Sjfv M_MOVE_PKTHDR(n, m); 3894205869Sjfv n->m_next = m; 3895205869Sjfv adapter->fmp = n; 3896205869Sjfv } else { 3897205869Sjfv adapter->dropped_pkts++; 3898205869Sjfv m_freem(adapter->fmp); 3899205869Sjfv adapter->fmp = NULL; 3900205869Sjfv error = ENOMEM; 3901205869Sjfv } 3902205869Sjfv } 3903205869Sjfv 3904205869Sjfv return (error); 3905205869Sjfv} 3906205869Sjfv#endif 3907205869Sjfv 3908205869Sjfv/********************************************************************* 3909205869Sjfv * 3910205869Sjfv * Verify that the hardware indicated that the checksum is valid. 3911205869Sjfv * Inform the stack about the status of checksum so that stack 3912205869Sjfv * doesn't spend time verifying the checksum. 3913205869Sjfv * 3914205869Sjfv *********************************************************************/ 3915205869Sjfvstatic void 3916205869Sjfvlem_receive_checksum(struct adapter *adapter, 3917205869Sjfv struct e1000_rx_desc *rx_desc, struct mbuf *mp) 3918205869Sjfv{ 3919205869Sjfv /* 82543 or newer only */ 3920205869Sjfv if ((adapter->hw.mac.type < e1000_82543) || 3921205869Sjfv /* Ignore Checksum bit is set */ 3922205869Sjfv (rx_desc->status & E1000_RXD_STAT_IXSM)) { 3923205869Sjfv mp->m_pkthdr.csum_flags = 0; 3924205869Sjfv return; 3925205869Sjfv } 3926205869Sjfv 3927205869Sjfv if (rx_desc->status & E1000_RXD_STAT_IPCS) { 3928205869Sjfv /* Did it pass? */ 3929205869Sjfv if (!(rx_desc->errors & E1000_RXD_ERR_IPE)) { 3930205869Sjfv /* IP Checksum Good */ 3931205869Sjfv mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; 3932205869Sjfv mp->m_pkthdr.csum_flags |= CSUM_IP_VALID; 3933205869Sjfv 3934205869Sjfv } else { 3935205869Sjfv mp->m_pkthdr.csum_flags = 0; 3936205869Sjfv } 3937205869Sjfv } 3938205869Sjfv 3939205869Sjfv if (rx_desc->status & E1000_RXD_STAT_TCPCS) { 3940205869Sjfv /* Did it pass? */ 3941205869Sjfv if (!(rx_desc->errors & E1000_RXD_ERR_TCPE)) { 3942205869Sjfv mp->m_pkthdr.csum_flags |= 3943205869Sjfv (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); 3944205869Sjfv mp->m_pkthdr.csum_data = htons(0xffff); 3945205869Sjfv } 3946205869Sjfv } 3947205869Sjfv} 3948205869Sjfv 3949205869Sjfv/* 3950205869Sjfv * This routine is run via an vlan 3951205869Sjfv * config EVENT 3952205869Sjfv */ 3953205869Sjfvstatic void 3954205869Sjfvlem_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3955205869Sjfv{ 3956205869Sjfv struct adapter *adapter = ifp->if_softc; 3957205869Sjfv u32 index, bit; 3958205869Sjfv 3959205869Sjfv if (ifp->if_softc != arg) /* Not our event */ 3960205869Sjfv return; 3961205869Sjfv 3962205869Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid ID */ 3963205869Sjfv return; 3964205869Sjfv 3965214646Sjfv EM_CORE_LOCK(adapter); 3966205869Sjfv index = (vtag >> 5) & 0x7F; 3967205869Sjfv bit = vtag & 0x1F; 3968214646Sjfv adapter->shadow_vfta[index] |= (1 << bit); 3969205869Sjfv ++adapter->num_vlans; 3970205869Sjfv /* Re-init to load the changes */ 3971214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 3972214646Sjfv lem_init_locked(adapter); 3973214646Sjfv EM_CORE_UNLOCK(adapter); 3974205869Sjfv} 3975205869Sjfv 3976205869Sjfv/* 3977205869Sjfv * This routine is run via an vlan 3978205869Sjfv * unconfig EVENT 3979205869Sjfv */ 3980205869Sjfvstatic void 3981205869Sjfvlem_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3982205869Sjfv{ 3983205869Sjfv struct adapter *adapter = ifp->if_softc; 3984205869Sjfv u32 index, bit; 3985205869Sjfv 3986205869Sjfv if (ifp->if_softc != arg) 3987205869Sjfv return; 3988205869Sjfv 3989205869Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 3990205869Sjfv return; 3991205869Sjfv 3992214646Sjfv EM_CORE_LOCK(adapter); 3993205869Sjfv index = (vtag >> 5) & 0x7F; 3994205869Sjfv bit = vtag & 0x1F; 3995214646Sjfv adapter->shadow_vfta[index] &= ~(1 << bit); 3996205869Sjfv --adapter->num_vlans; 3997205869Sjfv /* Re-init to load the changes */ 3998214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 3999214646Sjfv lem_init_locked(adapter); 4000214646Sjfv EM_CORE_UNLOCK(adapter); 4001205869Sjfv} 4002205869Sjfv 4003205869Sjfvstatic void 4004205869Sjfvlem_setup_vlan_hw_support(struct adapter *adapter) 4005205869Sjfv{ 4006205869Sjfv struct e1000_hw *hw = &adapter->hw; 4007205869Sjfv u32 reg; 4008205869Sjfv 4009205869Sjfv /* 4010205869Sjfv ** We get here thru init_locked, meaning 4011205869Sjfv ** a soft reset, this has already cleared 4012205869Sjfv ** the VFTA and other state, so if there 4013205869Sjfv ** have been no vlan's registered do nothing. 4014205869Sjfv */ 4015205869Sjfv if (adapter->num_vlans == 0) 4016205869Sjfv return; 4017205869Sjfv 4018205869Sjfv /* 4019205869Sjfv ** A soft reset zero's out the VFTA, so 4020205869Sjfv ** we need to repopulate it now. 4021205869Sjfv */ 4022205869Sjfv for (int i = 0; i < EM_VFTA_SIZE; i++) 4023214646Sjfv if (adapter->shadow_vfta[i] != 0) 4024205869Sjfv E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, 4025214646Sjfv i, adapter->shadow_vfta[i]); 4026205869Sjfv 4027205869Sjfv reg = E1000_READ_REG(hw, E1000_CTRL); 4028205869Sjfv reg |= E1000_CTRL_VME; 4029205869Sjfv E1000_WRITE_REG(hw, E1000_CTRL, reg); 4030205869Sjfv 4031205869Sjfv /* Enable the Filter Table */ 4032205869Sjfv reg = E1000_READ_REG(hw, E1000_RCTL); 4033205869Sjfv reg &= ~E1000_RCTL_CFIEN; 4034205869Sjfv reg |= E1000_RCTL_VFE; 4035205869Sjfv E1000_WRITE_REG(hw, E1000_RCTL, reg); 4036205869Sjfv} 4037205869Sjfv 4038205869Sjfvstatic void 4039205869Sjfvlem_enable_intr(struct adapter *adapter) 4040205869Sjfv{ 4041205869Sjfv struct e1000_hw *hw = &adapter->hw; 4042205869Sjfv u32 ims_mask = IMS_ENABLE_MASK; 4043205869Sjfv 4044205869Sjfv E1000_WRITE_REG(hw, E1000_IMS, ims_mask); 4045205869Sjfv} 4046205869Sjfv 4047205869Sjfvstatic void 4048205869Sjfvlem_disable_intr(struct adapter *adapter) 4049205869Sjfv{ 4050205869Sjfv struct e1000_hw *hw = &adapter->hw; 4051205869Sjfv 4052238953Sjfv E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 4053205869Sjfv} 4054205869Sjfv 4055205869Sjfv/* 4056205869Sjfv * Bit of a misnomer, what this really means is 4057205869Sjfv * to enable OS management of the system... aka 4058205869Sjfv * to disable special hardware management features 4059205869Sjfv */ 4060205869Sjfvstatic void 4061205869Sjfvlem_init_manageability(struct adapter *adapter) 4062205869Sjfv{ 4063205869Sjfv /* A shared code workaround */ 4064205869Sjfv if (adapter->has_manage) { 4065205869Sjfv int manc = E1000_READ_REG(&adapter->hw, E1000_MANC); 4066205869Sjfv /* disable hardware interception of ARP */ 4067205869Sjfv manc &= ~(E1000_MANC_ARP_EN); 4068205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); 4069205869Sjfv } 4070205869Sjfv} 4071205869Sjfv 4072205869Sjfv/* 4073205869Sjfv * Give control back to hardware management 4074205869Sjfv * controller if there is one. 4075205869Sjfv */ 4076205869Sjfvstatic void 4077205869Sjfvlem_release_manageability(struct adapter *adapter) 4078205869Sjfv{ 4079205869Sjfv if (adapter->has_manage) { 4080205869Sjfv int manc = E1000_READ_REG(&adapter->hw, E1000_MANC); 4081205869Sjfv 4082205869Sjfv /* re-enable hardware interception of ARP */ 4083205869Sjfv manc |= E1000_MANC_ARP_EN; 4084205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); 4085205869Sjfv } 4086205869Sjfv} 4087205869Sjfv 4088205869Sjfv/* 4089205869Sjfv * lem_get_hw_control sets the {CTRL_EXT|FWSM}:DRV_LOAD bit. 4090205869Sjfv * For ASF and Pass Through versions of f/w this means 4091205869Sjfv * that the driver is loaded. For AMT version type f/w 4092205869Sjfv * this means that the network i/f is open. 4093205869Sjfv */ 4094205869Sjfvstatic void 4095205869Sjfvlem_get_hw_control(struct adapter *adapter) 4096205869Sjfv{ 4097205869Sjfv u32 ctrl_ext; 4098205869Sjfv 4099205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 4100205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, 4101205869Sjfv ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); 4102205869Sjfv return; 4103205869Sjfv} 4104205869Sjfv 4105205869Sjfv/* 4106205869Sjfv * lem_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit. 4107205869Sjfv * For ASF and Pass Through versions of f/w this means that 4108205869Sjfv * the driver is no longer loaded. For AMT versions of the 4109205869Sjfv * f/w this means that the network i/f is closed. 4110205869Sjfv */ 4111205869Sjfvstatic void 4112205869Sjfvlem_release_hw_control(struct adapter *adapter) 4113205869Sjfv{ 4114205869Sjfv u32 ctrl_ext; 4115205869Sjfv 4116205869Sjfv if (!adapter->has_manage) 4117205869Sjfv return; 4118205869Sjfv 4119205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 4120205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, 4121205869Sjfv ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); 4122205869Sjfv return; 4123205869Sjfv} 4124205869Sjfv 4125205869Sjfvstatic int 4126205869Sjfvlem_is_valid_ether_addr(u8 *addr) 4127205869Sjfv{ 4128205869Sjfv char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; 4129205869Sjfv 4130205869Sjfv if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) { 4131205869Sjfv return (FALSE); 4132205869Sjfv } 4133205869Sjfv 4134205869Sjfv return (TRUE); 4135205869Sjfv} 4136205869Sjfv 4137205869Sjfv/* 4138205869Sjfv** Parse the interface capabilities with regard 4139205869Sjfv** to both system management and wake-on-lan for 4140205869Sjfv** later use. 4141205869Sjfv*/ 4142205869Sjfvstatic void 4143205869Sjfvlem_get_wakeup(device_t dev) 4144205869Sjfv{ 4145205869Sjfv struct adapter *adapter = device_get_softc(dev); 4146205869Sjfv u16 eeprom_data = 0, device_id, apme_mask; 4147205869Sjfv 4148205869Sjfv adapter->has_manage = e1000_enable_mng_pass_thru(&adapter->hw); 4149205869Sjfv apme_mask = EM_EEPROM_APME; 4150205869Sjfv 4151205869Sjfv switch (adapter->hw.mac.type) { 4152205869Sjfv case e1000_82542: 4153205869Sjfv case e1000_82543: 4154205869Sjfv break; 4155205869Sjfv case e1000_82544: 4156205869Sjfv e1000_read_nvm(&adapter->hw, 4157205869Sjfv NVM_INIT_CONTROL2_REG, 1, &eeprom_data); 4158205869Sjfv apme_mask = EM_82544_APME; 4159205869Sjfv break; 4160205869Sjfv case e1000_82546: 4161205869Sjfv case e1000_82546_rev_3: 4162205869Sjfv if (adapter->hw.bus.func == 1) { 4163205869Sjfv e1000_read_nvm(&adapter->hw, 4164205869Sjfv NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); 4165205869Sjfv break; 4166205869Sjfv } else 4167205869Sjfv e1000_read_nvm(&adapter->hw, 4168205869Sjfv NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); 4169205869Sjfv break; 4170205869Sjfv default: 4171205869Sjfv e1000_read_nvm(&adapter->hw, 4172205869Sjfv NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); 4173205869Sjfv break; 4174205869Sjfv } 4175205869Sjfv if (eeprom_data & apme_mask) 4176205869Sjfv adapter->wol = (E1000_WUFC_MAG | E1000_WUFC_MC); 4177205869Sjfv /* 4178205869Sjfv * We have the eeprom settings, now apply the special cases 4179205869Sjfv * where the eeprom may be wrong or the board won't support 4180205869Sjfv * wake on lan on a particular port 4181205869Sjfv */ 4182205869Sjfv device_id = pci_get_device(dev); 4183205869Sjfv switch (device_id) { 4184205869Sjfv case E1000_DEV_ID_82546GB_PCIE: 4185205869Sjfv adapter->wol = 0; 4186205869Sjfv break; 4187205869Sjfv case E1000_DEV_ID_82546EB_FIBER: 4188205869Sjfv case E1000_DEV_ID_82546GB_FIBER: 4189205869Sjfv /* Wake events only supported on port A for dual fiber 4190205869Sjfv * regardless of eeprom setting */ 4191205869Sjfv if (E1000_READ_REG(&adapter->hw, E1000_STATUS) & 4192205869Sjfv E1000_STATUS_FUNC_1) 4193205869Sjfv adapter->wol = 0; 4194205869Sjfv break; 4195205869Sjfv case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: 4196205869Sjfv /* if quad port adapter, disable WoL on all but port A */ 4197205869Sjfv if (global_quad_port_a != 0) 4198205869Sjfv adapter->wol = 0; 4199205869Sjfv /* Reset for multiple quad port adapters */ 4200205869Sjfv if (++global_quad_port_a == 4) 4201205869Sjfv global_quad_port_a = 0; 4202205869Sjfv break; 4203205869Sjfv } 4204205869Sjfv return; 4205205869Sjfv} 4206205869Sjfv 4207205869Sjfv 4208205869Sjfv/* 4209205869Sjfv * Enable PCI Wake On Lan capability 4210205869Sjfv */ 4211206001Smariusstatic void 4212205869Sjfvlem_enable_wakeup(device_t dev) 4213205869Sjfv{ 4214205869Sjfv struct adapter *adapter = device_get_softc(dev); 4215205869Sjfv struct ifnet *ifp = adapter->ifp; 4216205869Sjfv u32 pmc, ctrl, ctrl_ext, rctl; 4217205869Sjfv u16 status; 4218205869Sjfv 4219219902Sjhb if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0)) 4220205869Sjfv return; 4221205869Sjfv 4222205869Sjfv /* Advertise the wakeup capability */ 4223205869Sjfv ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); 4224205869Sjfv ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); 4225205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); 4226205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); 4227205869Sjfv 4228205869Sjfv /* Keep the laser running on Fiber adapters */ 4229205869Sjfv if (adapter->hw.phy.media_type == e1000_media_type_fiber || 4230205869Sjfv adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { 4231205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 4232205869Sjfv ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; 4233205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext); 4234205869Sjfv } 4235205869Sjfv 4236205869Sjfv /* 4237205869Sjfv ** Determine type of Wakeup: note that wol 4238205869Sjfv ** is set with all bits on by default. 4239205869Sjfv */ 4240205869Sjfv if ((ifp->if_capenable & IFCAP_WOL_MAGIC) == 0) 4241205869Sjfv adapter->wol &= ~E1000_WUFC_MAG; 4242205869Sjfv 4243205869Sjfv if ((ifp->if_capenable & IFCAP_WOL_MCAST) == 0) 4244205869Sjfv adapter->wol &= ~E1000_WUFC_MC; 4245205869Sjfv else { 4246205869Sjfv rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 4247205869Sjfv rctl |= E1000_RCTL_MPE; 4248205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); 4249205869Sjfv } 4250205869Sjfv 4251205869Sjfv if (adapter->hw.mac.type == e1000_pchlan) { 4252205869Sjfv if (lem_enable_phy_wakeup(adapter)) 4253205869Sjfv return; 4254205869Sjfv } else { 4255205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); 4256205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol); 4257205869Sjfv } 4258205869Sjfv 4259205869Sjfv 4260205869Sjfv /* Request PME */ 4261205869Sjfv status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2); 4262205869Sjfv status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); 4263205869Sjfv if (ifp->if_capenable & IFCAP_WOL) 4264205869Sjfv status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; 4265205869Sjfv pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2); 4266205869Sjfv 4267205869Sjfv return; 4268205869Sjfv} 4269205869Sjfv 4270205869Sjfv/* 4271205869Sjfv** WOL in the newer chipset interfaces (pchlan) 4272205869Sjfv** require thing to be copied into the phy 4273205869Sjfv*/ 4274205869Sjfvstatic int 4275205869Sjfvlem_enable_phy_wakeup(struct adapter *adapter) 4276205869Sjfv{ 4277205869Sjfv struct e1000_hw *hw = &adapter->hw; 4278205869Sjfv u32 mreg, ret = 0; 4279205869Sjfv u16 preg; 4280205869Sjfv 4281205869Sjfv /* copy MAC RARs to PHY RARs */ 4282205869Sjfv for (int i = 0; i < adapter->hw.mac.rar_entry_count; i++) { 4283205869Sjfv mreg = E1000_READ_REG(hw, E1000_RAL(i)); 4284205869Sjfv e1000_write_phy_reg(hw, BM_RAR_L(i), (u16)(mreg & 0xFFFF)); 4285205869Sjfv e1000_write_phy_reg(hw, BM_RAR_M(i), 4286205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4287205869Sjfv mreg = E1000_READ_REG(hw, E1000_RAH(i)); 4288205869Sjfv e1000_write_phy_reg(hw, BM_RAR_H(i), (u16)(mreg & 0xFFFF)); 4289205869Sjfv e1000_write_phy_reg(hw, BM_RAR_CTRL(i), 4290205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4291205869Sjfv } 4292205869Sjfv 4293205869Sjfv /* copy MAC MTA to PHY MTA */ 4294205869Sjfv for (int i = 0; i < adapter->hw.mac.mta_reg_count; i++) { 4295205869Sjfv mreg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); 4296205869Sjfv e1000_write_phy_reg(hw, BM_MTA(i), (u16)(mreg & 0xFFFF)); 4297205869Sjfv e1000_write_phy_reg(hw, BM_MTA(i) + 1, 4298205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4299205869Sjfv } 4300205869Sjfv 4301205869Sjfv /* configure PHY Rx Control register */ 4302205869Sjfv e1000_read_phy_reg(&adapter->hw, BM_RCTL, &preg); 4303205869Sjfv mreg = E1000_READ_REG(hw, E1000_RCTL); 4304205869Sjfv if (mreg & E1000_RCTL_UPE) 4305205869Sjfv preg |= BM_RCTL_UPE; 4306205869Sjfv if (mreg & E1000_RCTL_MPE) 4307205869Sjfv preg |= BM_RCTL_MPE; 4308205869Sjfv preg &= ~(BM_RCTL_MO_MASK); 4309205869Sjfv if (mreg & E1000_RCTL_MO_3) 4310205869Sjfv preg |= (((mreg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) 4311205869Sjfv << BM_RCTL_MO_SHIFT); 4312205869Sjfv if (mreg & E1000_RCTL_BAM) 4313205869Sjfv preg |= BM_RCTL_BAM; 4314205869Sjfv if (mreg & E1000_RCTL_PMCF) 4315205869Sjfv preg |= BM_RCTL_PMCF; 4316205869Sjfv mreg = E1000_READ_REG(hw, E1000_CTRL); 4317205869Sjfv if (mreg & E1000_CTRL_RFCE) 4318205869Sjfv preg |= BM_RCTL_RFCE; 4319205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_RCTL, preg); 4320205869Sjfv 4321205869Sjfv /* enable PHY wakeup in MAC register */ 4322205869Sjfv E1000_WRITE_REG(hw, E1000_WUC, 4323205869Sjfv E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); 4324205869Sjfv E1000_WRITE_REG(hw, E1000_WUFC, adapter->wol); 4325205869Sjfv 4326205869Sjfv /* configure and enable PHY wakeup in PHY registers */ 4327205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_WUFC, adapter->wol); 4328205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); 4329205869Sjfv 4330205869Sjfv /* activate PHY wakeup */ 4331205869Sjfv ret = hw->phy.ops.acquire(hw); 4332205869Sjfv if (ret) { 4333205869Sjfv printf("Could not acquire PHY\n"); 4334205869Sjfv return ret; 4335205869Sjfv } 4336205869Sjfv e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 4337205869Sjfv (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); 4338205869Sjfv ret = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &preg); 4339205869Sjfv if (ret) { 4340205869Sjfv printf("Could not read PHY page 769\n"); 4341205869Sjfv goto out; 4342205869Sjfv } 4343205869Sjfv preg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; 4344205869Sjfv ret = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, preg); 4345205869Sjfv if (ret) 4346205869Sjfv printf("Could not set PHY Host Wakeup bit\n"); 4347205869Sjfvout: 4348205869Sjfv hw->phy.ops.release(hw); 4349205869Sjfv 4350205869Sjfv return ret; 4351205869Sjfv} 4352205869Sjfv 4353206001Smariusstatic void 4354206001Smariuslem_led_func(void *arg, int onoff) 4355206001Smarius{ 4356206001Smarius struct adapter *adapter = arg; 4357205869Sjfv 4358206001Smarius EM_CORE_LOCK(adapter); 4359206001Smarius if (onoff) { 4360206001Smarius e1000_setup_led(&adapter->hw); 4361206001Smarius e1000_led_on(&adapter->hw); 4362206001Smarius } else { 4363206001Smarius e1000_led_off(&adapter->hw); 4364206001Smarius e1000_cleanup_led(&adapter->hw); 4365206001Smarius } 4366206001Smarius EM_CORE_UNLOCK(adapter); 4367206001Smarius} 4368206001Smarius 4369205869Sjfv/********************************************************************* 4370205869Sjfv* 82544 Coexistence issue workaround. 4371205869Sjfv* There are 2 issues. 4372205869Sjfv* 1. Transmit Hang issue. 4373205869Sjfv* To detect this issue, following equation can be used... 4374205869Sjfv* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 4375205869Sjfv* If SUM[3:0] is in between 1 to 4, we will have this issue. 4376205869Sjfv* 4377205869Sjfv* 2. DAC issue. 4378205869Sjfv* To detect this issue, following equation can be used... 4379205869Sjfv* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 4380205869Sjfv* If SUM[3:0] is in between 9 to c, we will have this issue. 4381205869Sjfv* 4382205869Sjfv* 4383205869Sjfv* WORKAROUND: 4384205869Sjfv* Make sure we do not have ending address 4385205869Sjfv* as 1,2,3,4(Hang) or 9,a,b,c (DAC) 4386205869Sjfv* 4387205869Sjfv*************************************************************************/ 4388205869Sjfvstatic u32 4389205869Sjfvlem_fill_descriptors (bus_addr_t address, u32 length, 4390205869Sjfv PDESC_ARRAY desc_array) 4391205869Sjfv{ 4392205869Sjfv u32 safe_terminator; 4393205869Sjfv 4394205869Sjfv /* Since issue is sensitive to length and address.*/ 4395205869Sjfv /* Let us first check the address...*/ 4396205869Sjfv if (length <= 4) { 4397205869Sjfv desc_array->descriptor[0].address = address; 4398205869Sjfv desc_array->descriptor[0].length = length; 4399205869Sjfv desc_array->elements = 1; 4400205869Sjfv return (desc_array->elements); 4401205869Sjfv } 4402205869Sjfv safe_terminator = (u32)((((u32)address & 0x7) + 4403205869Sjfv (length & 0xF)) & 0xF); 4404205869Sjfv /* if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then return */ 4405205869Sjfv if (safe_terminator == 0 || 4406205869Sjfv (safe_terminator > 4 && 4407205869Sjfv safe_terminator < 9) || 4408205869Sjfv (safe_terminator > 0xC && 4409205869Sjfv safe_terminator <= 0xF)) { 4410205869Sjfv desc_array->descriptor[0].address = address; 4411205869Sjfv desc_array->descriptor[0].length = length; 4412205869Sjfv desc_array->elements = 1; 4413205869Sjfv return (desc_array->elements); 4414205869Sjfv } 4415205869Sjfv 4416205869Sjfv desc_array->descriptor[0].address = address; 4417205869Sjfv desc_array->descriptor[0].length = length - 4; 4418205869Sjfv desc_array->descriptor[1].address = address + (length - 4); 4419205869Sjfv desc_array->descriptor[1].length = 4; 4420205869Sjfv desc_array->elements = 2; 4421205869Sjfv return (desc_array->elements); 4422205869Sjfv} 4423205869Sjfv 4424205869Sjfv/********************************************************************** 4425205869Sjfv * 4426205869Sjfv * Update the board statistics counters. 4427205869Sjfv * 4428205869Sjfv **********************************************************************/ 4429205869Sjfvstatic void 4430205869Sjfvlem_update_stats_counters(struct adapter *adapter) 4431205869Sjfv{ 4432205869Sjfv struct ifnet *ifp; 4433205869Sjfv 4434205869Sjfv if(adapter->hw.phy.media_type == e1000_media_type_copper || 4435205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_STATUS) & E1000_STATUS_LU)) { 4436205869Sjfv adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, E1000_SYMERRS); 4437205869Sjfv adapter->stats.sec += E1000_READ_REG(&adapter->hw, E1000_SEC); 4438205869Sjfv } 4439205869Sjfv adapter->stats.crcerrs += E1000_READ_REG(&adapter->hw, E1000_CRCERRS); 4440205869Sjfv adapter->stats.mpc += E1000_READ_REG(&adapter->hw, E1000_MPC); 4441205869Sjfv adapter->stats.scc += E1000_READ_REG(&adapter->hw, E1000_SCC); 4442205869Sjfv adapter->stats.ecol += E1000_READ_REG(&adapter->hw, E1000_ECOL); 4443205869Sjfv 4444205869Sjfv adapter->stats.mcc += E1000_READ_REG(&adapter->hw, E1000_MCC); 4445205869Sjfv adapter->stats.latecol += E1000_READ_REG(&adapter->hw, E1000_LATECOL); 4446205869Sjfv adapter->stats.colc += E1000_READ_REG(&adapter->hw, E1000_COLC); 4447205869Sjfv adapter->stats.dc += E1000_READ_REG(&adapter->hw, E1000_DC); 4448205869Sjfv adapter->stats.rlec += E1000_READ_REG(&adapter->hw, E1000_RLEC); 4449205869Sjfv adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, E1000_XONRXC); 4450205869Sjfv adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, E1000_XONTXC); 4451205869Sjfv adapter->stats.xoffrxc += E1000_READ_REG(&adapter->hw, E1000_XOFFRXC); 4452205869Sjfv adapter->stats.xofftxc += E1000_READ_REG(&adapter->hw, E1000_XOFFTXC); 4453205869Sjfv adapter->stats.fcruc += E1000_READ_REG(&adapter->hw, E1000_FCRUC); 4454205869Sjfv adapter->stats.prc64 += E1000_READ_REG(&adapter->hw, E1000_PRC64); 4455205869Sjfv adapter->stats.prc127 += E1000_READ_REG(&adapter->hw, E1000_PRC127); 4456205869Sjfv adapter->stats.prc255 += E1000_READ_REG(&adapter->hw, E1000_PRC255); 4457205869Sjfv adapter->stats.prc511 += E1000_READ_REG(&adapter->hw, E1000_PRC511); 4458205869Sjfv adapter->stats.prc1023 += E1000_READ_REG(&adapter->hw, E1000_PRC1023); 4459205869Sjfv adapter->stats.prc1522 += E1000_READ_REG(&adapter->hw, E1000_PRC1522); 4460205869Sjfv adapter->stats.gprc += E1000_READ_REG(&adapter->hw, E1000_GPRC); 4461205869Sjfv adapter->stats.bprc += E1000_READ_REG(&adapter->hw, E1000_BPRC); 4462205869Sjfv adapter->stats.mprc += E1000_READ_REG(&adapter->hw, E1000_MPRC); 4463205869Sjfv adapter->stats.gptc += E1000_READ_REG(&adapter->hw, E1000_GPTC); 4464205869Sjfv 4465205869Sjfv /* For the 64-bit byte counters the low dword must be read first. */ 4466205869Sjfv /* Both registers clear on the read of the high dword */ 4467205869Sjfv 4468212902Sjhb adapter->stats.gorc += E1000_READ_REG(&adapter->hw, E1000_GORCL) + 4469212902Sjhb ((u64)E1000_READ_REG(&adapter->hw, E1000_GORCH) << 32); 4470212902Sjhb adapter->stats.gotc += E1000_READ_REG(&adapter->hw, E1000_GOTCL) + 4471212902Sjhb ((u64)E1000_READ_REG(&adapter->hw, E1000_GOTCH) << 32); 4472205869Sjfv 4473205869Sjfv adapter->stats.rnbc += E1000_READ_REG(&adapter->hw, E1000_RNBC); 4474205869Sjfv adapter->stats.ruc += E1000_READ_REG(&adapter->hw, E1000_RUC); 4475205869Sjfv adapter->stats.rfc += E1000_READ_REG(&adapter->hw, E1000_RFC); 4476205869Sjfv adapter->stats.roc += E1000_READ_REG(&adapter->hw, E1000_ROC); 4477205869Sjfv adapter->stats.rjc += E1000_READ_REG(&adapter->hw, E1000_RJC); 4478205869Sjfv 4479205869Sjfv adapter->stats.tor += E1000_READ_REG(&adapter->hw, E1000_TORH); 4480205869Sjfv adapter->stats.tot += E1000_READ_REG(&adapter->hw, E1000_TOTH); 4481205869Sjfv 4482205869Sjfv adapter->stats.tpr += E1000_READ_REG(&adapter->hw, E1000_TPR); 4483205869Sjfv adapter->stats.tpt += E1000_READ_REG(&adapter->hw, E1000_TPT); 4484205869Sjfv adapter->stats.ptc64 += E1000_READ_REG(&adapter->hw, E1000_PTC64); 4485205869Sjfv adapter->stats.ptc127 += E1000_READ_REG(&adapter->hw, E1000_PTC127); 4486205869Sjfv adapter->stats.ptc255 += E1000_READ_REG(&adapter->hw, E1000_PTC255); 4487205869Sjfv adapter->stats.ptc511 += E1000_READ_REG(&adapter->hw, E1000_PTC511); 4488205869Sjfv adapter->stats.ptc1023 += E1000_READ_REG(&adapter->hw, E1000_PTC1023); 4489205869Sjfv adapter->stats.ptc1522 += E1000_READ_REG(&adapter->hw, E1000_PTC1522); 4490205869Sjfv adapter->stats.mptc += E1000_READ_REG(&adapter->hw, E1000_MPTC); 4491205869Sjfv adapter->stats.bptc += E1000_READ_REG(&adapter->hw, E1000_BPTC); 4492205869Sjfv 4493205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 4494205869Sjfv adapter->stats.algnerrc += 4495205869Sjfv E1000_READ_REG(&adapter->hw, E1000_ALGNERRC); 4496205869Sjfv adapter->stats.rxerrc += 4497205869Sjfv E1000_READ_REG(&adapter->hw, E1000_RXERRC); 4498205869Sjfv adapter->stats.tncrs += 4499205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TNCRS); 4500205869Sjfv adapter->stats.cexterr += 4501205869Sjfv E1000_READ_REG(&adapter->hw, E1000_CEXTERR); 4502205869Sjfv adapter->stats.tsctc += 4503205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TSCTC); 4504205869Sjfv adapter->stats.tsctfc += 4505205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TSCTFC); 4506205869Sjfv } 4507205869Sjfv ifp = adapter->ifp; 4508205869Sjfv 4509205869Sjfv ifp->if_collisions = adapter->stats.colc; 4510205869Sjfv 4511205869Sjfv /* Rx Errors */ 4512205869Sjfv ifp->if_ierrors = adapter->dropped_pkts + adapter->stats.rxerrc + 4513205869Sjfv adapter->stats.crcerrs + adapter->stats.algnerrc + 4514205869Sjfv adapter->stats.ruc + adapter->stats.roc + 4515205869Sjfv adapter->stats.mpc + adapter->stats.cexterr; 4516205869Sjfv 4517205869Sjfv /* Tx Errors */ 4518205869Sjfv ifp->if_oerrors = adapter->stats.ecol + 4519205869Sjfv adapter->stats.latecol + adapter->watchdog_events; 4520205869Sjfv} 4521205869Sjfv 4522212902Sjhb/* Export a single 32-bit register via a read-only sysctl. */ 4523212902Sjhbstatic int 4524212902Sjhblem_sysctl_reg_handler(SYSCTL_HANDLER_ARGS) 4525205869Sjfv{ 4526212902Sjhb struct adapter *adapter; 4527212902Sjhb u_int val; 4528205869Sjfv 4529212902Sjhb adapter = oidp->oid_arg1; 4530212902Sjhb val = E1000_READ_REG(&adapter->hw, oidp->oid_arg2); 4531212902Sjhb return (sysctl_handle_int(oidp, &val, 0, req)); 4532205869Sjfv} 4533205869Sjfv 4534212902Sjhb/* 4535212902Sjhb * Add sysctl variables, one per statistic, to the system. 4536212902Sjhb */ 4537205869Sjfvstatic void 4538212902Sjhblem_add_hw_stats(struct adapter *adapter) 4539205869Sjfv{ 4540205869Sjfv device_t dev = adapter->dev; 4541205869Sjfv 4542212902Sjhb struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 4543212902Sjhb struct sysctl_oid *tree = device_get_sysctl_tree(dev); 4544212902Sjhb struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 4545212902Sjhb struct e1000_hw_stats *stats = &adapter->stats; 4546212902Sjhb 4547212902Sjhb struct sysctl_oid *stat_node; 4548212902Sjhb struct sysctl_oid_list *stat_list; 4549212902Sjhb 4550212902Sjhb /* Driver Statistics */ 4551212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_alloc_fail", 4552212902Sjhb CTLFLAG_RD, &adapter->mbuf_alloc_failed, 4553212902Sjhb "Std mbuf failed"); 4554212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail", 4555212902Sjhb CTLFLAG_RD, &adapter->mbuf_cluster_failed, 4556212902Sjhb "Std mbuf cluster failed"); 4557212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 4558212902Sjhb CTLFLAG_RD, &adapter->dropped_pkts, 4559212902Sjhb "Driver dropped packets"); 4560212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail", 4561212902Sjhb CTLFLAG_RD, &adapter->no_tx_dma_setup, 4562212902Sjhb "Driver tx dma failure in xmit"); 4563212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_desc_fail1", 4564212902Sjhb CTLFLAG_RD, &adapter->no_tx_desc_avail1, 4565212902Sjhb "Not enough tx descriptors failure in xmit"); 4566212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_desc_fail2", 4567212902Sjhb CTLFLAG_RD, &adapter->no_tx_desc_avail2, 4568212902Sjhb "Not enough tx descriptors failure in xmit"); 4569212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns", 4570212902Sjhb CTLFLAG_RD, &adapter->rx_overruns, 4571212902Sjhb "RX overruns"); 4572212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_timeouts", 4573212902Sjhb CTLFLAG_RD, &adapter->watchdog_events, 4574212902Sjhb "Watchdog timeouts"); 4575212902Sjhb 4576212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "device_control", 4577217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_CTRL, 4578212902Sjhb lem_sysctl_reg_handler, "IU", 4579212902Sjhb "Device Control Register"); 4580212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_control", 4581217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RCTL, 4582212902Sjhb lem_sysctl_reg_handler, "IU", 4583212902Sjhb "Receiver Control Register"); 4584212902Sjhb SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_high_water", 4585212902Sjhb CTLFLAG_RD, &adapter->hw.fc.high_water, 0, 4586212902Sjhb "Flow Control High Watermark"); 4587212902Sjhb SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_low_water", 4588212902Sjhb CTLFLAG_RD, &adapter->hw.fc.low_water, 0, 4589212902Sjhb "Flow Control Low Watermark"); 4590217318Smdf SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_workaround", 4591212902Sjhb CTLFLAG_RD, &adapter->tx_fifo_wrk_cnt, 4592212902Sjhb "TX FIFO workaround events"); 4593217318Smdf SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_reset", 4594212902Sjhb CTLFLAG_RD, &adapter->tx_fifo_reset_cnt, 4595212902Sjhb "TX FIFO resets"); 4596212902Sjhb 4597212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_head", 4598217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDH(0), 4599212902Sjhb lem_sysctl_reg_handler, "IU", 4600212902Sjhb "Transmit Descriptor Head"); 4601212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_tail", 4602217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDT(0), 4603212902Sjhb lem_sysctl_reg_handler, "IU", 4604212902Sjhb "Transmit Descriptor Tail"); 4605212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_head", 4606217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDH(0), 4607212902Sjhb lem_sysctl_reg_handler, "IU", 4608212902Sjhb "Receive Descriptor Head"); 4609212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_tail", 4610217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDT(0), 4611212902Sjhb lem_sysctl_reg_handler, "IU", 4612212902Sjhb "Receive Descriptor Tail"); 4613212902Sjhb 4614212902Sjhb 4615212902Sjhb /* MAC stats get their own sub node */ 4616212902Sjhb 4617212902Sjhb stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 4618212902Sjhb CTLFLAG_RD, NULL, "Statistics"); 4619212902Sjhb stat_list = SYSCTL_CHILDREN(stat_node); 4620212902Sjhb 4621217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "excess_coll", 4622212902Sjhb CTLFLAG_RD, &stats->ecol, 4623212902Sjhb "Excessive collisions"); 4624217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "single_coll", 4625212902Sjhb CTLFLAG_RD, &stats->scc, 4626212902Sjhb "Single collisions"); 4627217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "multiple_coll", 4628212902Sjhb CTLFLAG_RD, &stats->mcc, 4629212902Sjhb "Multiple collisions"); 4630217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "late_coll", 4631212902Sjhb CTLFLAG_RD, &stats->latecol, 4632212902Sjhb "Late collisions"); 4633217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "collision_count", 4634212902Sjhb CTLFLAG_RD, &stats->colc, 4635212902Sjhb "Collision Count"); 4636217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "symbol_errors", 4637212902Sjhb CTLFLAG_RD, &adapter->stats.symerrs, 4638212902Sjhb "Symbol Errors"); 4639217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "sequence_errors", 4640212902Sjhb CTLFLAG_RD, &adapter->stats.sec, 4641212902Sjhb "Sequence Errors"); 4642217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "defer_count", 4643212902Sjhb CTLFLAG_RD, &adapter->stats.dc, 4644212902Sjhb "Defer Count"); 4645217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "missed_packets", 4646212902Sjhb CTLFLAG_RD, &adapter->stats.mpc, 4647212902Sjhb "Missed Packets"); 4648217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_no_buff", 4649212902Sjhb CTLFLAG_RD, &adapter->stats.rnbc, 4650212902Sjhb "Receive No Buffers"); 4651217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersize", 4652212902Sjhb CTLFLAG_RD, &adapter->stats.ruc, 4653212902Sjhb "Receive Undersize"); 4654217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", 4655212902Sjhb CTLFLAG_RD, &adapter->stats.rfc, 4656212902Sjhb "Fragmented Packets Received "); 4657217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversize", 4658212902Sjhb CTLFLAG_RD, &adapter->stats.roc, 4659212902Sjhb "Oversized Packets Received"); 4660217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabber", 4661212902Sjhb CTLFLAG_RD, &adapter->stats.rjc, 4662212902Sjhb "Recevied Jabber"); 4663217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_errs", 4664212902Sjhb CTLFLAG_RD, &adapter->stats.rxerrc, 4665212902Sjhb "Receive Errors"); 4666217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", 4667212902Sjhb CTLFLAG_RD, &adapter->stats.crcerrs, 4668212902Sjhb "CRC errors"); 4669217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "alignment_errs", 4670212902Sjhb CTLFLAG_RD, &adapter->stats.algnerrc, 4671212902Sjhb "Alignment Errors"); 4672217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs", 4673212902Sjhb CTLFLAG_RD, &adapter->stats.cexterr, 4674212902Sjhb "Collision/Carrier extension errors"); 4675217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", 4676212902Sjhb CTLFLAG_RD, &adapter->stats.xonrxc, 4677212902Sjhb "XON Received"); 4678217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", 4679212902Sjhb CTLFLAG_RD, &adapter->stats.xontxc, 4680212902Sjhb "XON Transmitted"); 4681217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", 4682212902Sjhb CTLFLAG_RD, &adapter->stats.xoffrxc, 4683212902Sjhb "XOFF Received"); 4684217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", 4685212902Sjhb CTLFLAG_RD, &adapter->stats.xofftxc, 4686212902Sjhb "XOFF Transmitted"); 4687212902Sjhb 4688212902Sjhb /* Packet Reception Stats */ 4689217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd", 4690212902Sjhb CTLFLAG_RD, &adapter->stats.tpr, 4691212902Sjhb "Total Packets Received "); 4692217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd", 4693212902Sjhb CTLFLAG_RD, &adapter->stats.gprc, 4694212902Sjhb "Good Packets Received"); 4695217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd", 4696212902Sjhb CTLFLAG_RD, &adapter->stats.bprc, 4697212902Sjhb "Broadcast Packets Received"); 4698217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd", 4699212902Sjhb CTLFLAG_RD, &adapter->stats.mprc, 4700212902Sjhb "Multicast Packets Received"); 4701217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", 4702212902Sjhb CTLFLAG_RD, &adapter->stats.prc64, 4703212902Sjhb "64 byte frames received "); 4704217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", 4705212902Sjhb CTLFLAG_RD, &adapter->stats.prc127, 4706212902Sjhb "65-127 byte frames received"); 4707217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", 4708212902Sjhb CTLFLAG_RD, &adapter->stats.prc255, 4709212902Sjhb "128-255 byte frames received"); 4710217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", 4711212902Sjhb CTLFLAG_RD, &adapter->stats.prc511, 4712212902Sjhb "256-511 byte frames received"); 4713217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", 4714212902Sjhb CTLFLAG_RD, &adapter->stats.prc1023, 4715212902Sjhb "512-1023 byte frames received"); 4716217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", 4717212902Sjhb CTLFLAG_RD, &adapter->stats.prc1522, 4718212902Sjhb "1023-1522 byte frames received"); 4719217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd", 4720212902Sjhb CTLFLAG_RD, &adapter->stats.gorc, 4721212902Sjhb "Good Octets Received"); 4722212902Sjhb 4723212902Sjhb /* Packet Transmission Stats */ 4724217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 4725212902Sjhb CTLFLAG_RD, &adapter->stats.gotc, 4726212902Sjhb "Good Octets Transmitted"); 4727217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", 4728212902Sjhb CTLFLAG_RD, &adapter->stats.tpt, 4729212902Sjhb "Total Packets Transmitted"); 4730217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 4731212902Sjhb CTLFLAG_RD, &adapter->stats.gptc, 4732212902Sjhb "Good Packets Transmitted"); 4733217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 4734212902Sjhb CTLFLAG_RD, &adapter->stats.bptc, 4735212902Sjhb "Broadcast Packets Transmitted"); 4736217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 4737212902Sjhb CTLFLAG_RD, &adapter->stats.mptc, 4738212902Sjhb "Multicast Packets Transmitted"); 4739217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", 4740212902Sjhb CTLFLAG_RD, &adapter->stats.ptc64, 4741212902Sjhb "64 byte frames transmitted "); 4742217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", 4743212902Sjhb CTLFLAG_RD, &adapter->stats.ptc127, 4744212902Sjhb "65-127 byte frames transmitted"); 4745217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", 4746212902Sjhb CTLFLAG_RD, &adapter->stats.ptc255, 4747212902Sjhb "128-255 byte frames transmitted"); 4748217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", 4749212902Sjhb CTLFLAG_RD, &adapter->stats.ptc511, 4750212902Sjhb "256-511 byte frames transmitted"); 4751217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", 4752212902Sjhb CTLFLAG_RD, &adapter->stats.ptc1023, 4753212902Sjhb "512-1023 byte frames transmitted"); 4754217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", 4755212902Sjhb CTLFLAG_RD, &adapter->stats.ptc1522, 4756212902Sjhb "1024-1522 byte frames transmitted"); 4757217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_txd", 4758212902Sjhb CTLFLAG_RD, &adapter->stats.tsctc, 4759212902Sjhb "TSO Contexts Transmitted"); 4760217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail", 4761212902Sjhb CTLFLAG_RD, &adapter->stats.tsctfc, 4762212902Sjhb "TSO Contexts Failed"); 4763205869Sjfv} 4764205869Sjfv 4765205869Sjfv/********************************************************************** 4766205869Sjfv * 4767205869Sjfv * This routine provides a way to dump out the adapter eeprom, 4768205869Sjfv * often a useful debug/service tool. This only dumps the first 4769205869Sjfv * 32 words, stuff that matters is in that extent. 4770205869Sjfv * 4771205869Sjfv **********************************************************************/ 4772205869Sjfv 4773205869Sjfvstatic int 4774212902Sjhblem_sysctl_nvm_info(SYSCTL_HANDLER_ARGS) 4775205869Sjfv{ 4776205869Sjfv struct adapter *adapter; 4777205869Sjfv int error; 4778205869Sjfv int result; 4779205869Sjfv 4780205869Sjfv result = -1; 4781205869Sjfv error = sysctl_handle_int(oidp, &result, 0, req); 4782205869Sjfv 4783205869Sjfv if (error || !req->newptr) 4784205869Sjfv return (error); 4785205869Sjfv 4786205869Sjfv /* 4787205869Sjfv * This value will cause a hex dump of the 4788205869Sjfv * first 32 16-bit words of the EEPROM to 4789205869Sjfv * the screen. 4790205869Sjfv */ 4791212902Sjhb if (result == 1) { 4792205869Sjfv adapter = (struct adapter *)arg1; 4793205869Sjfv lem_print_nvm_info(adapter); 4794205869Sjfv } 4795205869Sjfv 4796205869Sjfv return (error); 4797205869Sjfv} 4798205869Sjfv 4799212902Sjhbstatic void 4800212902Sjhblem_print_nvm_info(struct adapter *adapter) 4801205869Sjfv{ 4802212902Sjhb u16 eeprom_data; 4803212902Sjhb int i, j, row = 0; 4804205869Sjfv 4805212902Sjhb /* Its a bit crude, but it gets the job done */ 4806212902Sjhb printf("\nInterface EEPROM Dump:\n"); 4807212902Sjhb printf("Offset\n0x0000 "); 4808212902Sjhb for (i = 0, j = 0; i < 32; i++, j++) { 4809212902Sjhb if (j == 8) { /* Make the offset block */ 4810212902Sjhb j = 0; ++row; 4811212902Sjhb printf("\n0x00%x0 ",row); 4812212902Sjhb } 4813212902Sjhb e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data); 4814212902Sjhb printf("%04x ", eeprom_data); 4815205869Sjfv } 4816212902Sjhb printf("\n"); 4817205869Sjfv} 4818205869Sjfv 4819205869Sjfvstatic int 4820205869Sjfvlem_sysctl_int_delay(SYSCTL_HANDLER_ARGS) 4821205869Sjfv{ 4822205869Sjfv struct em_int_delay_info *info; 4823205869Sjfv struct adapter *adapter; 4824205869Sjfv u32 regval; 4825205869Sjfv int error; 4826205869Sjfv int usecs; 4827205869Sjfv int ticks; 4828205869Sjfv 4829205869Sjfv info = (struct em_int_delay_info *)arg1; 4830205869Sjfv usecs = info->value; 4831205869Sjfv error = sysctl_handle_int(oidp, &usecs, 0, req); 4832205869Sjfv if (error != 0 || req->newptr == NULL) 4833205869Sjfv return (error); 4834205869Sjfv if (usecs < 0 || usecs > EM_TICKS_TO_USECS(65535)) 4835205869Sjfv return (EINVAL); 4836205869Sjfv info->value = usecs; 4837205869Sjfv ticks = EM_USECS_TO_TICKS(usecs); 4838250414Sluigi if (info->offset == E1000_ITR) /* units are 256ns here */ 4839250414Sluigi ticks *= 4; 4840205869Sjfv 4841205869Sjfv adapter = info->adapter; 4842205869Sjfv 4843205869Sjfv EM_CORE_LOCK(adapter); 4844205869Sjfv regval = E1000_READ_OFFSET(&adapter->hw, info->offset); 4845205869Sjfv regval = (regval & ~0xffff) | (ticks & 0xffff); 4846205869Sjfv /* Handle a few special cases. */ 4847205869Sjfv switch (info->offset) { 4848205869Sjfv case E1000_RDTR: 4849205869Sjfv break; 4850205869Sjfv case E1000_TIDV: 4851205869Sjfv if (ticks == 0) { 4852205869Sjfv adapter->txd_cmd &= ~E1000_TXD_CMD_IDE; 4853205869Sjfv /* Don't write 0 into the TIDV register. */ 4854205869Sjfv regval++; 4855205869Sjfv } else 4856205869Sjfv adapter->txd_cmd |= E1000_TXD_CMD_IDE; 4857205869Sjfv break; 4858205869Sjfv } 4859205869Sjfv E1000_WRITE_OFFSET(&adapter->hw, info->offset, regval); 4860205869Sjfv EM_CORE_UNLOCK(adapter); 4861205869Sjfv return (0); 4862205869Sjfv} 4863205869Sjfv 4864205869Sjfvstatic void 4865205869Sjfvlem_add_int_delay_sysctl(struct adapter *adapter, const char *name, 4866205869Sjfv const char *description, struct em_int_delay_info *info, 4867205869Sjfv int offset, int value) 4868205869Sjfv{ 4869205869Sjfv info->adapter = adapter; 4870205869Sjfv info->offset = offset; 4871205869Sjfv info->value = value; 4872205869Sjfv SYSCTL_ADD_PROC(device_get_sysctl_ctx(adapter->dev), 4873205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4874205869Sjfv OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, 4875205869Sjfv info, 0, lem_sysctl_int_delay, "I", description); 4876205869Sjfv} 4877205869Sjfv 4878214646Sjfvstatic void 4879214646Sjfvlem_set_flow_cntrl(struct adapter *adapter, const char *name, 4880214646Sjfv const char *description, int *limit, int value) 4881214646Sjfv{ 4882214646Sjfv *limit = value; 4883214646Sjfv SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 4884214646Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4885214646Sjfv OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); 4886214646Sjfv} 4887214646Sjfv 4888205869Sjfvstatic void 4889205869Sjfvlem_add_rx_process_limit(struct adapter *adapter, const char *name, 4890205869Sjfv const char *description, int *limit, int value) 4891205869Sjfv{ 4892205869Sjfv *limit = value; 4893205869Sjfv SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 4894205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4895205869Sjfv OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); 4896205869Sjfv} 4897