1205869Sjfv/****************************************************************************** 2205869Sjfv 3294958Smarius Copyright (c) 2001-2015, Intel Corporation 4205869Sjfv All rights reserved. 5205869Sjfv 6205869Sjfv Redistribution and use in source and binary forms, with or without 7205869Sjfv modification, are permitted provided that the following conditions are met: 8205869Sjfv 9205869Sjfv 1. Redistributions of source code must retain the above copyright notice, 10205869Sjfv this list of conditions and the following disclaimer. 11205869Sjfv 12205869Sjfv 2. Redistributions in binary form must reproduce the above copyright 13205869Sjfv notice, this list of conditions and the following disclaimer in the 14205869Sjfv documentation and/or other materials provided with the distribution. 15205869Sjfv 16205869Sjfv 3. Neither the name of the Intel Corporation nor the names of its 17205869Sjfv contributors may be used to endorse or promote products derived from 18205869Sjfv this software without specific prior written permission. 19205869Sjfv 20205869Sjfv THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21205869Sjfv AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22205869Sjfv IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23205869Sjfv ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24205869Sjfv LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25205869Sjfv CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26205869Sjfv SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27205869Sjfv INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28205869Sjfv CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29205869Sjfv ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30205869Sjfv POSSIBILITY OF SUCH DAMAGE. 31205869Sjfv 32205869Sjfv******************************************************************************/ 33205869Sjfv/*$FreeBSD: releng/10.3/sys/dev/e1000/if_lem.c 294958 2016-01-27 22:31:08Z marius $*/ 34205869Sjfv 35270252Sluigi/* 36270252Sluigi * Uncomment the following extensions for better performance in a VM, 37270252Sluigi * especially if you have support in the hypervisor. 38270252Sluigi * See http://info.iet.unipi.it/~luigi/netmap/ 39270252Sluigi */ 40270252Sluigi// #define BATCH_DISPATCH 41270252Sluigi// #define NIC_SEND_COMBINING 42270252Sluigi// #define NIC_PARAVIRT /* enable virtio-like synchronization */ 43270252Sluigi 44253303Sjfv#include "opt_inet.h" 45253303Sjfv#include "opt_inet6.h" 46253303Sjfv 47205869Sjfv#ifdef HAVE_KERNEL_OPTION_HEADERS 48205869Sjfv#include "opt_device_polling.h" 49205869Sjfv#endif 50205869Sjfv 51205869Sjfv#include <sys/param.h> 52205869Sjfv#include <sys/systm.h> 53205869Sjfv#include <sys/bus.h> 54205869Sjfv#include <sys/endian.h> 55205869Sjfv#include <sys/kernel.h> 56205869Sjfv#include <sys/kthread.h> 57205869Sjfv#include <sys/malloc.h> 58205869Sjfv#include <sys/mbuf.h> 59205869Sjfv#include <sys/module.h> 60205869Sjfv#include <sys/rman.h> 61205869Sjfv#include <sys/socket.h> 62205869Sjfv#include <sys/sockio.h> 63205869Sjfv#include <sys/sysctl.h> 64205869Sjfv#include <sys/taskqueue.h> 65205869Sjfv#include <sys/eventhandler.h> 66205869Sjfv#include <machine/bus.h> 67205869Sjfv#include <machine/resource.h> 68205869Sjfv 69205869Sjfv#include <net/bpf.h> 70205869Sjfv#include <net/ethernet.h> 71205869Sjfv#include <net/if.h> 72205869Sjfv#include <net/if_arp.h> 73205869Sjfv#include <net/if_dl.h> 74205869Sjfv#include <net/if_media.h> 75205869Sjfv 76205869Sjfv#include <net/if_types.h> 77205869Sjfv#include <net/if_vlan_var.h> 78205869Sjfv 79205869Sjfv#include <netinet/in_systm.h> 80205869Sjfv#include <netinet/in.h> 81205869Sjfv#include <netinet/if_ether.h> 82205869Sjfv#include <netinet/ip.h> 83205869Sjfv#include <netinet/ip6.h> 84205869Sjfv#include <netinet/tcp.h> 85205869Sjfv#include <netinet/udp.h> 86205869Sjfv 87205869Sjfv#include <machine/in_cksum.h> 88206001Smarius#include <dev/led/led.h> 89205869Sjfv#include <dev/pci/pcivar.h> 90205869Sjfv#include <dev/pci/pcireg.h> 91205869Sjfv 92205869Sjfv#include "e1000_api.h" 93205869Sjfv#include "if_lem.h" 94205869Sjfv 95205869Sjfv/********************************************************************* 96205869Sjfv * Legacy Em Driver version: 97205869Sjfv *********************************************************************/ 98294958Smariuschar lem_driver_version[] = "1.1.0"; 99205869Sjfv 100205869Sjfv/********************************************************************* 101205869Sjfv * PCI Device ID Table 102205869Sjfv * 103205869Sjfv * Used by probe to select devices to load on 104205869Sjfv * Last field stores an index into e1000_strings 105205869Sjfv * Last entry must be all 0s 106205869Sjfv * 107205869Sjfv * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 108205869Sjfv *********************************************************************/ 109205869Sjfv 110205869Sjfvstatic em_vendor_info_t lem_vendor_info_array[] = 111205869Sjfv{ 112205869Sjfv /* Intel(R) PRO/1000 Network Connection */ 113205869Sjfv { 0x8086, E1000_DEV_ID_82540EM, PCI_ANY_ID, PCI_ANY_ID, 0}, 114205869Sjfv { 0x8086, E1000_DEV_ID_82540EM_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 115205869Sjfv { 0x8086, E1000_DEV_ID_82540EP, PCI_ANY_ID, PCI_ANY_ID, 0}, 116205869Sjfv { 0x8086, E1000_DEV_ID_82540EP_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 117205869Sjfv { 0x8086, E1000_DEV_ID_82540EP_LP, PCI_ANY_ID, PCI_ANY_ID, 0}, 118205869Sjfv 119205869Sjfv { 0x8086, E1000_DEV_ID_82541EI, PCI_ANY_ID, PCI_ANY_ID, 0}, 120205869Sjfv { 0x8086, E1000_DEV_ID_82541ER, PCI_ANY_ID, PCI_ANY_ID, 0}, 121205869Sjfv { 0x8086, E1000_DEV_ID_82541ER_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 122205869Sjfv { 0x8086, E1000_DEV_ID_82541EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, 123205869Sjfv { 0x8086, E1000_DEV_ID_82541GI, PCI_ANY_ID, PCI_ANY_ID, 0}, 124205869Sjfv { 0x8086, E1000_DEV_ID_82541GI_LF, PCI_ANY_ID, PCI_ANY_ID, 0}, 125205869Sjfv { 0x8086, E1000_DEV_ID_82541GI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, 126205869Sjfv 127205869Sjfv { 0x8086, E1000_DEV_ID_82542, PCI_ANY_ID, PCI_ANY_ID, 0}, 128205869Sjfv 129205869Sjfv { 0x8086, E1000_DEV_ID_82543GC_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 130205869Sjfv { 0x8086, E1000_DEV_ID_82543GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 131205869Sjfv 132205869Sjfv { 0x8086, E1000_DEV_ID_82544EI_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 133205869Sjfv { 0x8086, E1000_DEV_ID_82544EI_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 134205869Sjfv { 0x8086, E1000_DEV_ID_82544GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 135205869Sjfv { 0x8086, E1000_DEV_ID_82544GC_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 136205869Sjfv 137205869Sjfv { 0x8086, E1000_DEV_ID_82545EM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 138205869Sjfv { 0x8086, E1000_DEV_ID_82545EM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 139205869Sjfv { 0x8086, E1000_DEV_ID_82545GM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 140205869Sjfv { 0x8086, E1000_DEV_ID_82545GM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 141205869Sjfv { 0x8086, E1000_DEV_ID_82545GM_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, 142205869Sjfv 143205869Sjfv { 0x8086, E1000_DEV_ID_82546EB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 144205869Sjfv { 0x8086, E1000_DEV_ID_82546EB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 145205869Sjfv { 0x8086, E1000_DEV_ID_82546EB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 146205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 147205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 148205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, 149205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_PCIE, PCI_ANY_ID, PCI_ANY_ID, 0}, 150205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 151205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3, 152205869Sjfv PCI_ANY_ID, PCI_ANY_ID, 0}, 153205869Sjfv 154205869Sjfv { 0x8086, E1000_DEV_ID_82547EI, PCI_ANY_ID, PCI_ANY_ID, 0}, 155205869Sjfv { 0x8086, E1000_DEV_ID_82547EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, 156205869Sjfv { 0x8086, E1000_DEV_ID_82547GI, PCI_ANY_ID, PCI_ANY_ID, 0}, 157205869Sjfv /* required last entry */ 158205869Sjfv { 0, 0, 0, 0, 0} 159205869Sjfv}; 160205869Sjfv 161205869Sjfv/********************************************************************* 162205869Sjfv * Table of branding strings for all supported NICs. 163205869Sjfv *********************************************************************/ 164205869Sjfv 165205869Sjfvstatic char *lem_strings[] = { 166205869Sjfv "Intel(R) PRO/1000 Legacy Network Connection" 167205869Sjfv}; 168205869Sjfv 169205869Sjfv/********************************************************************* 170205869Sjfv * Function prototypes 171205869Sjfv *********************************************************************/ 172205869Sjfvstatic int lem_probe(device_t); 173205869Sjfvstatic int lem_attach(device_t); 174205869Sjfvstatic int lem_detach(device_t); 175205869Sjfvstatic int lem_shutdown(device_t); 176205869Sjfvstatic int lem_suspend(device_t); 177205869Sjfvstatic int lem_resume(device_t); 178205869Sjfvstatic void lem_start(struct ifnet *); 179205869Sjfvstatic void lem_start_locked(struct ifnet *ifp); 180205869Sjfvstatic int lem_ioctl(struct ifnet *, u_long, caddr_t); 181205869Sjfvstatic void lem_init(void *); 182205869Sjfvstatic void lem_init_locked(struct adapter *); 183205869Sjfvstatic void lem_stop(void *); 184205869Sjfvstatic void lem_media_status(struct ifnet *, struct ifmediareq *); 185205869Sjfvstatic int lem_media_change(struct ifnet *); 186205869Sjfvstatic void lem_identify_hardware(struct adapter *); 187205869Sjfvstatic int lem_allocate_pci_resources(struct adapter *); 188205869Sjfvstatic int lem_allocate_irq(struct adapter *adapter); 189205869Sjfvstatic void lem_free_pci_resources(struct adapter *); 190205869Sjfvstatic void lem_local_timer(void *); 191205869Sjfvstatic int lem_hardware_init(struct adapter *); 192211907Syongaristatic int lem_setup_interface(device_t, struct adapter *); 193205869Sjfvstatic void lem_setup_transmit_structures(struct adapter *); 194205869Sjfvstatic void lem_initialize_transmit_unit(struct adapter *); 195205869Sjfvstatic int lem_setup_receive_structures(struct adapter *); 196205869Sjfvstatic void lem_initialize_receive_unit(struct adapter *); 197205869Sjfvstatic void lem_enable_intr(struct adapter *); 198205869Sjfvstatic void lem_disable_intr(struct adapter *); 199205869Sjfvstatic void lem_free_transmit_structures(struct adapter *); 200205869Sjfvstatic void lem_free_receive_structures(struct adapter *); 201205869Sjfvstatic void lem_update_stats_counters(struct adapter *); 202212902Sjhbstatic void lem_add_hw_stats(struct adapter *adapter); 203205869Sjfvstatic void lem_txeof(struct adapter *); 204205869Sjfvstatic void lem_tx_purge(struct adapter *); 205205869Sjfvstatic int lem_allocate_receive_structures(struct adapter *); 206205869Sjfvstatic int lem_allocate_transmit_structures(struct adapter *); 207209238Sjfvstatic bool lem_rxeof(struct adapter *, int, int *); 208205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 209205869Sjfvstatic int lem_fixup_rx(struct adapter *); 210205869Sjfv#endif 211205869Sjfvstatic void lem_receive_checksum(struct adapter *, struct e1000_rx_desc *, 212205869Sjfv struct mbuf *); 213205869Sjfvstatic void lem_transmit_checksum_setup(struct adapter *, struct mbuf *, 214205869Sjfv u32 *, u32 *); 215205869Sjfvstatic void lem_set_promisc(struct adapter *); 216205869Sjfvstatic void lem_disable_promisc(struct adapter *); 217205869Sjfvstatic void lem_set_multi(struct adapter *); 218205869Sjfvstatic void lem_update_link_status(struct adapter *); 219205869Sjfvstatic int lem_get_buf(struct adapter *, int); 220205869Sjfvstatic void lem_register_vlan(void *, struct ifnet *, u16); 221205869Sjfvstatic void lem_unregister_vlan(void *, struct ifnet *, u16); 222205869Sjfvstatic void lem_setup_vlan_hw_support(struct adapter *); 223205869Sjfvstatic int lem_xmit(struct adapter *, struct mbuf **); 224205869Sjfvstatic void lem_smartspeed(struct adapter *); 225205869Sjfvstatic int lem_82547_fifo_workaround(struct adapter *, int); 226205869Sjfvstatic void lem_82547_update_fifo_head(struct adapter *, int); 227205869Sjfvstatic int lem_82547_tx_fifo_reset(struct adapter *); 228205869Sjfvstatic void lem_82547_move_tail(void *); 229205869Sjfvstatic int lem_dma_malloc(struct adapter *, bus_size_t, 230205869Sjfv struct em_dma_alloc *, int); 231205869Sjfvstatic void lem_dma_free(struct adapter *, struct em_dma_alloc *); 232212902Sjhbstatic int lem_sysctl_nvm_info(SYSCTL_HANDLER_ARGS); 233205869Sjfvstatic void lem_print_nvm_info(struct adapter *); 234205869Sjfvstatic int lem_is_valid_ether_addr(u8 *); 235205869Sjfvstatic u32 lem_fill_descriptors (bus_addr_t address, u32 length, 236205869Sjfv PDESC_ARRAY desc_array); 237205869Sjfvstatic int lem_sysctl_int_delay(SYSCTL_HANDLER_ARGS); 238205869Sjfvstatic void lem_add_int_delay_sysctl(struct adapter *, const char *, 239205869Sjfv const char *, struct em_int_delay_info *, int, int); 240214646Sjfvstatic void lem_set_flow_cntrl(struct adapter *, const char *, 241214646Sjfv const char *, int *, int); 242205869Sjfv/* Management and WOL Support */ 243205869Sjfvstatic void lem_init_manageability(struct adapter *); 244205869Sjfvstatic void lem_release_manageability(struct adapter *); 245205869Sjfvstatic void lem_get_hw_control(struct adapter *); 246205869Sjfvstatic void lem_release_hw_control(struct adapter *); 247205869Sjfvstatic void lem_get_wakeup(device_t); 248205869Sjfvstatic void lem_enable_wakeup(device_t); 249205869Sjfvstatic int lem_enable_phy_wakeup(struct adapter *); 250206001Smariusstatic void lem_led_func(void *, int); 251205869Sjfv 252205869Sjfvstatic void lem_intr(void *); 253205869Sjfvstatic int lem_irq_fast(void *); 254205869Sjfvstatic void lem_handle_rxtx(void *context, int pending); 255205869Sjfvstatic void lem_handle_link(void *context, int pending); 256205869Sjfvstatic void lem_add_rx_process_limit(struct adapter *, const char *, 257205869Sjfv const char *, int *, int); 258205869Sjfv 259205869Sjfv#ifdef DEVICE_POLLING 260205987Sjfvstatic poll_handler_t lem_poll; 261205869Sjfv#endif /* POLLING */ 262205869Sjfv 263205869Sjfv/********************************************************************* 264205869Sjfv * FreeBSD Device Interface Entry Points 265205869Sjfv *********************************************************************/ 266205869Sjfv 267205869Sjfvstatic device_method_t lem_methods[] = { 268205869Sjfv /* Device interface */ 269205869Sjfv DEVMETHOD(device_probe, lem_probe), 270205869Sjfv DEVMETHOD(device_attach, lem_attach), 271205869Sjfv DEVMETHOD(device_detach, lem_detach), 272205869Sjfv DEVMETHOD(device_shutdown, lem_shutdown), 273205869Sjfv DEVMETHOD(device_suspend, lem_suspend), 274205869Sjfv DEVMETHOD(device_resume, lem_resume), 275246128Ssbz DEVMETHOD_END 276205869Sjfv}; 277205869Sjfv 278205869Sjfvstatic driver_t lem_driver = { 279205869Sjfv "em", lem_methods, sizeof(struct adapter), 280205869Sjfv}; 281205869Sjfv 282205869Sjfvextern devclass_t em_devclass; 283205869SjfvDRIVER_MODULE(lem, pci, lem_driver, em_devclass, 0, 0); 284205869SjfvMODULE_DEPEND(lem, pci, 1, 1, 1); 285205869SjfvMODULE_DEPEND(lem, ether, 1, 1, 1); 286205869Sjfv 287205869Sjfv/********************************************************************* 288205869Sjfv * Tunable default values. 289205869Sjfv *********************************************************************/ 290205869Sjfv 291205869Sjfv#define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) 292205869Sjfv#define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) 293205869Sjfv 294250414Sluigi#define MAX_INTS_PER_SEC 8000 295250414Sluigi#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) 296250414Sluigi 297205869Sjfvstatic int lem_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV); 298205869Sjfvstatic int lem_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR); 299205869Sjfvstatic int lem_tx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_TADV); 300205869Sjfvstatic int lem_rx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_RADV); 301270252Sluigi/* 302270252Sluigi * increase lem_rxd and lem_txd to at least 2048 in netmap mode 303270252Sluigi * for better performance. 304270252Sluigi */ 305205869Sjfvstatic int lem_rxd = EM_DEFAULT_RXD; 306205869Sjfvstatic int lem_txd = EM_DEFAULT_TXD; 307205869Sjfvstatic int lem_smart_pwr_down = FALSE; 308205869Sjfv 309205869Sjfv/* Controls whether promiscuous also shows bad packets */ 310205869Sjfvstatic int lem_debug_sbp = FALSE; 311205869Sjfv 312205869SjfvTUNABLE_INT("hw.em.tx_int_delay", &lem_tx_int_delay_dflt); 313205869SjfvTUNABLE_INT("hw.em.rx_int_delay", &lem_rx_int_delay_dflt); 314205869SjfvTUNABLE_INT("hw.em.tx_abs_int_delay", &lem_tx_abs_int_delay_dflt); 315205869SjfvTUNABLE_INT("hw.em.rx_abs_int_delay", &lem_rx_abs_int_delay_dflt); 316205869SjfvTUNABLE_INT("hw.em.rxd", &lem_rxd); 317205869SjfvTUNABLE_INT("hw.em.txd", &lem_txd); 318205869SjfvTUNABLE_INT("hw.em.smart_pwr_down", &lem_smart_pwr_down); 319205869SjfvTUNABLE_INT("hw.em.sbp", &lem_debug_sbp); 320205869Sjfv 321238953Sjfv/* Interrupt style - default to fast */ 322238953Sjfvstatic int lem_use_legacy_irq = 0; 323238953SjfvTUNABLE_INT("hw.em.use_legacy_irq", &lem_use_legacy_irq); 324238953Sjfv 325205869Sjfv/* How many packets rxeof tries to clean at a time */ 326205869Sjfvstatic int lem_rx_process_limit = 100; 327205869SjfvTUNABLE_INT("hw.em.rx_process_limit", &lem_rx_process_limit); 328205869Sjfv 329205869Sjfv/* Flow control setting - default to FULL */ 330205869Sjfvstatic int lem_fc_setting = e1000_fc_full; 331205869SjfvTUNABLE_INT("hw.em.fc_setting", &lem_fc_setting); 332205869Sjfv 333205869Sjfv/* Global used in WOL setup with multiport cards */ 334205869Sjfvstatic int global_quad_port_a = 0; 335205869Sjfv 336228281Sluigi#ifdef DEV_NETMAP /* see ixgbe.c for details */ 337228281Sluigi#include <dev/netmap/if_lem_netmap.h> 338228281Sluigi#endif /* DEV_NETMAP */ 339228281Sluigi 340205869Sjfv/********************************************************************* 341205869Sjfv * Device identification routine 342205869Sjfv * 343205869Sjfv * em_probe determines if the driver should be loaded on 344205869Sjfv * adapter based on PCI vendor/device id of the adapter. 345205869Sjfv * 346205869Sjfv * return BUS_PROBE_DEFAULT on success, positive on failure 347205869Sjfv *********************************************************************/ 348205869Sjfv 349205869Sjfvstatic int 350205869Sjfvlem_probe(device_t dev) 351205869Sjfv{ 352205869Sjfv char adapter_name[60]; 353205869Sjfv u16 pci_vendor_id = 0; 354205869Sjfv u16 pci_device_id = 0; 355205869Sjfv u16 pci_subvendor_id = 0; 356205869Sjfv u16 pci_subdevice_id = 0; 357205869Sjfv em_vendor_info_t *ent; 358205869Sjfv 359205869Sjfv INIT_DEBUGOUT("em_probe: begin"); 360205869Sjfv 361205869Sjfv pci_vendor_id = pci_get_vendor(dev); 362205869Sjfv if (pci_vendor_id != EM_VENDOR_ID) 363205869Sjfv return (ENXIO); 364205869Sjfv 365205869Sjfv pci_device_id = pci_get_device(dev); 366205869Sjfv pci_subvendor_id = pci_get_subvendor(dev); 367205869Sjfv pci_subdevice_id = pci_get_subdevice(dev); 368205869Sjfv 369205869Sjfv ent = lem_vendor_info_array; 370205869Sjfv while (ent->vendor_id != 0) { 371205869Sjfv if ((pci_vendor_id == ent->vendor_id) && 372205869Sjfv (pci_device_id == ent->device_id) && 373205869Sjfv 374205869Sjfv ((pci_subvendor_id == ent->subvendor_id) || 375205869Sjfv (ent->subvendor_id == PCI_ANY_ID)) && 376205869Sjfv 377205869Sjfv ((pci_subdevice_id == ent->subdevice_id) || 378205869Sjfv (ent->subdevice_id == PCI_ANY_ID))) { 379205869Sjfv sprintf(adapter_name, "%s %s", 380205869Sjfv lem_strings[ent->index], 381205869Sjfv lem_driver_version); 382205869Sjfv device_set_desc_copy(dev, adapter_name); 383205869Sjfv return (BUS_PROBE_DEFAULT); 384205869Sjfv } 385205869Sjfv ent++; 386205869Sjfv } 387205869Sjfv 388205869Sjfv return (ENXIO); 389205869Sjfv} 390205869Sjfv 391205869Sjfv/********************************************************************* 392205869Sjfv * Device initialization routine 393205869Sjfv * 394205869Sjfv * The attach entry point is called when the driver is being loaded. 395205869Sjfv * This routine identifies the type of hardware, allocates all resources 396205869Sjfv * and initializes the hardware. 397205869Sjfv * 398205869Sjfv * return 0 on success, positive on failure 399205869Sjfv *********************************************************************/ 400205869Sjfv 401205869Sjfvstatic int 402205869Sjfvlem_attach(device_t dev) 403205869Sjfv{ 404205869Sjfv struct adapter *adapter; 405205869Sjfv int tsize, rsize; 406205869Sjfv int error = 0; 407205869Sjfv 408205869Sjfv INIT_DEBUGOUT("lem_attach: begin"); 409205869Sjfv 410205869Sjfv adapter = device_get_softc(dev); 411205869Sjfv adapter->dev = adapter->osdep.dev = dev; 412205869Sjfv EM_CORE_LOCK_INIT(adapter, device_get_nameunit(dev)); 413205869Sjfv EM_TX_LOCK_INIT(adapter, device_get_nameunit(dev)); 414205869Sjfv EM_RX_LOCK_INIT(adapter, device_get_nameunit(dev)); 415205869Sjfv 416205869Sjfv /* SYSCTL stuff */ 417205869Sjfv SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 418205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 419212902Sjhb OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0, 420212902Sjhb lem_sysctl_nvm_info, "I", "NVM Information"); 421205869Sjfv 422205869Sjfv callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0); 423205869Sjfv callout_init_mtx(&adapter->tx_fifo_timer, &adapter->tx_mtx, 0); 424205869Sjfv 425205869Sjfv /* Determine hardware and mac info */ 426205869Sjfv lem_identify_hardware(adapter); 427205869Sjfv 428205869Sjfv /* Setup PCI resources */ 429205869Sjfv if (lem_allocate_pci_resources(adapter)) { 430205869Sjfv device_printf(dev, "Allocation of PCI resources failed\n"); 431205869Sjfv error = ENXIO; 432205869Sjfv goto err_pci; 433205869Sjfv } 434205869Sjfv 435205869Sjfv /* Do Shared Code initialization */ 436205869Sjfv if (e1000_setup_init_funcs(&adapter->hw, TRUE)) { 437205869Sjfv device_printf(dev, "Setup of Shared code failed\n"); 438205869Sjfv error = ENXIO; 439205869Sjfv goto err_pci; 440205869Sjfv } 441205869Sjfv 442205869Sjfv e1000_get_bus_info(&adapter->hw); 443205869Sjfv 444205869Sjfv /* Set up some sysctls for the tunable interrupt delays */ 445205869Sjfv lem_add_int_delay_sysctl(adapter, "rx_int_delay", 446205869Sjfv "receive interrupt delay in usecs", &adapter->rx_int_delay, 447205869Sjfv E1000_REGISTER(&adapter->hw, E1000_RDTR), lem_rx_int_delay_dflt); 448205869Sjfv lem_add_int_delay_sysctl(adapter, "tx_int_delay", 449205869Sjfv "transmit interrupt delay in usecs", &adapter->tx_int_delay, 450205869Sjfv E1000_REGISTER(&adapter->hw, E1000_TIDV), lem_tx_int_delay_dflt); 451205869Sjfv if (adapter->hw.mac.type >= e1000_82540) { 452205869Sjfv lem_add_int_delay_sysctl(adapter, "rx_abs_int_delay", 453205869Sjfv "receive interrupt delay limit in usecs", 454205869Sjfv &adapter->rx_abs_int_delay, 455205869Sjfv E1000_REGISTER(&adapter->hw, E1000_RADV), 456205869Sjfv lem_rx_abs_int_delay_dflt); 457205869Sjfv lem_add_int_delay_sysctl(adapter, "tx_abs_int_delay", 458205869Sjfv "transmit interrupt delay limit in usecs", 459205869Sjfv &adapter->tx_abs_int_delay, 460205869Sjfv E1000_REGISTER(&adapter->hw, E1000_TADV), 461205869Sjfv lem_tx_abs_int_delay_dflt); 462250414Sluigi lem_add_int_delay_sysctl(adapter, "itr", 463250414Sluigi "interrupt delay limit in usecs/4", 464250414Sluigi &adapter->tx_itr, 465250414Sluigi E1000_REGISTER(&adapter->hw, E1000_ITR), 466250414Sluigi DEFAULT_ITR); 467205869Sjfv } 468205869Sjfv 469205869Sjfv /* Sysctls for limiting the amount of work done in the taskqueue */ 470205869Sjfv lem_add_rx_process_limit(adapter, "rx_processing_limit", 471205869Sjfv "max number of rx packets to process", &adapter->rx_process_limit, 472205869Sjfv lem_rx_process_limit); 473205869Sjfv 474270252Sluigi#ifdef NIC_SEND_COMBINING 475270252Sluigi /* Sysctls to control mitigation */ 476270252Sluigi lem_add_rx_process_limit(adapter, "sc_enable", 477270252Sluigi "driver TDT mitigation", &adapter->sc_enable, 0); 478270252Sluigi#endif /* NIC_SEND_COMBINING */ 479270252Sluigi#ifdef BATCH_DISPATCH 480270252Sluigi lem_add_rx_process_limit(adapter, "batch_enable", 481270252Sluigi "driver rx batch", &adapter->batch_enable, 0); 482270252Sluigi#endif /* BATCH_DISPATCH */ 483270252Sluigi#ifdef NIC_PARAVIRT 484270252Sluigi lem_add_rx_process_limit(adapter, "rx_retries", 485270252Sluigi "driver rx retries", &adapter->rx_retries, 0); 486270252Sluigi#endif /* NIC_PARAVIRT */ 487270252Sluigi 488214646Sjfv /* Sysctl for setting the interface flow control */ 489214646Sjfv lem_set_flow_cntrl(adapter, "flow_control", 490228387Sjfv "flow control setting", 491214646Sjfv &adapter->fc_setting, lem_fc_setting); 492214646Sjfv 493205869Sjfv /* 494205869Sjfv * Validate number of transmit and receive descriptors. It 495205869Sjfv * must not exceed hardware maximum, and must be multiple 496205869Sjfv * of E1000_DBA_ALIGN. 497205869Sjfv */ 498205869Sjfv if (((lem_txd * sizeof(struct e1000_tx_desc)) % EM_DBA_ALIGN) != 0 || 499205869Sjfv (adapter->hw.mac.type >= e1000_82544 && lem_txd > EM_MAX_TXD) || 500205869Sjfv (adapter->hw.mac.type < e1000_82544 && lem_txd > EM_MAX_TXD_82543) || 501205869Sjfv (lem_txd < EM_MIN_TXD)) { 502205869Sjfv device_printf(dev, "Using %d TX descriptors instead of %d!\n", 503205869Sjfv EM_DEFAULT_TXD, lem_txd); 504205869Sjfv adapter->num_tx_desc = EM_DEFAULT_TXD; 505205869Sjfv } else 506205869Sjfv adapter->num_tx_desc = lem_txd; 507205869Sjfv if (((lem_rxd * sizeof(struct e1000_rx_desc)) % EM_DBA_ALIGN) != 0 || 508205869Sjfv (adapter->hw.mac.type >= e1000_82544 && lem_rxd > EM_MAX_RXD) || 509205869Sjfv (adapter->hw.mac.type < e1000_82544 && lem_rxd > EM_MAX_RXD_82543) || 510205869Sjfv (lem_rxd < EM_MIN_RXD)) { 511205869Sjfv device_printf(dev, "Using %d RX descriptors instead of %d!\n", 512205869Sjfv EM_DEFAULT_RXD, lem_rxd); 513205869Sjfv adapter->num_rx_desc = EM_DEFAULT_RXD; 514205869Sjfv } else 515205869Sjfv adapter->num_rx_desc = lem_rxd; 516205869Sjfv 517205869Sjfv adapter->hw.mac.autoneg = DO_AUTO_NEG; 518205869Sjfv adapter->hw.phy.autoneg_wait_to_complete = FALSE; 519205869Sjfv adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; 520205869Sjfv adapter->rx_buffer_len = 2048; 521205869Sjfv 522205869Sjfv e1000_init_script_state_82541(&adapter->hw, TRUE); 523205869Sjfv e1000_set_tbi_compatibility_82543(&adapter->hw, TRUE); 524205869Sjfv 525205869Sjfv /* Copper options */ 526205869Sjfv if (adapter->hw.phy.media_type == e1000_media_type_copper) { 527205869Sjfv adapter->hw.phy.mdix = AUTO_ALL_MODES; 528205869Sjfv adapter->hw.phy.disable_polarity_correction = FALSE; 529205869Sjfv adapter->hw.phy.ms_type = EM_MASTER_SLAVE; 530205869Sjfv } 531205869Sjfv 532205869Sjfv /* 533205869Sjfv * Set the frame limits assuming 534205869Sjfv * standard ethernet sized frames. 535205869Sjfv */ 536205869Sjfv adapter->max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE; 537205869Sjfv adapter->min_frame_size = ETH_ZLEN + ETHERNET_FCS_SIZE; 538205869Sjfv 539205869Sjfv /* 540205869Sjfv * This controls when hardware reports transmit completion 541205869Sjfv * status. 542205869Sjfv */ 543205869Sjfv adapter->hw.mac.report_tx_early = 1; 544205869Sjfv 545270252Sluigi#ifdef NIC_PARAVIRT 546270252Sluigi device_printf(dev, "driver supports paravirt, subdev 0x%x\n", 547270252Sluigi adapter->hw.subsystem_device_id); 548270252Sluigi if (adapter->hw.subsystem_device_id == E1000_PARA_SUBDEV) { 549270252Sluigi uint64_t bus_addr; 550270252Sluigi 551270252Sluigi device_printf(dev, "paravirt support on dev %p\n", adapter); 552270252Sluigi tsize = 4096; // XXX one page for the csb 553270252Sluigi if (lem_dma_malloc(adapter, tsize, &adapter->csb_mem, BUS_DMA_NOWAIT)) { 554270252Sluigi device_printf(dev, "Unable to allocate csb memory\n"); 555270252Sluigi error = ENOMEM; 556270252Sluigi goto err_csb; 557270252Sluigi } 558270252Sluigi /* Setup the Base of the CSB */ 559270252Sluigi adapter->csb = (struct paravirt_csb *)adapter->csb_mem.dma_vaddr; 560270252Sluigi /* force the first kick */ 561270252Sluigi adapter->csb->host_need_txkick = 1; /* txring empty */ 562270252Sluigi adapter->csb->guest_need_rxkick = 1; /* no rx packets */ 563270252Sluigi bus_addr = adapter->csb_mem.dma_paddr; 564270252Sluigi lem_add_rx_process_limit(adapter, "csb_on", 565270252Sluigi "enable paravirt.", &adapter->csb->guest_csb_on, 0); 566270252Sluigi lem_add_rx_process_limit(adapter, "txc_lim", 567270252Sluigi "txc_lim", &adapter->csb->host_txcycles_lim, 1); 568270252Sluigi 569270252Sluigi /* some stats */ 570270252Sluigi#define PA_SC(name, var, val) \ 571270252Sluigi lem_add_rx_process_limit(adapter, name, name, var, val) 572270252Sluigi PA_SC("host_need_txkick",&adapter->csb->host_need_txkick, 1); 573270252Sluigi PA_SC("host_rxkick_at",&adapter->csb->host_rxkick_at, ~0); 574270252Sluigi PA_SC("guest_need_txkick",&adapter->csb->guest_need_txkick, 0); 575270252Sluigi PA_SC("guest_need_rxkick",&adapter->csb->guest_need_rxkick, 1); 576270252Sluigi PA_SC("tdt_reg_count",&adapter->tdt_reg_count, 0); 577270252Sluigi PA_SC("tdt_csb_count",&adapter->tdt_csb_count, 0); 578270252Sluigi PA_SC("tdt_int_count",&adapter->tdt_int_count, 0); 579270252Sluigi PA_SC("guest_need_kick_count",&adapter->guest_need_kick_count, 0); 580270252Sluigi /* tell the host where the block is */ 581270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_CSBAH, 582270252Sluigi (u32)(bus_addr >> 32)); 583270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_CSBAL, 584270252Sluigi (u32)bus_addr); 585270252Sluigi } 586270252Sluigi#endif /* NIC_PARAVIRT */ 587270252Sluigi 588205869Sjfv tsize = roundup2(adapter->num_tx_desc * sizeof(struct e1000_tx_desc), 589205869Sjfv EM_DBA_ALIGN); 590205869Sjfv 591205869Sjfv /* Allocate Transmit Descriptor ring */ 592205869Sjfv if (lem_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) { 593205869Sjfv device_printf(dev, "Unable to allocate tx_desc memory\n"); 594205869Sjfv error = ENOMEM; 595205869Sjfv goto err_tx_desc; 596205869Sjfv } 597205869Sjfv adapter->tx_desc_base = 598205869Sjfv (struct e1000_tx_desc *)adapter->txdma.dma_vaddr; 599205869Sjfv 600205869Sjfv rsize = roundup2(adapter->num_rx_desc * sizeof(struct e1000_rx_desc), 601205869Sjfv EM_DBA_ALIGN); 602205869Sjfv 603205869Sjfv /* Allocate Receive Descriptor ring */ 604205869Sjfv if (lem_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) { 605205869Sjfv device_printf(dev, "Unable to allocate rx_desc memory\n"); 606205869Sjfv error = ENOMEM; 607205869Sjfv goto err_rx_desc; 608205869Sjfv } 609205869Sjfv adapter->rx_desc_base = 610205869Sjfv (struct e1000_rx_desc *)adapter->rxdma.dma_vaddr; 611205869Sjfv 612211913Syongari /* Allocate multicast array memory. */ 613211913Syongari adapter->mta = malloc(sizeof(u8) * ETH_ADDR_LEN * 614211913Syongari MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT); 615211913Syongari if (adapter->mta == NULL) { 616211913Syongari device_printf(dev, "Can not allocate multicast setup array\n"); 617211913Syongari error = ENOMEM; 618211913Syongari goto err_hw_init; 619211913Syongari } 620211913Syongari 621205869Sjfv /* 622205869Sjfv ** Start from a known state, this is 623205869Sjfv ** important in reading the nvm and 624205869Sjfv ** mac from that. 625205869Sjfv */ 626205869Sjfv e1000_reset_hw(&adapter->hw); 627205869Sjfv 628205869Sjfv /* Make sure we have a good EEPROM before we read from it */ 629205869Sjfv if (e1000_validate_nvm_checksum(&adapter->hw) < 0) { 630205869Sjfv /* 631205869Sjfv ** Some PCI-E parts fail the first check due to 632205869Sjfv ** the link being in sleep state, call it again, 633205869Sjfv ** if it fails a second time its a real issue. 634205869Sjfv */ 635205869Sjfv if (e1000_validate_nvm_checksum(&adapter->hw) < 0) { 636205869Sjfv device_printf(dev, 637205869Sjfv "The EEPROM Checksum Is Not Valid\n"); 638205869Sjfv error = EIO; 639205869Sjfv goto err_hw_init; 640205869Sjfv } 641205869Sjfv } 642205869Sjfv 643205869Sjfv /* Copy the permanent MAC address out of the EEPROM */ 644205869Sjfv if (e1000_read_mac_addr(&adapter->hw) < 0) { 645205869Sjfv device_printf(dev, "EEPROM read error while reading MAC" 646205869Sjfv " address\n"); 647205869Sjfv error = EIO; 648205869Sjfv goto err_hw_init; 649205869Sjfv } 650205869Sjfv 651205869Sjfv if (!lem_is_valid_ether_addr(adapter->hw.mac.addr)) { 652205869Sjfv device_printf(dev, "Invalid MAC address\n"); 653205869Sjfv error = EIO; 654205869Sjfv goto err_hw_init; 655205869Sjfv } 656205869Sjfv 657205869Sjfv /* Initialize the hardware */ 658205869Sjfv if (lem_hardware_init(adapter)) { 659205869Sjfv device_printf(dev, "Unable to initialize the hardware\n"); 660205869Sjfv error = EIO; 661205869Sjfv goto err_hw_init; 662205869Sjfv } 663205869Sjfv 664205869Sjfv /* Allocate transmit descriptors and buffers */ 665205869Sjfv if (lem_allocate_transmit_structures(adapter)) { 666205869Sjfv device_printf(dev, "Could not setup transmit structures\n"); 667205869Sjfv error = ENOMEM; 668205869Sjfv goto err_tx_struct; 669205869Sjfv } 670205869Sjfv 671205869Sjfv /* Allocate receive descriptors and buffers */ 672205869Sjfv if (lem_allocate_receive_structures(adapter)) { 673205869Sjfv device_printf(dev, "Could not setup receive structures\n"); 674205869Sjfv error = ENOMEM; 675205869Sjfv goto err_rx_struct; 676205869Sjfv } 677205869Sjfv 678205869Sjfv /* 679205869Sjfv ** Do interrupt configuration 680205869Sjfv */ 681205869Sjfv error = lem_allocate_irq(adapter); 682205869Sjfv if (error) 683205869Sjfv goto err_rx_struct; 684205869Sjfv 685205869Sjfv /* 686205869Sjfv * Get Wake-on-Lan and Management info for later use 687205869Sjfv */ 688205869Sjfv lem_get_wakeup(dev); 689205869Sjfv 690205869Sjfv /* Setup OS specific network interface */ 691211907Syongari if (lem_setup_interface(dev, adapter) != 0) 692211907Syongari goto err_rx_struct; 693205869Sjfv 694205869Sjfv /* Initialize statistics */ 695205869Sjfv lem_update_stats_counters(adapter); 696205869Sjfv 697205869Sjfv adapter->hw.mac.get_link_status = 1; 698205869Sjfv lem_update_link_status(adapter); 699205869Sjfv 700205869Sjfv /* Indicate SOL/IDER usage */ 701205869Sjfv if (e1000_check_reset_block(&adapter->hw)) 702205869Sjfv device_printf(dev, 703205869Sjfv "PHY reset is blocked due to SOL/IDER session.\n"); 704205869Sjfv 705205869Sjfv /* Do we need workaround for 82544 PCI-X adapter? */ 706205869Sjfv if (adapter->hw.bus.type == e1000_bus_type_pcix && 707205869Sjfv adapter->hw.mac.type == e1000_82544) 708205869Sjfv adapter->pcix_82544 = TRUE; 709205869Sjfv else 710205869Sjfv adapter->pcix_82544 = FALSE; 711205869Sjfv 712205869Sjfv /* Register for VLAN events */ 713205869Sjfv adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 714205869Sjfv lem_register_vlan, adapter, EVENTHANDLER_PRI_FIRST); 715205869Sjfv adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 716205869Sjfv lem_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST); 717205869Sjfv 718212902Sjhb lem_add_hw_stats(adapter); 719212902Sjhb 720205869Sjfv /* Non-AMT based hardware can now take control from firmware */ 721205869Sjfv if (adapter->has_manage && !adapter->has_amt) 722205869Sjfv lem_get_hw_control(adapter); 723205869Sjfv 724205869Sjfv /* Tell the stack that the interface is not active */ 725205869Sjfv adapter->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 726205869Sjfv 727206001Smarius adapter->led_dev = led_create(lem_led_func, adapter, 728206001Smarius device_get_nameunit(dev)); 729206001Smarius 730228281Sluigi#ifdef DEV_NETMAP 731228281Sluigi lem_netmap_attach(adapter); 732228281Sluigi#endif /* DEV_NETMAP */ 733205869Sjfv INIT_DEBUGOUT("lem_attach: end"); 734205869Sjfv 735205869Sjfv return (0); 736205869Sjfv 737205869Sjfverr_rx_struct: 738205869Sjfv lem_free_transmit_structures(adapter); 739205869Sjfverr_tx_struct: 740205869Sjfverr_hw_init: 741205869Sjfv lem_release_hw_control(adapter); 742205869Sjfv lem_dma_free(adapter, &adapter->rxdma); 743205869Sjfverr_rx_desc: 744205869Sjfv lem_dma_free(adapter, &adapter->txdma); 745205869Sjfverr_tx_desc: 746270252Sluigi#ifdef NIC_PARAVIRT 747270252Sluigi lem_dma_free(adapter, &adapter->csb_mem); 748270252Sluigierr_csb: 749270252Sluigi#endif /* NIC_PARAVIRT */ 750270252Sluigi 751205869Sjfverr_pci: 752211907Syongari if (adapter->ifp != NULL) 753211907Syongari if_free(adapter->ifp); 754205869Sjfv lem_free_pci_resources(adapter); 755211913Syongari free(adapter->mta, M_DEVBUF); 756205869Sjfv EM_TX_LOCK_DESTROY(adapter); 757205869Sjfv EM_RX_LOCK_DESTROY(adapter); 758205869Sjfv EM_CORE_LOCK_DESTROY(adapter); 759205869Sjfv 760205869Sjfv return (error); 761205869Sjfv} 762205869Sjfv 763205869Sjfv/********************************************************************* 764205869Sjfv * Device removal routine 765205869Sjfv * 766205869Sjfv * The detach entry point is called when the driver is being removed. 767205869Sjfv * This routine stops the adapter and deallocates all the resources 768205869Sjfv * that were allocated for driver operation. 769205869Sjfv * 770205869Sjfv * return 0 on success, positive on failure 771205869Sjfv *********************************************************************/ 772205869Sjfv 773205869Sjfvstatic int 774205869Sjfvlem_detach(device_t dev) 775205869Sjfv{ 776205869Sjfv struct adapter *adapter = device_get_softc(dev); 777205869Sjfv struct ifnet *ifp = adapter->ifp; 778205869Sjfv 779205869Sjfv INIT_DEBUGOUT("em_detach: begin"); 780205869Sjfv 781205869Sjfv /* Make sure VLANS are not using driver */ 782205869Sjfv if (adapter->ifp->if_vlantrunk != NULL) { 783205869Sjfv device_printf(dev,"Vlan in use, detach first\n"); 784205869Sjfv return (EBUSY); 785205869Sjfv } 786205869Sjfv 787205869Sjfv#ifdef DEVICE_POLLING 788205869Sjfv if (ifp->if_capenable & IFCAP_POLLING) 789205869Sjfv ether_poll_deregister(ifp); 790205869Sjfv#endif 791205869Sjfv 792206001Smarius if (adapter->led_dev != NULL) 793206001Smarius led_destroy(adapter->led_dev); 794206001Smarius 795205869Sjfv EM_CORE_LOCK(adapter); 796205869Sjfv EM_TX_LOCK(adapter); 797205869Sjfv adapter->in_detach = 1; 798205869Sjfv lem_stop(adapter); 799205869Sjfv e1000_phy_hw_reset(&adapter->hw); 800205869Sjfv 801205869Sjfv lem_release_manageability(adapter); 802205869Sjfv 803205869Sjfv EM_TX_UNLOCK(adapter); 804205869Sjfv EM_CORE_UNLOCK(adapter); 805205869Sjfv 806205869Sjfv /* Unregister VLAN events */ 807205869Sjfv if (adapter->vlan_attach != NULL) 808205869Sjfv EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach); 809205869Sjfv if (adapter->vlan_detach != NULL) 810205869Sjfv EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); 811205869Sjfv 812205869Sjfv ether_ifdetach(adapter->ifp); 813205869Sjfv callout_drain(&adapter->timer); 814205869Sjfv callout_drain(&adapter->tx_fifo_timer); 815205869Sjfv 816228281Sluigi#ifdef DEV_NETMAP 817228281Sluigi netmap_detach(ifp); 818228281Sluigi#endif /* DEV_NETMAP */ 819205869Sjfv lem_free_pci_resources(adapter); 820205869Sjfv bus_generic_detach(dev); 821205869Sjfv if_free(ifp); 822205869Sjfv 823205869Sjfv lem_free_transmit_structures(adapter); 824205869Sjfv lem_free_receive_structures(adapter); 825205869Sjfv 826205869Sjfv /* Free Transmit Descriptor ring */ 827205869Sjfv if (adapter->tx_desc_base) { 828205869Sjfv lem_dma_free(adapter, &adapter->txdma); 829205869Sjfv adapter->tx_desc_base = NULL; 830205869Sjfv } 831205869Sjfv 832205869Sjfv /* Free Receive Descriptor ring */ 833205869Sjfv if (adapter->rx_desc_base) { 834205869Sjfv lem_dma_free(adapter, &adapter->rxdma); 835205869Sjfv adapter->rx_desc_base = NULL; 836205869Sjfv } 837205869Sjfv 838270252Sluigi#ifdef NIC_PARAVIRT 839270252Sluigi if (adapter->csb) { 840270252Sluigi lem_dma_free(adapter, &adapter->csb_mem); 841270252Sluigi adapter->csb = NULL; 842270252Sluigi } 843270252Sluigi#endif /* NIC_PARAVIRT */ 844205869Sjfv lem_release_hw_control(adapter); 845211913Syongari free(adapter->mta, M_DEVBUF); 846205869Sjfv EM_TX_LOCK_DESTROY(adapter); 847205869Sjfv EM_RX_LOCK_DESTROY(adapter); 848205869Sjfv EM_CORE_LOCK_DESTROY(adapter); 849205869Sjfv 850205869Sjfv return (0); 851205869Sjfv} 852205869Sjfv 853205869Sjfv/********************************************************************* 854205869Sjfv * 855205869Sjfv * Shutdown entry point 856205869Sjfv * 857205869Sjfv **********************************************************************/ 858205869Sjfv 859205869Sjfvstatic int 860205869Sjfvlem_shutdown(device_t dev) 861205869Sjfv{ 862205869Sjfv return lem_suspend(dev); 863205869Sjfv} 864205869Sjfv 865205869Sjfv/* 866205869Sjfv * Suspend/resume device methods. 867205869Sjfv */ 868205869Sjfvstatic int 869205869Sjfvlem_suspend(device_t dev) 870205869Sjfv{ 871205869Sjfv struct adapter *adapter = device_get_softc(dev); 872205869Sjfv 873205869Sjfv EM_CORE_LOCK(adapter); 874205869Sjfv 875205869Sjfv lem_release_manageability(adapter); 876205869Sjfv lem_release_hw_control(adapter); 877205869Sjfv lem_enable_wakeup(dev); 878205869Sjfv 879205869Sjfv EM_CORE_UNLOCK(adapter); 880205869Sjfv 881205869Sjfv return bus_generic_suspend(dev); 882205869Sjfv} 883205869Sjfv 884205869Sjfvstatic int 885205869Sjfvlem_resume(device_t dev) 886205869Sjfv{ 887205869Sjfv struct adapter *adapter = device_get_softc(dev); 888205869Sjfv struct ifnet *ifp = adapter->ifp; 889205869Sjfv 890205869Sjfv EM_CORE_LOCK(adapter); 891205869Sjfv lem_init_locked(adapter); 892205869Sjfv lem_init_manageability(adapter); 893205869Sjfv EM_CORE_UNLOCK(adapter); 894205869Sjfv lem_start(ifp); 895205869Sjfv 896205869Sjfv return bus_generic_resume(dev); 897205869Sjfv} 898205869Sjfv 899205869Sjfv 900205869Sjfvstatic void 901205869Sjfvlem_start_locked(struct ifnet *ifp) 902205869Sjfv{ 903205869Sjfv struct adapter *adapter = ifp->if_softc; 904205869Sjfv struct mbuf *m_head; 905205869Sjfv 906205869Sjfv EM_TX_LOCK_ASSERT(adapter); 907205869Sjfv 908205869Sjfv if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) != 909205869Sjfv IFF_DRV_RUNNING) 910205869Sjfv return; 911205869Sjfv if (!adapter->link_active) 912205869Sjfv return; 913205869Sjfv 914214646Sjfv /* 915214646Sjfv * Force a cleanup if number of TX descriptors 916214646Sjfv * available hits the threshold 917214646Sjfv */ 918214646Sjfv if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) { 919214646Sjfv lem_txeof(adapter); 920214646Sjfv /* Now do we at least have a minimal? */ 921214646Sjfv if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) { 922214646Sjfv adapter->no_tx_desc_avail1++; 923214646Sjfv return; 924214646Sjfv } 925214646Sjfv } 926214646Sjfv 927205869Sjfv while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 928205869Sjfv 929205869Sjfv IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 930205869Sjfv if (m_head == NULL) 931205869Sjfv break; 932205869Sjfv /* 933205869Sjfv * Encapsulation can modify our pointer, and or make it 934205869Sjfv * NULL on failure. In that event, we can't requeue. 935205869Sjfv */ 936205869Sjfv if (lem_xmit(adapter, &m_head)) { 937205869Sjfv if (m_head == NULL) 938205869Sjfv break; 939205869Sjfv ifp->if_drv_flags |= IFF_DRV_OACTIVE; 940205869Sjfv IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 941205869Sjfv break; 942205869Sjfv } 943205869Sjfv 944205869Sjfv /* Send a copy of the frame to the BPF listener */ 945205869Sjfv ETHER_BPF_MTAP(ifp, m_head); 946205869Sjfv 947205869Sjfv /* Set timeout in case hardware has problems transmitting. */ 948205869Sjfv adapter->watchdog_check = TRUE; 949206614Sjfv adapter->watchdog_time = ticks; 950205869Sjfv } 951205869Sjfv if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) 952205869Sjfv ifp->if_drv_flags |= IFF_DRV_OACTIVE; 953270252Sluigi#ifdef NIC_PARAVIRT 954289386Sadrian if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) && adapter->csb && 955270252Sluigi adapter->csb->guest_csb_on && 956270252Sluigi !(adapter->csb->guest_need_txkick & 1)) { 957270252Sluigi adapter->csb->guest_need_txkick = 1; 958270252Sluigi adapter->guest_need_kick_count++; 959270252Sluigi // XXX memory barrier 960270252Sluigi lem_txeof(adapter); // XXX possibly clear IFF_DRV_OACTIVE 961270252Sluigi } 962270252Sluigi#endif /* NIC_PARAVIRT */ 963205869Sjfv 964205869Sjfv return; 965205869Sjfv} 966205869Sjfv 967205869Sjfvstatic void 968205869Sjfvlem_start(struct ifnet *ifp) 969205869Sjfv{ 970205869Sjfv struct adapter *adapter = ifp->if_softc; 971205869Sjfv 972205869Sjfv EM_TX_LOCK(adapter); 973205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) 974205869Sjfv lem_start_locked(ifp); 975205869Sjfv EM_TX_UNLOCK(adapter); 976205869Sjfv} 977205869Sjfv 978205869Sjfv/********************************************************************* 979205869Sjfv * Ioctl entry point 980205869Sjfv * 981205869Sjfv * em_ioctl is called when the user wants to configure the 982205869Sjfv * interface. 983205869Sjfv * 984205869Sjfv * return 0 on success, positive on failure 985205869Sjfv **********************************************************************/ 986205869Sjfv 987205869Sjfvstatic int 988205869Sjfvlem_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 989205869Sjfv{ 990205869Sjfv struct adapter *adapter = ifp->if_softc; 991228387Sjfv struct ifreq *ifr = (struct ifreq *)data; 992228387Sjfv#if defined(INET) || defined(INET6) 993228387Sjfv struct ifaddr *ifa = (struct ifaddr *)data; 994205869Sjfv#endif 995228387Sjfv bool avoid_reset = FALSE; 996228387Sjfv int error = 0; 997205869Sjfv 998205869Sjfv if (adapter->in_detach) 999205869Sjfv return (error); 1000205869Sjfv 1001205869Sjfv switch (command) { 1002205869Sjfv case SIOCSIFADDR: 1003205869Sjfv#ifdef INET 1004228387Sjfv if (ifa->ifa_addr->sa_family == AF_INET) 1005228387Sjfv avoid_reset = TRUE; 1006228387Sjfv#endif 1007228387Sjfv#ifdef INET6 1008228387Sjfv if (ifa->ifa_addr->sa_family == AF_INET6) 1009228387Sjfv avoid_reset = TRUE; 1010228387Sjfv#endif 1011228387Sjfv /* 1012228387Sjfv ** Calling init results in link renegotiation, 1013228387Sjfv ** so we avoid doing it when possible. 1014228387Sjfv */ 1015228387Sjfv if (avoid_reset) { 1016205869Sjfv ifp->if_flags |= IFF_UP; 1017228387Sjfv if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 1018228387Sjfv lem_init(adapter); 1019228387Sjfv#ifdef INET 1020228387Sjfv if (!(ifp->if_flags & IFF_NOARP)) 1021228387Sjfv arp_ifinit(ifp, ifa); 1022228387Sjfv#endif 1023205869Sjfv } else 1024205869Sjfv error = ether_ioctl(ifp, command, data); 1025205869Sjfv break; 1026205869Sjfv case SIOCSIFMTU: 1027205869Sjfv { 1028205869Sjfv int max_frame_size; 1029205869Sjfv 1030205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); 1031205869Sjfv 1032205869Sjfv EM_CORE_LOCK(adapter); 1033205869Sjfv switch (adapter->hw.mac.type) { 1034205869Sjfv case e1000_82542: 1035205869Sjfv max_frame_size = ETHER_MAX_LEN; 1036205869Sjfv break; 1037205869Sjfv default: 1038205869Sjfv max_frame_size = MAX_JUMBO_FRAME_SIZE; 1039205869Sjfv } 1040205869Sjfv if (ifr->ifr_mtu > max_frame_size - ETHER_HDR_LEN - 1041205869Sjfv ETHER_CRC_LEN) { 1042205869Sjfv EM_CORE_UNLOCK(adapter); 1043205869Sjfv error = EINVAL; 1044205869Sjfv break; 1045205869Sjfv } 1046205869Sjfv 1047205869Sjfv ifp->if_mtu = ifr->ifr_mtu; 1048205869Sjfv adapter->max_frame_size = 1049205869Sjfv ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 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 1673294958Smarius m = m_collapse(*m_headp, M_NOWAIT, EM_MAX_SCATTER); 1674205869Sjfv if (m == NULL) { 1675294958Smarius adapter->mbuf_defrag_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_tag = NULL; 2703205869Sjfv 2704205869Sjfv return (error); 2705205869Sjfv} 2706205869Sjfv 2707205869Sjfvstatic void 2708205869Sjfvlem_dma_free(struct adapter *adapter, struct em_dma_alloc *dma) 2709205869Sjfv{ 2710205869Sjfv if (dma->dma_tag == NULL) 2711205869Sjfv return; 2712294958Smarius if (dma->dma_paddr != 0) { 2713205869Sjfv bus_dmamap_sync(dma->dma_tag, dma->dma_map, 2714205869Sjfv BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2715205869Sjfv bus_dmamap_unload(dma->dma_tag, dma->dma_map); 2716294958Smarius dma->dma_paddr = 0; 2717294958Smarius } 2718294958Smarius if (dma->dma_vaddr != NULL) { 2719205869Sjfv bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 2720294958Smarius dma->dma_vaddr = NULL; 2721205869Sjfv } 2722205869Sjfv bus_dma_tag_destroy(dma->dma_tag); 2723205869Sjfv dma->dma_tag = NULL; 2724205869Sjfv} 2725205869Sjfv 2726205869Sjfv 2727205869Sjfv/********************************************************************* 2728205869Sjfv * 2729205869Sjfv * Allocate memory for tx_buffer structures. The tx_buffer stores all 2730205869Sjfv * the information needed to transmit a packet on the wire. 2731205869Sjfv * 2732205869Sjfv **********************************************************************/ 2733205869Sjfvstatic int 2734205869Sjfvlem_allocate_transmit_structures(struct adapter *adapter) 2735205869Sjfv{ 2736205869Sjfv device_t dev = adapter->dev; 2737205869Sjfv struct em_buffer *tx_buffer; 2738205869Sjfv int error; 2739205869Sjfv 2740205869Sjfv /* 2741205869Sjfv * Create DMA tags for tx descriptors 2742205869Sjfv */ 2743205869Sjfv if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 2744205869Sjfv 1, 0, /* alignment, bounds */ 2745205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 2746205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 2747205869Sjfv NULL, NULL, /* filter, filterarg */ 2748214646Sjfv MCLBYTES * EM_MAX_SCATTER, /* maxsize */ 2749205869Sjfv EM_MAX_SCATTER, /* nsegments */ 2750214646Sjfv MCLBYTES, /* maxsegsize */ 2751205869Sjfv 0, /* flags */ 2752214646Sjfv NULL, /* lockfunc */ 2753214646Sjfv NULL, /* lockarg */ 2754205869Sjfv &adapter->txtag)) != 0) { 2755205869Sjfv device_printf(dev, "Unable to allocate TX DMA tag\n"); 2756205869Sjfv goto fail; 2757205869Sjfv } 2758205869Sjfv 2759205869Sjfv adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) * 2760205869Sjfv adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); 2761205869Sjfv if (adapter->tx_buffer_area == NULL) { 2762205869Sjfv device_printf(dev, "Unable to allocate tx_buffer memory\n"); 2763205869Sjfv error = ENOMEM; 2764205869Sjfv goto fail; 2765205869Sjfv } 2766205869Sjfv 2767205869Sjfv /* Create the descriptor buffer dma maps */ 2768205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++) { 2769205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2770205869Sjfv error = bus_dmamap_create(adapter->txtag, 0, &tx_buffer->map); 2771205869Sjfv if (error != 0) { 2772205869Sjfv device_printf(dev, "Unable to create TX DMA map\n"); 2773205869Sjfv goto fail; 2774205869Sjfv } 2775205869Sjfv tx_buffer->next_eop = -1; 2776205869Sjfv } 2777205869Sjfv 2778205869Sjfv return (0); 2779205869Sjfvfail: 2780205869Sjfv lem_free_transmit_structures(adapter); 2781205869Sjfv return (error); 2782205869Sjfv} 2783205869Sjfv 2784205869Sjfv/********************************************************************* 2785205869Sjfv * 2786205869Sjfv * (Re)Initialize transmit structures. 2787205869Sjfv * 2788205869Sjfv **********************************************************************/ 2789205869Sjfvstatic void 2790205869Sjfvlem_setup_transmit_structures(struct adapter *adapter) 2791205869Sjfv{ 2792205869Sjfv struct em_buffer *tx_buffer; 2793228281Sluigi#ifdef DEV_NETMAP 2794228281Sluigi /* we are already locked */ 2795228281Sluigi struct netmap_adapter *na = NA(adapter->ifp); 2796228281Sluigi struct netmap_slot *slot = netmap_reset(na, NR_TX, 0, 0); 2797228281Sluigi#endif /* DEV_NETMAP */ 2798205869Sjfv 2799205869Sjfv /* Clear the old ring contents */ 2800205869Sjfv bzero(adapter->tx_desc_base, 2801205869Sjfv (sizeof(struct e1000_tx_desc)) * adapter->num_tx_desc); 2802205869Sjfv 2803205869Sjfv /* Free any existing TX buffers */ 2804205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) { 2805205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2806205869Sjfv bus_dmamap_sync(adapter->txtag, tx_buffer->map, 2807205869Sjfv BUS_DMASYNC_POSTWRITE); 2808205869Sjfv bus_dmamap_unload(adapter->txtag, tx_buffer->map); 2809205869Sjfv m_freem(tx_buffer->m_head); 2810205869Sjfv tx_buffer->m_head = NULL; 2811228281Sluigi#ifdef DEV_NETMAP 2812228281Sluigi if (slot) { 2813231796Sluigi /* the i-th NIC entry goes to slot si */ 2814232238Sluigi int si = netmap_idx_n2k(&na->tx_rings[0], i); 2815229939Sluigi uint64_t paddr; 2816228281Sluigi void *addr; 2817228281Sluigi 2818270252Sluigi addr = PNMB(na, slot + si, &paddr); 2819270235Sluigi adapter->tx_desc_base[i].buffer_addr = htole64(paddr); 2820228281Sluigi /* reload the map for netmap mode */ 2821270252Sluigi netmap_load_map(na, adapter->txtag, tx_buffer->map, addr); 2822228281Sluigi } 2823228281Sluigi#endif /* DEV_NETMAP */ 2824205869Sjfv tx_buffer->next_eop = -1; 2825205869Sjfv } 2826205869Sjfv 2827205869Sjfv /* Reset state */ 2828225640Srstone adapter->last_hw_offload = 0; 2829205869Sjfv adapter->next_avail_tx_desc = 0; 2830205869Sjfv adapter->next_tx_to_clean = 0; 2831205869Sjfv adapter->num_tx_desc_avail = adapter->num_tx_desc; 2832205869Sjfv 2833205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 2834205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2835205869Sjfv 2836205869Sjfv return; 2837205869Sjfv} 2838205869Sjfv 2839205869Sjfv/********************************************************************* 2840205869Sjfv * 2841205869Sjfv * Enable transmit unit. 2842205869Sjfv * 2843205869Sjfv **********************************************************************/ 2844205869Sjfvstatic void 2845205869Sjfvlem_initialize_transmit_unit(struct adapter *adapter) 2846205869Sjfv{ 2847205869Sjfv u32 tctl, tipg = 0; 2848205869Sjfv u64 bus_addr; 2849205869Sjfv 2850205869Sjfv INIT_DEBUGOUT("lem_initialize_transmit_unit: begin"); 2851205869Sjfv /* Setup the Base and Length of the Tx Descriptor Ring */ 2852205869Sjfv bus_addr = adapter->txdma.dma_paddr; 2853205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDLEN(0), 2854205869Sjfv adapter->num_tx_desc * sizeof(struct e1000_tx_desc)); 2855205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDBAH(0), 2856205869Sjfv (u32)(bus_addr >> 32)); 2857205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDBAL(0), 2858205869Sjfv (u32)bus_addr); 2859205869Sjfv /* Setup the HW Tx Head and Tail descriptor pointers */ 2860205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0); 2861205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDH(0), 0); 2862205869Sjfv 2863205869Sjfv HW_DEBUGOUT2("Base = %x, Length = %x\n", 2864205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDBAL(0)), 2865205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDLEN(0))); 2866205869Sjfv 2867205869Sjfv /* Set the default values for the Tx Inter Packet Gap timer */ 2868205869Sjfv switch (adapter->hw.mac.type) { 2869205869Sjfv case e1000_82542: 2870205869Sjfv tipg = DEFAULT_82542_TIPG_IPGT; 2871205869Sjfv tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 2872205869Sjfv tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 2873205869Sjfv break; 2874205869Sjfv default: 2875205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 2876205869Sjfv (adapter->hw.phy.media_type == 2877205869Sjfv e1000_media_type_internal_serdes)) 2878205869Sjfv tipg = DEFAULT_82543_TIPG_IPGT_FIBER; 2879205869Sjfv else 2880205869Sjfv tipg = DEFAULT_82543_TIPG_IPGT_COPPER; 2881205869Sjfv tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 2882205869Sjfv tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 2883205869Sjfv } 2884205869Sjfv 2885205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TIPG, tipg); 2886205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TIDV, adapter->tx_int_delay.value); 2887205869Sjfv if(adapter->hw.mac.type >= e1000_82540) 2888205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TADV, 2889205869Sjfv adapter->tx_abs_int_delay.value); 2890205869Sjfv 2891205869Sjfv /* Program the Transmit Control Register */ 2892205869Sjfv tctl = E1000_READ_REG(&adapter->hw, E1000_TCTL); 2893205869Sjfv tctl &= ~E1000_TCTL_CT; 2894205869Sjfv tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN | 2895205869Sjfv (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); 2896205869Sjfv 2897205869Sjfv /* This write will effectively turn on the transmit unit. */ 2898205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); 2899205869Sjfv 2900205869Sjfv /* Setup Transmit Descriptor Base Settings */ 2901205869Sjfv adapter->txd_cmd = E1000_TXD_CMD_IFCS; 2902205869Sjfv 2903205869Sjfv if (adapter->tx_int_delay.value > 0) 2904205869Sjfv adapter->txd_cmd |= E1000_TXD_CMD_IDE; 2905205869Sjfv} 2906205869Sjfv 2907205869Sjfv/********************************************************************* 2908205869Sjfv * 2909205869Sjfv * Free all transmit related data structures. 2910205869Sjfv * 2911205869Sjfv **********************************************************************/ 2912205869Sjfvstatic void 2913205869Sjfvlem_free_transmit_structures(struct adapter *adapter) 2914205869Sjfv{ 2915205869Sjfv struct em_buffer *tx_buffer; 2916205869Sjfv 2917205869Sjfv INIT_DEBUGOUT("free_transmit_structures: begin"); 2918205869Sjfv 2919205869Sjfv if (adapter->tx_buffer_area != NULL) { 2920205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++) { 2921205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2922205869Sjfv if (tx_buffer->m_head != NULL) { 2923205869Sjfv bus_dmamap_sync(adapter->txtag, tx_buffer->map, 2924205869Sjfv BUS_DMASYNC_POSTWRITE); 2925205869Sjfv bus_dmamap_unload(adapter->txtag, 2926205869Sjfv tx_buffer->map); 2927205869Sjfv m_freem(tx_buffer->m_head); 2928205869Sjfv tx_buffer->m_head = NULL; 2929205869Sjfv } else if (tx_buffer->map != NULL) 2930205869Sjfv bus_dmamap_unload(adapter->txtag, 2931205869Sjfv tx_buffer->map); 2932205869Sjfv if (tx_buffer->map != NULL) { 2933205869Sjfv bus_dmamap_destroy(adapter->txtag, 2934205869Sjfv tx_buffer->map); 2935205869Sjfv tx_buffer->map = NULL; 2936205869Sjfv } 2937205869Sjfv } 2938205869Sjfv } 2939205869Sjfv if (adapter->tx_buffer_area != NULL) { 2940205869Sjfv free(adapter->tx_buffer_area, M_DEVBUF); 2941205869Sjfv adapter->tx_buffer_area = NULL; 2942205869Sjfv } 2943205869Sjfv if (adapter->txtag != NULL) { 2944205869Sjfv bus_dma_tag_destroy(adapter->txtag); 2945205869Sjfv adapter->txtag = NULL; 2946205869Sjfv } 2947205869Sjfv} 2948205869Sjfv 2949205869Sjfv/********************************************************************* 2950205869Sjfv * 2951205869Sjfv * The offload context needs to be set when we transfer the first 2952205869Sjfv * packet of a particular protocol (TCP/UDP). This routine has been 2953205869Sjfv * enhanced to deal with inserted VLAN headers, and IPV6 (not complete) 2954205869Sjfv * 2955205869Sjfv * Added back the old method of keeping the current context type 2956205869Sjfv * and not setting if unnecessary, as this is reported to be a 2957205869Sjfv * big performance win. -jfv 2958205869Sjfv **********************************************************************/ 2959205869Sjfvstatic void 2960205869Sjfvlem_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp, 2961205869Sjfv u32 *txd_upper, u32 *txd_lower) 2962205869Sjfv{ 2963205869Sjfv struct e1000_context_desc *TXD = NULL; 2964205869Sjfv struct em_buffer *tx_buffer; 2965205869Sjfv struct ether_vlan_header *eh; 2966205869Sjfv struct ip *ip = NULL; 2967205869Sjfv struct ip6_hdr *ip6; 2968205869Sjfv int curr_txd, ehdrlen; 2969205869Sjfv u32 cmd, hdr_len, ip_hlen; 2970205869Sjfv u16 etype; 2971205869Sjfv u8 ipproto; 2972205869Sjfv 2973205869Sjfv 2974205869Sjfv cmd = hdr_len = ipproto = 0; 2975209959Sjfv *txd_upper = *txd_lower = 0; 2976205869Sjfv curr_txd = adapter->next_avail_tx_desc; 2977205869Sjfv 2978205869Sjfv /* 2979205869Sjfv * Determine where frame payload starts. 2980205869Sjfv * Jump over vlan headers if already present, 2981205869Sjfv * helpful for QinQ too. 2982205869Sjfv */ 2983205869Sjfv eh = mtod(mp, struct ether_vlan_header *); 2984205869Sjfv if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 2985205869Sjfv etype = ntohs(eh->evl_proto); 2986205869Sjfv ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 2987205869Sjfv } else { 2988205869Sjfv etype = ntohs(eh->evl_encap_proto); 2989205869Sjfv ehdrlen = ETHER_HDR_LEN; 2990205869Sjfv } 2991205869Sjfv 2992205869Sjfv /* 2993205869Sjfv * We only support TCP/UDP for IPv4 and IPv6 for the moment. 2994205869Sjfv * TODO: Support SCTP too when it hits the tree. 2995205869Sjfv */ 2996205869Sjfv switch (etype) { 2997205869Sjfv case ETHERTYPE_IP: 2998205869Sjfv ip = (struct ip *)(mp->m_data + ehdrlen); 2999205869Sjfv ip_hlen = ip->ip_hl << 2; 3000205869Sjfv 3001205869Sjfv /* Setup of IP header checksum. */ 3002205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_IP) { 3003205869Sjfv /* 3004205869Sjfv * Start offset for header checksum calculation. 3005205869Sjfv * End offset for header checksum calculation. 3006205869Sjfv * Offset of place to put the checksum. 3007205869Sjfv */ 3008205869Sjfv TXD = (struct e1000_context_desc *) 3009205869Sjfv &adapter->tx_desc_base[curr_txd]; 3010205869Sjfv TXD->lower_setup.ip_fields.ipcss = ehdrlen; 3011205869Sjfv TXD->lower_setup.ip_fields.ipcse = 3012205869Sjfv htole16(ehdrlen + ip_hlen); 3013205869Sjfv TXD->lower_setup.ip_fields.ipcso = 3014205869Sjfv ehdrlen + offsetof(struct ip, ip_sum); 3015205869Sjfv cmd |= E1000_TXD_CMD_IP; 3016205869Sjfv *txd_upper |= E1000_TXD_POPTS_IXSM << 8; 3017205869Sjfv } 3018205869Sjfv 3019205869Sjfv hdr_len = ehdrlen + ip_hlen; 3020205869Sjfv ipproto = ip->ip_p; 3021205869Sjfv 3022205869Sjfv break; 3023205869Sjfv case ETHERTYPE_IPV6: 3024205869Sjfv ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 3025205869Sjfv ip_hlen = sizeof(struct ip6_hdr); /* XXX: No header stacking. */ 3026205869Sjfv 3027205869Sjfv /* IPv6 doesn't have a header checksum. */ 3028205869Sjfv 3029205869Sjfv hdr_len = ehdrlen + ip_hlen; 3030205869Sjfv ipproto = ip6->ip6_nxt; 3031209959Sjfv break; 3032205869Sjfv 3033205869Sjfv default: 3034205869Sjfv return; 3035205869Sjfv } 3036205869Sjfv 3037205869Sjfv switch (ipproto) { 3038205869Sjfv case IPPROTO_TCP: 3039205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_TCP) { 3040205869Sjfv *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 3041205869Sjfv *txd_upper |= E1000_TXD_POPTS_TXSM << 8; 3042205869Sjfv /* no need for context if already set */ 3043205869Sjfv if (adapter->last_hw_offload == CSUM_TCP) 3044205869Sjfv return; 3045205869Sjfv adapter->last_hw_offload = CSUM_TCP; 3046205869Sjfv /* 3047205869Sjfv * Start offset for payload checksum calculation. 3048205869Sjfv * End offset for payload checksum calculation. 3049205869Sjfv * Offset of place to put the checksum. 3050205869Sjfv */ 3051205869Sjfv TXD = (struct e1000_context_desc *) 3052205869Sjfv &adapter->tx_desc_base[curr_txd]; 3053205869Sjfv TXD->upper_setup.tcp_fields.tucss = hdr_len; 3054205869Sjfv TXD->upper_setup.tcp_fields.tucse = htole16(0); 3055205869Sjfv TXD->upper_setup.tcp_fields.tucso = 3056205869Sjfv hdr_len + offsetof(struct tcphdr, th_sum); 3057205869Sjfv cmd |= E1000_TXD_CMD_TCP; 3058205869Sjfv } 3059205869Sjfv break; 3060205869Sjfv case IPPROTO_UDP: 3061205869Sjfv { 3062205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_UDP) { 3063205869Sjfv *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 3064205869Sjfv *txd_upper |= E1000_TXD_POPTS_TXSM << 8; 3065205869Sjfv /* no need for context if already set */ 3066205869Sjfv if (adapter->last_hw_offload == CSUM_UDP) 3067205869Sjfv return; 3068205869Sjfv adapter->last_hw_offload = CSUM_UDP; 3069205869Sjfv /* 3070205869Sjfv * Start offset for header checksum calculation. 3071205869Sjfv * End offset for header checksum calculation. 3072205869Sjfv * Offset of place to put the checksum. 3073205869Sjfv */ 3074205869Sjfv TXD = (struct e1000_context_desc *) 3075205869Sjfv &adapter->tx_desc_base[curr_txd]; 3076205869Sjfv TXD->upper_setup.tcp_fields.tucss = hdr_len; 3077205869Sjfv TXD->upper_setup.tcp_fields.tucse = htole16(0); 3078205869Sjfv TXD->upper_setup.tcp_fields.tucso = 3079205869Sjfv hdr_len + offsetof(struct udphdr, uh_sum); 3080205869Sjfv } 3081205869Sjfv /* Fall Thru */ 3082205869Sjfv } 3083205869Sjfv default: 3084205869Sjfv break; 3085205869Sjfv } 3086205869Sjfv 3087209959Sjfv if (TXD == NULL) 3088209959Sjfv return; 3089205869Sjfv TXD->tcp_seg_setup.data = htole32(0); 3090205869Sjfv TXD->cmd_and_length = 3091205869Sjfv htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd); 3092205869Sjfv tx_buffer = &adapter->tx_buffer_area[curr_txd]; 3093205869Sjfv tx_buffer->m_head = NULL; 3094205869Sjfv tx_buffer->next_eop = -1; 3095205869Sjfv 3096205869Sjfv if (++curr_txd == adapter->num_tx_desc) 3097205869Sjfv curr_txd = 0; 3098205869Sjfv 3099205869Sjfv adapter->num_tx_desc_avail--; 3100205869Sjfv adapter->next_avail_tx_desc = curr_txd; 3101205869Sjfv} 3102205869Sjfv 3103205869Sjfv 3104205869Sjfv/********************************************************************** 3105205869Sjfv * 3106205869Sjfv * Examine each tx_buffer in the used queue. If the hardware is done 3107205869Sjfv * processing the packet then free associated resources. The 3108205869Sjfv * tx_buffer is put back on the free queue. 3109205869Sjfv * 3110205869Sjfv **********************************************************************/ 3111205869Sjfvstatic void 3112205869Sjfvlem_txeof(struct adapter *adapter) 3113205869Sjfv{ 3114205869Sjfv int first, last, done, num_avail; 3115205869Sjfv struct em_buffer *tx_buffer; 3116205869Sjfv struct e1000_tx_desc *tx_desc, *eop_desc; 3117205869Sjfv struct ifnet *ifp = adapter->ifp; 3118205869Sjfv 3119205869Sjfv EM_TX_LOCK_ASSERT(adapter); 3120205869Sjfv 3121228281Sluigi#ifdef DEV_NETMAP 3122262151Sluigi if (netmap_tx_irq(ifp, 0)) 3123228281Sluigi return; 3124228281Sluigi#endif /* DEV_NETMAP */ 3125205869Sjfv if (adapter->num_tx_desc_avail == adapter->num_tx_desc) 3126205869Sjfv return; 3127205869Sjfv 3128205869Sjfv num_avail = adapter->num_tx_desc_avail; 3129205869Sjfv first = adapter->next_tx_to_clean; 3130205869Sjfv tx_desc = &adapter->tx_desc_base[first]; 3131205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 3132205869Sjfv last = tx_buffer->next_eop; 3133205869Sjfv eop_desc = &adapter->tx_desc_base[last]; 3134205869Sjfv 3135205869Sjfv /* 3136205869Sjfv * What this does is get the index of the 3137205869Sjfv * first descriptor AFTER the EOP of the 3138205869Sjfv * first packet, that way we can do the 3139205869Sjfv * simple comparison on the inner while loop. 3140205869Sjfv */ 3141205869Sjfv if (++last == adapter->num_tx_desc) 3142205869Sjfv last = 0; 3143205869Sjfv done = last; 3144205869Sjfv 3145205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 3146205869Sjfv BUS_DMASYNC_POSTREAD); 3147205869Sjfv 3148205869Sjfv while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) { 3149205869Sjfv /* We clean the range of the packet */ 3150205869Sjfv while (first != done) { 3151205869Sjfv tx_desc->upper.data = 0; 3152205869Sjfv tx_desc->lower.data = 0; 3153205869Sjfv tx_desc->buffer_addr = 0; 3154205869Sjfv ++num_avail; 3155205869Sjfv 3156205869Sjfv if (tx_buffer->m_head) { 3157205869Sjfv ifp->if_opackets++; 3158205869Sjfv bus_dmamap_sync(adapter->txtag, 3159205869Sjfv tx_buffer->map, 3160205869Sjfv BUS_DMASYNC_POSTWRITE); 3161205869Sjfv bus_dmamap_unload(adapter->txtag, 3162205869Sjfv tx_buffer->map); 3163205869Sjfv 3164205869Sjfv m_freem(tx_buffer->m_head); 3165205869Sjfv tx_buffer->m_head = NULL; 3166205869Sjfv } 3167205869Sjfv tx_buffer->next_eop = -1; 3168205869Sjfv adapter->watchdog_time = ticks; 3169205869Sjfv 3170205869Sjfv if (++first == adapter->num_tx_desc) 3171205869Sjfv first = 0; 3172205869Sjfv 3173205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 3174205869Sjfv tx_desc = &adapter->tx_desc_base[first]; 3175205869Sjfv } 3176205869Sjfv /* See if we can continue to the next packet */ 3177205869Sjfv last = tx_buffer->next_eop; 3178205869Sjfv if (last != -1) { 3179205869Sjfv eop_desc = &adapter->tx_desc_base[last]; 3180205869Sjfv /* Get new done point */ 3181205869Sjfv if (++last == adapter->num_tx_desc) last = 0; 3182205869Sjfv done = last; 3183205869Sjfv } else 3184205869Sjfv break; 3185205869Sjfv } 3186205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 3187205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3188205869Sjfv 3189205869Sjfv adapter->next_tx_to_clean = first; 3190214646Sjfv adapter->num_tx_desc_avail = num_avail; 3191205869Sjfv 3192270252Sluigi#ifdef NIC_SEND_COMBINING 3193270252Sluigi if ((adapter->shadow_tdt & MIT_PENDING_TDT) == MIT_PENDING_TDT) { 3194270252Sluigi /* a tdt write is pending, do it */ 3195270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 3196270252Sluigi 0xffff & adapter->shadow_tdt); 3197270252Sluigi adapter->shadow_tdt = MIT_PENDING_INT; 3198270252Sluigi } else { 3199270252Sluigi adapter->shadow_tdt = 0; // disable 3200270252Sluigi } 3201270252Sluigi#endif /* NIC_SEND_COMBINING */ 3202205869Sjfv /* 3203205869Sjfv * If we have enough room, clear IFF_DRV_OACTIVE to 3204205869Sjfv * tell the stack that it is OK to send packets. 3205205869Sjfv * If there are no pending descriptors, clear the watchdog. 3206205869Sjfv */ 3207214646Sjfv if (adapter->num_tx_desc_avail > EM_TX_CLEANUP_THRESHOLD) { 3208205869Sjfv ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 3209270252Sluigi#ifdef NIC_PARAVIRT 3210270252Sluigi if (adapter->csb) { // XXX also csb_on ? 3211270252Sluigi adapter->csb->guest_need_txkick = 2; /* acked */ 3212270252Sluigi // XXX memory barrier 3213270252Sluigi } 3214270252Sluigi#endif /* NIC_PARAVIRT */ 3215214646Sjfv if (adapter->num_tx_desc_avail == adapter->num_tx_desc) { 3216205869Sjfv adapter->watchdog_check = FALSE; 3217205869Sjfv return; 3218205869Sjfv } 3219205869Sjfv } 3220205869Sjfv} 3221205869Sjfv 3222205869Sjfv/********************************************************************* 3223205869Sjfv * 3224205869Sjfv * When Link is lost sometimes there is work still in the TX ring 3225205869Sjfv * which may result in a watchdog, rather than allow that we do an 3226205869Sjfv * attempted cleanup and then reinit here. Note that this has been 3227205869Sjfv * seens mostly with fiber adapters. 3228205869Sjfv * 3229205869Sjfv **********************************************************************/ 3230205869Sjfvstatic void 3231205869Sjfvlem_tx_purge(struct adapter *adapter) 3232205869Sjfv{ 3233205869Sjfv if ((!adapter->link_active) && (adapter->watchdog_check)) { 3234205869Sjfv EM_TX_LOCK(adapter); 3235205869Sjfv lem_txeof(adapter); 3236205869Sjfv EM_TX_UNLOCK(adapter); 3237205869Sjfv if (adapter->watchdog_check) /* Still outstanding? */ 3238205869Sjfv lem_init_locked(adapter); 3239205869Sjfv } 3240205869Sjfv} 3241205869Sjfv 3242205869Sjfv/********************************************************************* 3243205869Sjfv * 3244205869Sjfv * Get a buffer from system mbuf buffer pool. 3245205869Sjfv * 3246205869Sjfv **********************************************************************/ 3247205869Sjfvstatic int 3248205869Sjfvlem_get_buf(struct adapter *adapter, int i) 3249205869Sjfv{ 3250205869Sjfv struct mbuf *m; 3251205869Sjfv bus_dma_segment_t segs[1]; 3252205869Sjfv bus_dmamap_t map; 3253205869Sjfv struct em_buffer *rx_buffer; 3254205869Sjfv int error, nsegs; 3255205869Sjfv 3256243857Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 3257205869Sjfv if (m == NULL) { 3258205869Sjfv adapter->mbuf_cluster_failed++; 3259205869Sjfv return (ENOBUFS); 3260205869Sjfv } 3261205869Sjfv m->m_len = m->m_pkthdr.len = MCLBYTES; 3262205869Sjfv 3263205869Sjfv if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN)) 3264205869Sjfv m_adj(m, ETHER_ALIGN); 3265205869Sjfv 3266205869Sjfv /* 3267205869Sjfv * Using memory from the mbuf cluster pool, invoke the 3268205869Sjfv * bus_dma machinery to arrange the memory mapping. 3269205869Sjfv */ 3270205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->rxtag, 3271205869Sjfv adapter->rx_sparemap, m, segs, &nsegs, BUS_DMA_NOWAIT); 3272205869Sjfv if (error != 0) { 3273205869Sjfv m_free(m); 3274205869Sjfv return (error); 3275205869Sjfv } 3276205869Sjfv 3277205869Sjfv /* If nsegs is wrong then the stack is corrupt. */ 3278205869Sjfv KASSERT(nsegs == 1, ("Too many segments returned!")); 3279205869Sjfv 3280205869Sjfv rx_buffer = &adapter->rx_buffer_area[i]; 3281205869Sjfv if (rx_buffer->m_head != NULL) 3282205869Sjfv bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 3283205869Sjfv 3284205869Sjfv map = rx_buffer->map; 3285205869Sjfv rx_buffer->map = adapter->rx_sparemap; 3286205869Sjfv adapter->rx_sparemap = map; 3287205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD); 3288205869Sjfv rx_buffer->m_head = m; 3289205869Sjfv 3290205869Sjfv adapter->rx_desc_base[i].buffer_addr = htole64(segs[0].ds_addr); 3291205869Sjfv return (0); 3292205869Sjfv} 3293205869Sjfv 3294205869Sjfv/********************************************************************* 3295205869Sjfv * 3296205869Sjfv * Allocate memory for rx_buffer structures. Since we use one 3297205869Sjfv * rx_buffer per received packet, the maximum number of rx_buffer's 3298205869Sjfv * that we'll need is equal to the number of receive descriptors 3299205869Sjfv * that we've allocated. 3300205869Sjfv * 3301205869Sjfv **********************************************************************/ 3302205869Sjfvstatic int 3303205869Sjfvlem_allocate_receive_structures(struct adapter *adapter) 3304205869Sjfv{ 3305205869Sjfv device_t dev = adapter->dev; 3306205869Sjfv struct em_buffer *rx_buffer; 3307205869Sjfv int i, error; 3308205869Sjfv 3309205869Sjfv adapter->rx_buffer_area = malloc(sizeof(struct em_buffer) * 3310205869Sjfv adapter->num_rx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); 3311205869Sjfv if (adapter->rx_buffer_area == NULL) { 3312205869Sjfv device_printf(dev, "Unable to allocate rx_buffer memory\n"); 3313205869Sjfv return (ENOMEM); 3314205869Sjfv } 3315205869Sjfv 3316205869Sjfv error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 3317205869Sjfv 1, 0, /* alignment, bounds */ 3318205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 3319205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 3320205869Sjfv NULL, NULL, /* filter, filterarg */ 3321205869Sjfv MCLBYTES, /* maxsize */ 3322205869Sjfv 1, /* nsegments */ 3323205869Sjfv MCLBYTES, /* maxsegsize */ 3324205869Sjfv 0, /* flags */ 3325205869Sjfv NULL, /* lockfunc */ 3326205869Sjfv NULL, /* lockarg */ 3327205869Sjfv &adapter->rxtag); 3328205869Sjfv if (error) { 3329205869Sjfv device_printf(dev, "%s: bus_dma_tag_create failed %d\n", 3330205869Sjfv __func__, error); 3331205869Sjfv goto fail; 3332205869Sjfv } 3333205869Sjfv 3334205869Sjfv /* Create the spare map (used by getbuf) */ 3335259508Skib error = bus_dmamap_create(adapter->rxtag, 0, &adapter->rx_sparemap); 3336205869Sjfv if (error) { 3337205869Sjfv device_printf(dev, "%s: bus_dmamap_create failed: %d\n", 3338205869Sjfv __func__, error); 3339205869Sjfv goto fail; 3340205869Sjfv } 3341205869Sjfv 3342205869Sjfv rx_buffer = adapter->rx_buffer_area; 3343205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3344259508Skib error = bus_dmamap_create(adapter->rxtag, 0, &rx_buffer->map); 3345205869Sjfv if (error) { 3346205869Sjfv device_printf(dev, "%s: bus_dmamap_create failed: %d\n", 3347205869Sjfv __func__, error); 3348205869Sjfv goto fail; 3349205869Sjfv } 3350205869Sjfv } 3351205869Sjfv 3352205869Sjfv return (0); 3353205869Sjfv 3354205869Sjfvfail: 3355205869Sjfv lem_free_receive_structures(adapter); 3356205869Sjfv return (error); 3357205869Sjfv} 3358205869Sjfv 3359205869Sjfv/********************************************************************* 3360205869Sjfv * 3361205869Sjfv * (Re)initialize receive structures. 3362205869Sjfv * 3363205869Sjfv **********************************************************************/ 3364205869Sjfvstatic int 3365205869Sjfvlem_setup_receive_structures(struct adapter *adapter) 3366205869Sjfv{ 3367205869Sjfv struct em_buffer *rx_buffer; 3368205869Sjfv int i, error; 3369228281Sluigi#ifdef DEV_NETMAP 3370228281Sluigi /* we are already under lock */ 3371228281Sluigi struct netmap_adapter *na = NA(adapter->ifp); 3372228281Sluigi struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0); 3373228281Sluigi#endif 3374205869Sjfv 3375205869Sjfv /* Reset descriptor ring */ 3376205869Sjfv bzero(adapter->rx_desc_base, 3377205869Sjfv (sizeof(struct e1000_rx_desc)) * adapter->num_rx_desc); 3378205869Sjfv 3379205869Sjfv /* Free current RX buffers. */ 3380205869Sjfv rx_buffer = adapter->rx_buffer_area; 3381205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3382205869Sjfv if (rx_buffer->m_head != NULL) { 3383205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, 3384205869Sjfv BUS_DMASYNC_POSTREAD); 3385205869Sjfv bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 3386205869Sjfv m_freem(rx_buffer->m_head); 3387205869Sjfv rx_buffer->m_head = NULL; 3388205869Sjfv } 3389205869Sjfv } 3390205869Sjfv 3391205869Sjfv /* Allocate new ones. */ 3392205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++) { 3393228281Sluigi#ifdef DEV_NETMAP 3394228281Sluigi if (slot) { 3395231796Sluigi /* the i-th NIC entry goes to slot si */ 3396232238Sluigi int si = netmap_idx_n2k(&na->rx_rings[0], i); 3397229939Sluigi uint64_t paddr; 3398228281Sluigi void *addr; 3399228281Sluigi 3400270252Sluigi addr = PNMB(na, slot + si, &paddr); 3401270252Sluigi netmap_load_map(na, adapter->rxtag, rx_buffer->map, addr); 3402228281Sluigi /* Update descriptor */ 3403229939Sluigi adapter->rx_desc_base[i].buffer_addr = htole64(paddr); 3404228281Sluigi continue; 3405228281Sluigi } 3406228281Sluigi#endif /* DEV_NETMAP */ 3407205869Sjfv error = lem_get_buf(adapter, i); 3408205869Sjfv if (error) 3409205869Sjfv return (error); 3410205869Sjfv } 3411205869Sjfv 3412205869Sjfv /* Setup our descriptor pointers */ 3413205869Sjfv adapter->next_rx_desc_to_check = 0; 3414205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3415205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3416205869Sjfv 3417205869Sjfv return (0); 3418205869Sjfv} 3419205869Sjfv 3420205869Sjfv/********************************************************************* 3421205869Sjfv * 3422205869Sjfv * Enable receive unit. 3423205869Sjfv * 3424205869Sjfv **********************************************************************/ 3425205869Sjfv 3426205869Sjfvstatic void 3427205869Sjfvlem_initialize_receive_unit(struct adapter *adapter) 3428205869Sjfv{ 3429205869Sjfv struct ifnet *ifp = adapter->ifp; 3430205869Sjfv u64 bus_addr; 3431205869Sjfv u32 rctl, rxcsum; 3432205869Sjfv 3433205869Sjfv INIT_DEBUGOUT("lem_initialize_receive_unit: begin"); 3434205869Sjfv 3435205869Sjfv /* 3436205869Sjfv * Make sure receives are disabled while setting 3437205869Sjfv * up the descriptor ring 3438205869Sjfv */ 3439205869Sjfv rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 3440205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); 3441205869Sjfv 3442205869Sjfv if (adapter->hw.mac.type >= e1000_82540) { 3443205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RADV, 3444205869Sjfv adapter->rx_abs_int_delay.value); 3445205869Sjfv /* 3446205869Sjfv * Set the interrupt throttling rate. Value is calculated 3447205869Sjfv * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) 3448205869Sjfv */ 3449205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_ITR, DEFAULT_ITR); 3450205869Sjfv } 3451205869Sjfv 3452205869Sjfv /* Setup the Base and Length of the Rx Descriptor Ring */ 3453205869Sjfv bus_addr = adapter->rxdma.dma_paddr; 3454205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0), 3455205869Sjfv adapter->num_rx_desc * sizeof(struct e1000_rx_desc)); 3456205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDBAH(0), 3457205869Sjfv (u32)(bus_addr >> 32)); 3458205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDBAL(0), 3459205869Sjfv (u32)bus_addr); 3460205869Sjfv 3461205869Sjfv /* Setup the Receive Control Register */ 3462205869Sjfv rctl &= ~(3 << E1000_RCTL_MO_SHIFT); 3463205869Sjfv rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | 3464205869Sjfv E1000_RCTL_RDMTS_HALF | 3465205869Sjfv (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); 3466205869Sjfv 3467205869Sjfv /* Make sure VLAN Filters are off */ 3468205869Sjfv rctl &= ~E1000_RCTL_VFE; 3469205869Sjfv 3470205869Sjfv if (e1000_tbi_sbp_enabled_82543(&adapter->hw)) 3471205869Sjfv rctl |= E1000_RCTL_SBP; 3472205869Sjfv else 3473205869Sjfv rctl &= ~E1000_RCTL_SBP; 3474205869Sjfv 3475205869Sjfv switch (adapter->rx_buffer_len) { 3476205869Sjfv default: 3477205869Sjfv case 2048: 3478205869Sjfv rctl |= E1000_RCTL_SZ_2048; 3479205869Sjfv break; 3480205869Sjfv case 4096: 3481205869Sjfv rctl |= E1000_RCTL_SZ_4096 | 3482205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3483205869Sjfv break; 3484205869Sjfv case 8192: 3485205869Sjfv rctl |= E1000_RCTL_SZ_8192 | 3486205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3487205869Sjfv break; 3488205869Sjfv case 16384: 3489205869Sjfv rctl |= E1000_RCTL_SZ_16384 | 3490205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3491205869Sjfv break; 3492205869Sjfv } 3493205869Sjfv 3494205869Sjfv if (ifp->if_mtu > ETHERMTU) 3495205869Sjfv rctl |= E1000_RCTL_LPE; 3496205869Sjfv else 3497205869Sjfv rctl &= ~E1000_RCTL_LPE; 3498205869Sjfv 3499205869Sjfv /* Enable 82543 Receive Checksum Offload for TCP and UDP */ 3500205869Sjfv if ((adapter->hw.mac.type >= e1000_82543) && 3501205869Sjfv (ifp->if_capenable & IFCAP_RXCSUM)) { 3502205869Sjfv rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM); 3503205869Sjfv rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); 3504205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum); 3505205869Sjfv } 3506205869Sjfv 3507205869Sjfv /* Enable Receives */ 3508205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); 3509205869Sjfv 3510205869Sjfv /* 3511205869Sjfv * Setup the HW Rx Head and 3512205869Sjfv * Tail Descriptor Pointers 3513205869Sjfv */ 3514205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0); 3515250413Sluigi rctl = adapter->num_rx_desc - 1; /* default RDT value */ 3516228281Sluigi#ifdef DEV_NETMAP 3517228281Sluigi /* preserve buffers already made available to clients */ 3518250413Sluigi if (ifp->if_capenable & IFCAP_NETMAP) 3519262151Sluigi rctl -= nm_kr_rxspace(&NA(adapter->ifp)->rx_rings[0]); 3520228281Sluigi#endif /* DEV_NETMAP */ 3521250413Sluigi E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), rctl); 3522205869Sjfv 3523205869Sjfv return; 3524205869Sjfv} 3525205869Sjfv 3526205869Sjfv/********************************************************************* 3527205869Sjfv * 3528205869Sjfv * Free receive related data structures. 3529205869Sjfv * 3530205869Sjfv **********************************************************************/ 3531205869Sjfvstatic void 3532205869Sjfvlem_free_receive_structures(struct adapter *adapter) 3533205869Sjfv{ 3534205869Sjfv struct em_buffer *rx_buffer; 3535205869Sjfv int i; 3536205869Sjfv 3537205869Sjfv INIT_DEBUGOUT("free_receive_structures: begin"); 3538205869Sjfv 3539205869Sjfv if (adapter->rx_sparemap) { 3540205869Sjfv bus_dmamap_destroy(adapter->rxtag, adapter->rx_sparemap); 3541205869Sjfv adapter->rx_sparemap = NULL; 3542205869Sjfv } 3543205869Sjfv 3544205869Sjfv /* Cleanup any existing buffers */ 3545205869Sjfv if (adapter->rx_buffer_area != NULL) { 3546205869Sjfv rx_buffer = adapter->rx_buffer_area; 3547205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3548205869Sjfv if (rx_buffer->m_head != NULL) { 3549205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, 3550205869Sjfv BUS_DMASYNC_POSTREAD); 3551205869Sjfv bus_dmamap_unload(adapter->rxtag, 3552205869Sjfv rx_buffer->map); 3553205869Sjfv m_freem(rx_buffer->m_head); 3554205869Sjfv rx_buffer->m_head = NULL; 3555205869Sjfv } else if (rx_buffer->map != NULL) 3556205869Sjfv bus_dmamap_unload(adapter->rxtag, 3557205869Sjfv rx_buffer->map); 3558205869Sjfv if (rx_buffer->map != NULL) { 3559205869Sjfv bus_dmamap_destroy(adapter->rxtag, 3560205869Sjfv rx_buffer->map); 3561205869Sjfv rx_buffer->map = NULL; 3562205869Sjfv } 3563205869Sjfv } 3564205869Sjfv } 3565205869Sjfv 3566205869Sjfv if (adapter->rx_buffer_area != NULL) { 3567205869Sjfv free(adapter->rx_buffer_area, M_DEVBUF); 3568205869Sjfv adapter->rx_buffer_area = NULL; 3569205869Sjfv } 3570205869Sjfv 3571205869Sjfv if (adapter->rxtag != NULL) { 3572205869Sjfv bus_dma_tag_destroy(adapter->rxtag); 3573205869Sjfv adapter->rxtag = NULL; 3574205869Sjfv } 3575205869Sjfv} 3576205869Sjfv 3577205869Sjfv/********************************************************************* 3578205869Sjfv * 3579205869Sjfv * This routine executes in interrupt context. It replenishes 3580205869Sjfv * the mbufs in the descriptor and sends data which has been 3581205869Sjfv * dma'ed into host memory to upper layer. 3582205869Sjfv * 3583205869Sjfv * We loop at most count times if count is > 0, or until done if 3584205869Sjfv * count < 0. 3585205869Sjfv * 3586205869Sjfv * For polling we also now return the number of cleaned packets 3587205869Sjfv *********************************************************************/ 3588209238Sjfvstatic bool 3589209238Sjfvlem_rxeof(struct adapter *adapter, int count, int *done) 3590205869Sjfv{ 3591241844Seadler struct ifnet *ifp = adapter->ifp; 3592205869Sjfv struct mbuf *mp; 3593214646Sjfv u8 status = 0, accept_frame = 0, eop = 0; 3594205869Sjfv u16 len, desc_len, prev_len_adj; 3595205869Sjfv int i, rx_sent = 0; 3596205869Sjfv struct e1000_rx_desc *current_desc; 3597205869Sjfv 3598270252Sluigi#ifdef BATCH_DISPATCH 3599270252Sluigi struct mbuf *mh = NULL, *mt = NULL; 3600270252Sluigi#endif /* BATCH_DISPATCH */ 3601270252Sluigi#ifdef NIC_PARAVIRT 3602270252Sluigi int retries = 0; 3603270252Sluigi struct paravirt_csb* csb = adapter->csb; 3604270252Sluigi int csb_mode = csb && csb->guest_csb_on; 3605270252Sluigi 3606270252Sluigi //ND("clear guest_rxkick at %d", adapter->next_rx_desc_to_check); 3607270252Sluigi if (csb_mode && csb->guest_need_rxkick) 3608270252Sluigi csb->guest_need_rxkick = 0; 3609270252Sluigi#endif /* NIC_PARAVIRT */ 3610205869Sjfv EM_RX_LOCK(adapter); 3611270252Sluigi 3612270252Sluigi#ifdef BATCH_DISPATCH 3613270252Sluigi batch_again: 3614270252Sluigi#endif /* BATCH_DISPATCH */ 3615205869Sjfv i = adapter->next_rx_desc_to_check; 3616205869Sjfv current_desc = &adapter->rx_desc_base[i]; 3617205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3618205869Sjfv BUS_DMASYNC_POSTREAD); 3619205869Sjfv 3620228281Sluigi#ifdef DEV_NETMAP 3621262151Sluigi if (netmap_rx_irq(ifp, 0, &rx_sent)) { 3622262151Sluigi EM_RX_UNLOCK(adapter); 3623250109Sluigi return (FALSE); 3624262151Sluigi } 3625228281Sluigi#endif /* DEV_NETMAP */ 3626228281Sluigi 3627270252Sluigi#if 1 // XXX optimization ? 3628205869Sjfv if (!((current_desc->status) & E1000_RXD_STAT_DD)) { 3629209238Sjfv if (done != NULL) 3630209238Sjfv *done = rx_sent; 3631205869Sjfv EM_RX_UNLOCK(adapter); 3632209238Sjfv return (FALSE); 3633205869Sjfv } 3634270252Sluigi#endif /* 0 */ 3635205869Sjfv 3636214646Sjfv while (count != 0 && ifp->if_drv_flags & IFF_DRV_RUNNING) { 3637205869Sjfv struct mbuf *m = NULL; 3638205869Sjfv 3639214646Sjfv status = current_desc->status; 3640270252Sluigi if ((status & E1000_RXD_STAT_DD) == 0) { 3641270252Sluigi#ifdef NIC_PARAVIRT 3642270252Sluigi if (csb_mode) { 3643270252Sluigi /* buffer not ready yet. Retry a few times before giving up */ 3644270252Sluigi if (++retries <= adapter->rx_retries) { 3645270252Sluigi continue; 3646270252Sluigi } 3647270252Sluigi if (csb->guest_need_rxkick == 0) { 3648270252Sluigi // ND("set guest_rxkick at %d", adapter->next_rx_desc_to_check); 3649270252Sluigi csb->guest_need_rxkick = 1; 3650270252Sluigi // XXX memory barrier, status volatile ? 3651270252Sluigi continue; /* double check */ 3652270252Sluigi } 3653270252Sluigi } 3654270252Sluigi /* no buffer ready, give up */ 3655270252Sluigi#endif /* NIC_PARAVIRT */ 3656214646Sjfv break; 3657270252Sluigi } 3658270252Sluigi#ifdef NIC_PARAVIRT 3659270252Sluigi if (csb_mode) { 3660270252Sluigi if (csb->guest_need_rxkick) 3661270252Sluigi // ND("clear again guest_rxkick at %d", adapter->next_rx_desc_to_check); 3662270252Sluigi csb->guest_need_rxkick = 0; 3663270252Sluigi retries = 0; 3664270252Sluigi } 3665270252Sluigi#endif /* NIC_PARAVIRT */ 3666214646Sjfv 3667205869Sjfv mp = adapter->rx_buffer_area[i].m_head; 3668205869Sjfv /* 3669205869Sjfv * Can't defer bus_dmamap_sync(9) because TBI_ACCEPT 3670205869Sjfv * needs to access the last received byte in the mbuf. 3671205869Sjfv */ 3672205869Sjfv bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map, 3673205869Sjfv BUS_DMASYNC_POSTREAD); 3674205869Sjfv 3675205869Sjfv accept_frame = 1; 3676205869Sjfv prev_len_adj = 0; 3677205869Sjfv desc_len = le16toh(current_desc->length); 3678205869Sjfv if (status & E1000_RXD_STAT_EOP) { 3679205869Sjfv count--; 3680205869Sjfv eop = 1; 3681205869Sjfv if (desc_len < ETHER_CRC_LEN) { 3682205869Sjfv len = 0; 3683205869Sjfv prev_len_adj = ETHER_CRC_LEN - desc_len; 3684205869Sjfv } else 3685205869Sjfv len = desc_len - ETHER_CRC_LEN; 3686205869Sjfv } else { 3687205869Sjfv eop = 0; 3688205869Sjfv len = desc_len; 3689205869Sjfv } 3690205869Sjfv 3691205869Sjfv if (current_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) { 3692205869Sjfv u8 last_byte; 3693205869Sjfv u32 pkt_len = desc_len; 3694205869Sjfv 3695205869Sjfv if (adapter->fmp != NULL) 3696205869Sjfv pkt_len += adapter->fmp->m_pkthdr.len; 3697205869Sjfv 3698205869Sjfv last_byte = *(mtod(mp, caddr_t) + desc_len - 1); 3699205869Sjfv if (TBI_ACCEPT(&adapter->hw, status, 3700205869Sjfv current_desc->errors, pkt_len, last_byte, 3701205869Sjfv adapter->min_frame_size, adapter->max_frame_size)) { 3702205869Sjfv e1000_tbi_adjust_stats_82543(&adapter->hw, 3703205869Sjfv &adapter->stats, pkt_len, 3704205869Sjfv adapter->hw.mac.addr, 3705205869Sjfv adapter->max_frame_size); 3706205869Sjfv if (len > 0) 3707205869Sjfv len--; 3708205869Sjfv } else 3709205869Sjfv accept_frame = 0; 3710205869Sjfv } 3711205869Sjfv 3712205869Sjfv if (accept_frame) { 3713205869Sjfv if (lem_get_buf(adapter, i) != 0) { 3714205869Sjfv ifp->if_iqdrops++; 3715205869Sjfv goto discard; 3716205869Sjfv } 3717205869Sjfv 3718205869Sjfv /* Assign correct length to the current fragment */ 3719205869Sjfv mp->m_len = len; 3720205869Sjfv 3721205869Sjfv if (adapter->fmp == NULL) { 3722205869Sjfv mp->m_pkthdr.len = len; 3723205869Sjfv adapter->fmp = mp; /* Store the first mbuf */ 3724205869Sjfv adapter->lmp = mp; 3725205869Sjfv } else { 3726205869Sjfv /* Chain mbuf's together */ 3727205869Sjfv mp->m_flags &= ~M_PKTHDR; 3728205869Sjfv /* 3729205869Sjfv * Adjust length of previous mbuf in chain if 3730205869Sjfv * we received less than 4 bytes in the last 3731205869Sjfv * descriptor. 3732205869Sjfv */ 3733205869Sjfv if (prev_len_adj > 0) { 3734205869Sjfv adapter->lmp->m_len -= prev_len_adj; 3735205869Sjfv adapter->fmp->m_pkthdr.len -= 3736205869Sjfv prev_len_adj; 3737205869Sjfv } 3738205869Sjfv adapter->lmp->m_next = mp; 3739205869Sjfv adapter->lmp = adapter->lmp->m_next; 3740205869Sjfv adapter->fmp->m_pkthdr.len += len; 3741205869Sjfv } 3742205869Sjfv 3743205869Sjfv if (eop) { 3744205869Sjfv adapter->fmp->m_pkthdr.rcvif = ifp; 3745205869Sjfv ifp->if_ipackets++; 3746205869Sjfv lem_receive_checksum(adapter, current_desc, 3747205869Sjfv adapter->fmp); 3748205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3749205869Sjfv if (adapter->max_frame_size > 3750205869Sjfv (MCLBYTES - ETHER_ALIGN) && 3751205869Sjfv lem_fixup_rx(adapter) != 0) 3752205869Sjfv goto skip; 3753205869Sjfv#endif 3754205869Sjfv if (status & E1000_RXD_STAT_VP) { 3755205869Sjfv adapter->fmp->m_pkthdr.ether_vtag = 3756229606Srwatson le16toh(current_desc->special); 3757205869Sjfv adapter->fmp->m_flags |= M_VLANTAG; 3758205869Sjfv } 3759205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3760205869Sjfvskip: 3761205869Sjfv#endif 3762205869Sjfv m = adapter->fmp; 3763205869Sjfv adapter->fmp = NULL; 3764205869Sjfv adapter->lmp = NULL; 3765205869Sjfv } 3766205869Sjfv } else { 3767240879Ssbruno adapter->dropped_pkts++; 3768205869Sjfvdiscard: 3769205869Sjfv /* Reuse loaded DMA map and just update mbuf chain */ 3770205869Sjfv mp = adapter->rx_buffer_area[i].m_head; 3771205869Sjfv mp->m_len = mp->m_pkthdr.len = MCLBYTES; 3772205869Sjfv mp->m_data = mp->m_ext.ext_buf; 3773205869Sjfv mp->m_next = NULL; 3774205869Sjfv if (adapter->max_frame_size <= 3775205869Sjfv (MCLBYTES - ETHER_ALIGN)) 3776205869Sjfv m_adj(mp, ETHER_ALIGN); 3777205869Sjfv if (adapter->fmp != NULL) { 3778205869Sjfv m_freem(adapter->fmp); 3779205869Sjfv adapter->fmp = NULL; 3780205869Sjfv adapter->lmp = NULL; 3781205869Sjfv } 3782205869Sjfv m = NULL; 3783205869Sjfv } 3784205869Sjfv 3785205869Sjfv /* Zero out the receive descriptors status. */ 3786205869Sjfv current_desc->status = 0; 3787205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3788205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3789205869Sjfv 3790270252Sluigi#ifdef NIC_PARAVIRT 3791270252Sluigi if (csb_mode) { 3792270252Sluigi /* the buffer at i has been already replaced by lem_get_buf() 3793270252Sluigi * so it is safe to set guest_rdt = i and possibly send a kick. 3794270252Sluigi * XXX see if we can optimize it later. 3795270252Sluigi */ 3796270252Sluigi csb->guest_rdt = i; 3797270252Sluigi // XXX memory barrier 3798270252Sluigi if (i == csb->host_rxkick_at) 3799270252Sluigi E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); 3800270252Sluigi } 3801270252Sluigi#endif /* NIC_PARAVIRT */ 3802205869Sjfv /* Advance our pointers to the next descriptor. */ 3803205869Sjfv if (++i == adapter->num_rx_desc) 3804205869Sjfv i = 0; 3805205869Sjfv /* Call into the stack */ 3806205869Sjfv if (m != NULL) { 3807270252Sluigi#ifdef BATCH_DISPATCH 3808270252Sluigi if (adapter->batch_enable) { 3809270252Sluigi if (mh == NULL) 3810270252Sluigi mh = mt = m; 3811270252Sluigi else 3812270252Sluigi mt->m_nextpkt = m; 3813270252Sluigi mt = m; 3814270252Sluigi m->m_nextpkt = NULL; 3815270252Sluigi rx_sent++; 3816270252Sluigi current_desc = &adapter->rx_desc_base[i]; 3817270252Sluigi continue; 3818270252Sluigi } 3819270252Sluigi#endif /* BATCH_DISPATCH */ 3820205869Sjfv adapter->next_rx_desc_to_check = i; 3821205869Sjfv EM_RX_UNLOCK(adapter); 3822205869Sjfv (*ifp->if_input)(ifp, m); 3823205869Sjfv EM_RX_LOCK(adapter); 3824205869Sjfv rx_sent++; 3825205869Sjfv i = adapter->next_rx_desc_to_check; 3826205869Sjfv } 3827205869Sjfv current_desc = &adapter->rx_desc_base[i]; 3828205869Sjfv } 3829205869Sjfv adapter->next_rx_desc_to_check = i; 3830270252Sluigi#ifdef BATCH_DISPATCH 3831270252Sluigi if (mh) { 3832270252Sluigi EM_RX_UNLOCK(adapter); 3833270252Sluigi while ( (mt = mh) != NULL) { 3834270252Sluigi mh = mh->m_nextpkt; 3835270252Sluigi mt->m_nextpkt = NULL; 3836270252Sluigi if_input(ifp, mt); 3837270252Sluigi } 3838270252Sluigi EM_RX_LOCK(adapter); 3839270252Sluigi i = adapter->next_rx_desc_to_check; /* in case of interrupts */ 3840270252Sluigi if (count > 0) 3841270252Sluigi goto batch_again; 3842270252Sluigi } 3843270252Sluigi#endif /* BATCH_DISPATCH */ 3844205869Sjfv 3845205869Sjfv /* Advance the E1000's Receive Queue #0 "Tail Pointer". */ 3846205869Sjfv if (--i < 0) 3847205869Sjfv i = adapter->num_rx_desc - 1; 3848270252Sluigi#ifdef NIC_PARAVIRT 3849270252Sluigi if (!csb_mode) /* filter out writes */ 3850270252Sluigi#endif /* NIC_PARAVIRT */ 3851205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); 3852209238Sjfv if (done != NULL) 3853209238Sjfv *done = rx_sent; 3854205869Sjfv EM_RX_UNLOCK(adapter); 3855214646Sjfv return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE); 3856205869Sjfv} 3857205869Sjfv 3858205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3859205869Sjfv/* 3860205869Sjfv * When jumbo frames are enabled we should realign entire payload on 3861205869Sjfv * architecures with strict alignment. This is serious design mistake of 8254x 3862205869Sjfv * as it nullifies DMA operations. 8254x just allows RX buffer size to be 3863205869Sjfv * 2048/4096/8192/16384. What we really want is 2048 - ETHER_ALIGN to align its 3864205869Sjfv * payload. On architecures without strict alignment restrictions 8254x still 3865205869Sjfv * performs unaligned memory access which would reduce the performance too. 3866205869Sjfv * To avoid copying over an entire frame to align, we allocate a new mbuf and 3867205869Sjfv * copy ethernet header to the new mbuf. The new mbuf is prepended into the 3868205869Sjfv * existing mbuf chain. 3869205869Sjfv * 3870205869Sjfv * Be aware, best performance of the 8254x is achived only when jumbo frame is 3871205869Sjfv * not used at all on architectures with strict alignment. 3872205869Sjfv */ 3873205869Sjfvstatic int 3874205869Sjfvlem_fixup_rx(struct adapter *adapter) 3875205869Sjfv{ 3876205869Sjfv struct mbuf *m, *n; 3877205869Sjfv int error; 3878205869Sjfv 3879205869Sjfv error = 0; 3880205869Sjfv m = adapter->fmp; 3881205869Sjfv if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN)) { 3882205869Sjfv bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len); 3883205869Sjfv m->m_data += ETHER_HDR_LEN; 3884205869Sjfv } else { 3885243857Sglebius MGETHDR(n, M_NOWAIT, MT_DATA); 3886205869Sjfv if (n != NULL) { 3887205869Sjfv bcopy(m->m_data, n->m_data, ETHER_HDR_LEN); 3888205869Sjfv m->m_data += ETHER_HDR_LEN; 3889205869Sjfv m->m_len -= ETHER_HDR_LEN; 3890205869Sjfv n->m_len = ETHER_HDR_LEN; 3891205869Sjfv M_MOVE_PKTHDR(n, m); 3892205869Sjfv n->m_next = m; 3893205869Sjfv adapter->fmp = n; 3894205869Sjfv } else { 3895205869Sjfv adapter->dropped_pkts++; 3896205869Sjfv m_freem(adapter->fmp); 3897205869Sjfv adapter->fmp = NULL; 3898205869Sjfv error = ENOMEM; 3899205869Sjfv } 3900205869Sjfv } 3901205869Sjfv 3902205869Sjfv return (error); 3903205869Sjfv} 3904205869Sjfv#endif 3905205869Sjfv 3906205869Sjfv/********************************************************************* 3907205869Sjfv * 3908205869Sjfv * Verify that the hardware indicated that the checksum is valid. 3909205869Sjfv * Inform the stack about the status of checksum so that stack 3910205869Sjfv * doesn't spend time verifying the checksum. 3911205869Sjfv * 3912205869Sjfv *********************************************************************/ 3913205869Sjfvstatic void 3914205869Sjfvlem_receive_checksum(struct adapter *adapter, 3915205869Sjfv struct e1000_rx_desc *rx_desc, struct mbuf *mp) 3916205869Sjfv{ 3917205869Sjfv /* 82543 or newer only */ 3918205869Sjfv if ((adapter->hw.mac.type < e1000_82543) || 3919205869Sjfv /* Ignore Checksum bit is set */ 3920205869Sjfv (rx_desc->status & E1000_RXD_STAT_IXSM)) { 3921205869Sjfv mp->m_pkthdr.csum_flags = 0; 3922205869Sjfv return; 3923205869Sjfv } 3924205869Sjfv 3925205869Sjfv if (rx_desc->status & E1000_RXD_STAT_IPCS) { 3926205869Sjfv /* Did it pass? */ 3927205869Sjfv if (!(rx_desc->errors & E1000_RXD_ERR_IPE)) { 3928205869Sjfv /* IP Checksum Good */ 3929205869Sjfv mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; 3930205869Sjfv mp->m_pkthdr.csum_flags |= CSUM_IP_VALID; 3931205869Sjfv 3932205869Sjfv } else { 3933205869Sjfv mp->m_pkthdr.csum_flags = 0; 3934205869Sjfv } 3935205869Sjfv } 3936205869Sjfv 3937205869Sjfv if (rx_desc->status & E1000_RXD_STAT_TCPCS) { 3938205869Sjfv /* Did it pass? */ 3939205869Sjfv if (!(rx_desc->errors & E1000_RXD_ERR_TCPE)) { 3940205869Sjfv mp->m_pkthdr.csum_flags |= 3941205869Sjfv (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); 3942205869Sjfv mp->m_pkthdr.csum_data = htons(0xffff); 3943205869Sjfv } 3944205869Sjfv } 3945205869Sjfv} 3946205869Sjfv 3947205869Sjfv/* 3948205869Sjfv * This routine is run via an vlan 3949205869Sjfv * config EVENT 3950205869Sjfv */ 3951205869Sjfvstatic void 3952205869Sjfvlem_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3953205869Sjfv{ 3954205869Sjfv struct adapter *adapter = ifp->if_softc; 3955205869Sjfv u32 index, bit; 3956205869Sjfv 3957205869Sjfv if (ifp->if_softc != arg) /* Not our event */ 3958205869Sjfv return; 3959205869Sjfv 3960205869Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid ID */ 3961205869Sjfv return; 3962205869Sjfv 3963214646Sjfv EM_CORE_LOCK(adapter); 3964205869Sjfv index = (vtag >> 5) & 0x7F; 3965205869Sjfv bit = vtag & 0x1F; 3966214646Sjfv adapter->shadow_vfta[index] |= (1 << bit); 3967205869Sjfv ++adapter->num_vlans; 3968205869Sjfv /* Re-init to load the changes */ 3969214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 3970214646Sjfv lem_init_locked(adapter); 3971214646Sjfv EM_CORE_UNLOCK(adapter); 3972205869Sjfv} 3973205869Sjfv 3974205869Sjfv/* 3975205869Sjfv * This routine is run via an vlan 3976205869Sjfv * unconfig EVENT 3977205869Sjfv */ 3978205869Sjfvstatic void 3979205869Sjfvlem_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3980205869Sjfv{ 3981205869Sjfv struct adapter *adapter = ifp->if_softc; 3982205869Sjfv u32 index, bit; 3983205869Sjfv 3984205869Sjfv if (ifp->if_softc != arg) 3985205869Sjfv return; 3986205869Sjfv 3987205869Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 3988205869Sjfv return; 3989205869Sjfv 3990214646Sjfv EM_CORE_LOCK(adapter); 3991205869Sjfv index = (vtag >> 5) & 0x7F; 3992205869Sjfv bit = vtag & 0x1F; 3993214646Sjfv adapter->shadow_vfta[index] &= ~(1 << bit); 3994205869Sjfv --adapter->num_vlans; 3995205869Sjfv /* Re-init to load the changes */ 3996214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 3997214646Sjfv lem_init_locked(adapter); 3998214646Sjfv EM_CORE_UNLOCK(adapter); 3999205869Sjfv} 4000205869Sjfv 4001205869Sjfvstatic void 4002205869Sjfvlem_setup_vlan_hw_support(struct adapter *adapter) 4003205869Sjfv{ 4004205869Sjfv struct e1000_hw *hw = &adapter->hw; 4005205869Sjfv u32 reg; 4006205869Sjfv 4007205869Sjfv /* 4008205869Sjfv ** We get here thru init_locked, meaning 4009205869Sjfv ** a soft reset, this has already cleared 4010205869Sjfv ** the VFTA and other state, so if there 4011205869Sjfv ** have been no vlan's registered do nothing. 4012205869Sjfv */ 4013205869Sjfv if (adapter->num_vlans == 0) 4014205869Sjfv return; 4015205869Sjfv 4016205869Sjfv /* 4017205869Sjfv ** A soft reset zero's out the VFTA, so 4018205869Sjfv ** we need to repopulate it now. 4019205869Sjfv */ 4020205869Sjfv for (int i = 0; i < EM_VFTA_SIZE; i++) 4021214646Sjfv if (adapter->shadow_vfta[i] != 0) 4022205869Sjfv E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, 4023214646Sjfv i, adapter->shadow_vfta[i]); 4024205869Sjfv 4025205869Sjfv reg = E1000_READ_REG(hw, E1000_CTRL); 4026205869Sjfv reg |= E1000_CTRL_VME; 4027205869Sjfv E1000_WRITE_REG(hw, E1000_CTRL, reg); 4028205869Sjfv 4029205869Sjfv /* Enable the Filter Table */ 4030205869Sjfv reg = E1000_READ_REG(hw, E1000_RCTL); 4031205869Sjfv reg &= ~E1000_RCTL_CFIEN; 4032205869Sjfv reg |= E1000_RCTL_VFE; 4033205869Sjfv E1000_WRITE_REG(hw, E1000_RCTL, reg); 4034205869Sjfv} 4035205869Sjfv 4036205869Sjfvstatic void 4037205869Sjfvlem_enable_intr(struct adapter *adapter) 4038205869Sjfv{ 4039205869Sjfv struct e1000_hw *hw = &adapter->hw; 4040205869Sjfv u32 ims_mask = IMS_ENABLE_MASK; 4041205869Sjfv 4042205869Sjfv E1000_WRITE_REG(hw, E1000_IMS, ims_mask); 4043205869Sjfv} 4044205869Sjfv 4045205869Sjfvstatic void 4046205869Sjfvlem_disable_intr(struct adapter *adapter) 4047205869Sjfv{ 4048205869Sjfv struct e1000_hw *hw = &adapter->hw; 4049205869Sjfv 4050238953Sjfv E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 4051205869Sjfv} 4052205869Sjfv 4053205869Sjfv/* 4054205869Sjfv * Bit of a misnomer, what this really means is 4055205869Sjfv * to enable OS management of the system... aka 4056205869Sjfv * to disable special hardware management features 4057205869Sjfv */ 4058205869Sjfvstatic void 4059205869Sjfvlem_init_manageability(struct adapter *adapter) 4060205869Sjfv{ 4061205869Sjfv /* A shared code workaround */ 4062205869Sjfv if (adapter->has_manage) { 4063205869Sjfv int manc = E1000_READ_REG(&adapter->hw, E1000_MANC); 4064205869Sjfv /* disable hardware interception of ARP */ 4065205869Sjfv manc &= ~(E1000_MANC_ARP_EN); 4066205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); 4067205869Sjfv } 4068205869Sjfv} 4069205869Sjfv 4070205869Sjfv/* 4071205869Sjfv * Give control back to hardware management 4072205869Sjfv * controller if there is one. 4073205869Sjfv */ 4074205869Sjfvstatic void 4075205869Sjfvlem_release_manageability(struct adapter *adapter) 4076205869Sjfv{ 4077205869Sjfv if (adapter->has_manage) { 4078205869Sjfv int manc = E1000_READ_REG(&adapter->hw, E1000_MANC); 4079205869Sjfv 4080205869Sjfv /* re-enable hardware interception of ARP */ 4081205869Sjfv manc |= E1000_MANC_ARP_EN; 4082205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); 4083205869Sjfv } 4084205869Sjfv} 4085205869Sjfv 4086205869Sjfv/* 4087205869Sjfv * lem_get_hw_control sets the {CTRL_EXT|FWSM}:DRV_LOAD bit. 4088205869Sjfv * For ASF and Pass Through versions of f/w this means 4089205869Sjfv * that the driver is loaded. For AMT version type f/w 4090205869Sjfv * this means that the network i/f is open. 4091205869Sjfv */ 4092205869Sjfvstatic void 4093205869Sjfvlem_get_hw_control(struct adapter *adapter) 4094205869Sjfv{ 4095205869Sjfv u32 ctrl_ext; 4096205869Sjfv 4097205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 4098205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, 4099205869Sjfv ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); 4100205869Sjfv return; 4101205869Sjfv} 4102205869Sjfv 4103205869Sjfv/* 4104205869Sjfv * lem_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit. 4105205869Sjfv * For ASF and Pass Through versions of f/w this means that 4106205869Sjfv * the driver is no longer loaded. For AMT versions of the 4107205869Sjfv * f/w this means that the network i/f is closed. 4108205869Sjfv */ 4109205869Sjfvstatic void 4110205869Sjfvlem_release_hw_control(struct adapter *adapter) 4111205869Sjfv{ 4112205869Sjfv u32 ctrl_ext; 4113205869Sjfv 4114205869Sjfv if (!adapter->has_manage) 4115205869Sjfv return; 4116205869Sjfv 4117205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 4118205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, 4119205869Sjfv ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); 4120205869Sjfv return; 4121205869Sjfv} 4122205869Sjfv 4123205869Sjfvstatic int 4124205869Sjfvlem_is_valid_ether_addr(u8 *addr) 4125205869Sjfv{ 4126205869Sjfv char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; 4127205869Sjfv 4128205869Sjfv if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) { 4129205869Sjfv return (FALSE); 4130205869Sjfv } 4131205869Sjfv 4132205869Sjfv return (TRUE); 4133205869Sjfv} 4134205869Sjfv 4135205869Sjfv/* 4136205869Sjfv** Parse the interface capabilities with regard 4137205869Sjfv** to both system management and wake-on-lan for 4138205869Sjfv** later use. 4139205869Sjfv*/ 4140205869Sjfvstatic void 4141205869Sjfvlem_get_wakeup(device_t dev) 4142205869Sjfv{ 4143205869Sjfv struct adapter *adapter = device_get_softc(dev); 4144205869Sjfv u16 eeprom_data = 0, device_id, apme_mask; 4145205869Sjfv 4146205869Sjfv adapter->has_manage = e1000_enable_mng_pass_thru(&adapter->hw); 4147205869Sjfv apme_mask = EM_EEPROM_APME; 4148205869Sjfv 4149205869Sjfv switch (adapter->hw.mac.type) { 4150205869Sjfv case e1000_82542: 4151205869Sjfv case e1000_82543: 4152205869Sjfv break; 4153205869Sjfv case e1000_82544: 4154205869Sjfv e1000_read_nvm(&adapter->hw, 4155205869Sjfv NVM_INIT_CONTROL2_REG, 1, &eeprom_data); 4156205869Sjfv apme_mask = EM_82544_APME; 4157205869Sjfv break; 4158205869Sjfv case e1000_82546: 4159205869Sjfv case e1000_82546_rev_3: 4160205869Sjfv if (adapter->hw.bus.func == 1) { 4161205869Sjfv e1000_read_nvm(&adapter->hw, 4162205869Sjfv NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); 4163205869Sjfv break; 4164205869Sjfv } else 4165205869Sjfv e1000_read_nvm(&adapter->hw, 4166205869Sjfv NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); 4167205869Sjfv break; 4168205869Sjfv default: 4169205869Sjfv e1000_read_nvm(&adapter->hw, 4170205869Sjfv NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); 4171205869Sjfv break; 4172205869Sjfv } 4173205869Sjfv if (eeprom_data & apme_mask) 4174205869Sjfv adapter->wol = (E1000_WUFC_MAG | E1000_WUFC_MC); 4175205869Sjfv /* 4176205869Sjfv * We have the eeprom settings, now apply the special cases 4177205869Sjfv * where the eeprom may be wrong or the board won't support 4178205869Sjfv * wake on lan on a particular port 4179205869Sjfv */ 4180205869Sjfv device_id = pci_get_device(dev); 4181205869Sjfv switch (device_id) { 4182205869Sjfv case E1000_DEV_ID_82546GB_PCIE: 4183205869Sjfv adapter->wol = 0; 4184205869Sjfv break; 4185205869Sjfv case E1000_DEV_ID_82546EB_FIBER: 4186205869Sjfv case E1000_DEV_ID_82546GB_FIBER: 4187205869Sjfv /* Wake events only supported on port A for dual fiber 4188205869Sjfv * regardless of eeprom setting */ 4189205869Sjfv if (E1000_READ_REG(&adapter->hw, E1000_STATUS) & 4190205869Sjfv E1000_STATUS_FUNC_1) 4191205869Sjfv adapter->wol = 0; 4192205869Sjfv break; 4193205869Sjfv case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: 4194205869Sjfv /* if quad port adapter, disable WoL on all but port A */ 4195205869Sjfv if (global_quad_port_a != 0) 4196205869Sjfv adapter->wol = 0; 4197205869Sjfv /* Reset for multiple quad port adapters */ 4198205869Sjfv if (++global_quad_port_a == 4) 4199205869Sjfv global_quad_port_a = 0; 4200205869Sjfv break; 4201205869Sjfv } 4202205869Sjfv return; 4203205869Sjfv} 4204205869Sjfv 4205205869Sjfv 4206205869Sjfv/* 4207205869Sjfv * Enable PCI Wake On Lan capability 4208205869Sjfv */ 4209206001Smariusstatic void 4210205869Sjfvlem_enable_wakeup(device_t dev) 4211205869Sjfv{ 4212205869Sjfv struct adapter *adapter = device_get_softc(dev); 4213205869Sjfv struct ifnet *ifp = adapter->ifp; 4214205869Sjfv u32 pmc, ctrl, ctrl_ext, rctl; 4215205869Sjfv u16 status; 4216205869Sjfv 4217219902Sjhb if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0)) 4218205869Sjfv return; 4219205869Sjfv 4220205869Sjfv /* Advertise the wakeup capability */ 4221205869Sjfv ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); 4222205869Sjfv ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); 4223205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); 4224205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); 4225205869Sjfv 4226205869Sjfv /* Keep the laser running on Fiber adapters */ 4227205869Sjfv if (adapter->hw.phy.media_type == e1000_media_type_fiber || 4228205869Sjfv adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { 4229205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 4230205869Sjfv ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; 4231205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext); 4232205869Sjfv } 4233205869Sjfv 4234205869Sjfv /* 4235205869Sjfv ** Determine type of Wakeup: note that wol 4236205869Sjfv ** is set with all bits on by default. 4237205869Sjfv */ 4238205869Sjfv if ((ifp->if_capenable & IFCAP_WOL_MAGIC) == 0) 4239205869Sjfv adapter->wol &= ~E1000_WUFC_MAG; 4240205869Sjfv 4241205869Sjfv if ((ifp->if_capenable & IFCAP_WOL_MCAST) == 0) 4242205869Sjfv adapter->wol &= ~E1000_WUFC_MC; 4243205869Sjfv else { 4244205869Sjfv rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 4245205869Sjfv rctl |= E1000_RCTL_MPE; 4246205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); 4247205869Sjfv } 4248205869Sjfv 4249205869Sjfv if (adapter->hw.mac.type == e1000_pchlan) { 4250205869Sjfv if (lem_enable_phy_wakeup(adapter)) 4251205869Sjfv return; 4252205869Sjfv } else { 4253205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); 4254205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol); 4255205869Sjfv } 4256205869Sjfv 4257205869Sjfv 4258205869Sjfv /* Request PME */ 4259205869Sjfv status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2); 4260205869Sjfv status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); 4261205869Sjfv if (ifp->if_capenable & IFCAP_WOL) 4262205869Sjfv status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; 4263205869Sjfv pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2); 4264205869Sjfv 4265205869Sjfv return; 4266205869Sjfv} 4267205869Sjfv 4268205869Sjfv/* 4269205869Sjfv** WOL in the newer chipset interfaces (pchlan) 4270205869Sjfv** require thing to be copied into the phy 4271205869Sjfv*/ 4272205869Sjfvstatic int 4273205869Sjfvlem_enable_phy_wakeup(struct adapter *adapter) 4274205869Sjfv{ 4275205869Sjfv struct e1000_hw *hw = &adapter->hw; 4276205869Sjfv u32 mreg, ret = 0; 4277205869Sjfv u16 preg; 4278205869Sjfv 4279205869Sjfv /* copy MAC RARs to PHY RARs */ 4280205869Sjfv for (int i = 0; i < adapter->hw.mac.rar_entry_count; i++) { 4281205869Sjfv mreg = E1000_READ_REG(hw, E1000_RAL(i)); 4282205869Sjfv e1000_write_phy_reg(hw, BM_RAR_L(i), (u16)(mreg & 0xFFFF)); 4283205869Sjfv e1000_write_phy_reg(hw, BM_RAR_M(i), 4284205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4285205869Sjfv mreg = E1000_READ_REG(hw, E1000_RAH(i)); 4286205869Sjfv e1000_write_phy_reg(hw, BM_RAR_H(i), (u16)(mreg & 0xFFFF)); 4287205869Sjfv e1000_write_phy_reg(hw, BM_RAR_CTRL(i), 4288205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4289205869Sjfv } 4290205869Sjfv 4291205869Sjfv /* copy MAC MTA to PHY MTA */ 4292205869Sjfv for (int i = 0; i < adapter->hw.mac.mta_reg_count; i++) { 4293205869Sjfv mreg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); 4294205869Sjfv e1000_write_phy_reg(hw, BM_MTA(i), (u16)(mreg & 0xFFFF)); 4295205869Sjfv e1000_write_phy_reg(hw, BM_MTA(i) + 1, 4296205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4297205869Sjfv } 4298205869Sjfv 4299205869Sjfv /* configure PHY Rx Control register */ 4300205869Sjfv e1000_read_phy_reg(&adapter->hw, BM_RCTL, &preg); 4301205869Sjfv mreg = E1000_READ_REG(hw, E1000_RCTL); 4302205869Sjfv if (mreg & E1000_RCTL_UPE) 4303205869Sjfv preg |= BM_RCTL_UPE; 4304205869Sjfv if (mreg & E1000_RCTL_MPE) 4305205869Sjfv preg |= BM_RCTL_MPE; 4306205869Sjfv preg &= ~(BM_RCTL_MO_MASK); 4307205869Sjfv if (mreg & E1000_RCTL_MO_3) 4308205869Sjfv preg |= (((mreg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) 4309205869Sjfv << BM_RCTL_MO_SHIFT); 4310205869Sjfv if (mreg & E1000_RCTL_BAM) 4311205869Sjfv preg |= BM_RCTL_BAM; 4312205869Sjfv if (mreg & E1000_RCTL_PMCF) 4313205869Sjfv preg |= BM_RCTL_PMCF; 4314205869Sjfv mreg = E1000_READ_REG(hw, E1000_CTRL); 4315205869Sjfv if (mreg & E1000_CTRL_RFCE) 4316205869Sjfv preg |= BM_RCTL_RFCE; 4317205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_RCTL, preg); 4318205869Sjfv 4319205869Sjfv /* enable PHY wakeup in MAC register */ 4320205869Sjfv E1000_WRITE_REG(hw, E1000_WUC, 4321205869Sjfv E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); 4322205869Sjfv E1000_WRITE_REG(hw, E1000_WUFC, adapter->wol); 4323205869Sjfv 4324205869Sjfv /* configure and enable PHY wakeup in PHY registers */ 4325205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_WUFC, adapter->wol); 4326205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); 4327205869Sjfv 4328205869Sjfv /* activate PHY wakeup */ 4329205869Sjfv ret = hw->phy.ops.acquire(hw); 4330205869Sjfv if (ret) { 4331205869Sjfv printf("Could not acquire PHY\n"); 4332205869Sjfv return ret; 4333205869Sjfv } 4334205869Sjfv e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 4335205869Sjfv (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); 4336205869Sjfv ret = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &preg); 4337205869Sjfv if (ret) { 4338205869Sjfv printf("Could not read PHY page 769\n"); 4339205869Sjfv goto out; 4340205869Sjfv } 4341205869Sjfv preg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; 4342205869Sjfv ret = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, preg); 4343205869Sjfv if (ret) 4344205869Sjfv printf("Could not set PHY Host Wakeup bit\n"); 4345205869Sjfvout: 4346205869Sjfv hw->phy.ops.release(hw); 4347205869Sjfv 4348205869Sjfv return ret; 4349205869Sjfv} 4350205869Sjfv 4351206001Smariusstatic void 4352206001Smariuslem_led_func(void *arg, int onoff) 4353206001Smarius{ 4354206001Smarius struct adapter *adapter = arg; 4355205869Sjfv 4356206001Smarius EM_CORE_LOCK(adapter); 4357206001Smarius if (onoff) { 4358206001Smarius e1000_setup_led(&adapter->hw); 4359206001Smarius e1000_led_on(&adapter->hw); 4360206001Smarius } else { 4361206001Smarius e1000_led_off(&adapter->hw); 4362206001Smarius e1000_cleanup_led(&adapter->hw); 4363206001Smarius } 4364206001Smarius EM_CORE_UNLOCK(adapter); 4365206001Smarius} 4366206001Smarius 4367205869Sjfv/********************************************************************* 4368205869Sjfv* 82544 Coexistence issue workaround. 4369205869Sjfv* There are 2 issues. 4370205869Sjfv* 1. Transmit Hang issue. 4371205869Sjfv* To detect this issue, following equation can be used... 4372205869Sjfv* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 4373205869Sjfv* If SUM[3:0] is in between 1 to 4, we will have this issue. 4374205869Sjfv* 4375205869Sjfv* 2. DAC issue. 4376205869Sjfv* To detect this issue, following equation can be used... 4377205869Sjfv* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 4378205869Sjfv* If SUM[3:0] is in between 9 to c, we will have this issue. 4379205869Sjfv* 4380205869Sjfv* 4381205869Sjfv* WORKAROUND: 4382205869Sjfv* Make sure we do not have ending address 4383205869Sjfv* as 1,2,3,4(Hang) or 9,a,b,c (DAC) 4384205869Sjfv* 4385205869Sjfv*************************************************************************/ 4386205869Sjfvstatic u32 4387205869Sjfvlem_fill_descriptors (bus_addr_t address, u32 length, 4388205869Sjfv PDESC_ARRAY desc_array) 4389205869Sjfv{ 4390205869Sjfv u32 safe_terminator; 4391205869Sjfv 4392205869Sjfv /* Since issue is sensitive to length and address.*/ 4393205869Sjfv /* Let us first check the address...*/ 4394205869Sjfv if (length <= 4) { 4395205869Sjfv desc_array->descriptor[0].address = address; 4396205869Sjfv desc_array->descriptor[0].length = length; 4397205869Sjfv desc_array->elements = 1; 4398205869Sjfv return (desc_array->elements); 4399205869Sjfv } 4400205869Sjfv safe_terminator = (u32)((((u32)address & 0x7) + 4401205869Sjfv (length & 0xF)) & 0xF); 4402205869Sjfv /* if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then return */ 4403205869Sjfv if (safe_terminator == 0 || 4404205869Sjfv (safe_terminator > 4 && 4405205869Sjfv safe_terminator < 9) || 4406205869Sjfv (safe_terminator > 0xC && 4407205869Sjfv safe_terminator <= 0xF)) { 4408205869Sjfv desc_array->descriptor[0].address = address; 4409205869Sjfv desc_array->descriptor[0].length = length; 4410205869Sjfv desc_array->elements = 1; 4411205869Sjfv return (desc_array->elements); 4412205869Sjfv } 4413205869Sjfv 4414205869Sjfv desc_array->descriptor[0].address = address; 4415205869Sjfv desc_array->descriptor[0].length = length - 4; 4416205869Sjfv desc_array->descriptor[1].address = address + (length - 4); 4417205869Sjfv desc_array->descriptor[1].length = 4; 4418205869Sjfv desc_array->elements = 2; 4419205869Sjfv return (desc_array->elements); 4420205869Sjfv} 4421205869Sjfv 4422205869Sjfv/********************************************************************** 4423205869Sjfv * 4424205869Sjfv * Update the board statistics counters. 4425205869Sjfv * 4426205869Sjfv **********************************************************************/ 4427205869Sjfvstatic void 4428205869Sjfvlem_update_stats_counters(struct adapter *adapter) 4429205869Sjfv{ 4430205869Sjfv struct ifnet *ifp; 4431205869Sjfv 4432205869Sjfv if(adapter->hw.phy.media_type == e1000_media_type_copper || 4433205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_STATUS) & E1000_STATUS_LU)) { 4434205869Sjfv adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, E1000_SYMERRS); 4435205869Sjfv adapter->stats.sec += E1000_READ_REG(&adapter->hw, E1000_SEC); 4436205869Sjfv } 4437205869Sjfv adapter->stats.crcerrs += E1000_READ_REG(&adapter->hw, E1000_CRCERRS); 4438205869Sjfv adapter->stats.mpc += E1000_READ_REG(&adapter->hw, E1000_MPC); 4439205869Sjfv adapter->stats.scc += E1000_READ_REG(&adapter->hw, E1000_SCC); 4440205869Sjfv adapter->stats.ecol += E1000_READ_REG(&adapter->hw, E1000_ECOL); 4441205869Sjfv 4442205869Sjfv adapter->stats.mcc += E1000_READ_REG(&adapter->hw, E1000_MCC); 4443205869Sjfv adapter->stats.latecol += E1000_READ_REG(&adapter->hw, E1000_LATECOL); 4444205869Sjfv adapter->stats.colc += E1000_READ_REG(&adapter->hw, E1000_COLC); 4445205869Sjfv adapter->stats.dc += E1000_READ_REG(&adapter->hw, E1000_DC); 4446205869Sjfv adapter->stats.rlec += E1000_READ_REG(&adapter->hw, E1000_RLEC); 4447205869Sjfv adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, E1000_XONRXC); 4448205869Sjfv adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, E1000_XONTXC); 4449205869Sjfv adapter->stats.xoffrxc += E1000_READ_REG(&adapter->hw, E1000_XOFFRXC); 4450205869Sjfv adapter->stats.xofftxc += E1000_READ_REG(&adapter->hw, E1000_XOFFTXC); 4451205869Sjfv adapter->stats.fcruc += E1000_READ_REG(&adapter->hw, E1000_FCRUC); 4452205869Sjfv adapter->stats.prc64 += E1000_READ_REG(&adapter->hw, E1000_PRC64); 4453205869Sjfv adapter->stats.prc127 += E1000_READ_REG(&adapter->hw, E1000_PRC127); 4454205869Sjfv adapter->stats.prc255 += E1000_READ_REG(&adapter->hw, E1000_PRC255); 4455205869Sjfv adapter->stats.prc511 += E1000_READ_REG(&adapter->hw, E1000_PRC511); 4456205869Sjfv adapter->stats.prc1023 += E1000_READ_REG(&adapter->hw, E1000_PRC1023); 4457205869Sjfv adapter->stats.prc1522 += E1000_READ_REG(&adapter->hw, E1000_PRC1522); 4458205869Sjfv adapter->stats.gprc += E1000_READ_REG(&adapter->hw, E1000_GPRC); 4459205869Sjfv adapter->stats.bprc += E1000_READ_REG(&adapter->hw, E1000_BPRC); 4460205869Sjfv adapter->stats.mprc += E1000_READ_REG(&adapter->hw, E1000_MPRC); 4461205869Sjfv adapter->stats.gptc += E1000_READ_REG(&adapter->hw, E1000_GPTC); 4462205869Sjfv 4463205869Sjfv /* For the 64-bit byte counters the low dword must be read first. */ 4464205869Sjfv /* Both registers clear on the read of the high dword */ 4465205869Sjfv 4466212902Sjhb adapter->stats.gorc += E1000_READ_REG(&adapter->hw, E1000_GORCL) + 4467212902Sjhb ((u64)E1000_READ_REG(&adapter->hw, E1000_GORCH) << 32); 4468212902Sjhb adapter->stats.gotc += E1000_READ_REG(&adapter->hw, E1000_GOTCL) + 4469212902Sjhb ((u64)E1000_READ_REG(&adapter->hw, E1000_GOTCH) << 32); 4470205869Sjfv 4471205869Sjfv adapter->stats.rnbc += E1000_READ_REG(&adapter->hw, E1000_RNBC); 4472205869Sjfv adapter->stats.ruc += E1000_READ_REG(&adapter->hw, E1000_RUC); 4473205869Sjfv adapter->stats.rfc += E1000_READ_REG(&adapter->hw, E1000_RFC); 4474205869Sjfv adapter->stats.roc += E1000_READ_REG(&adapter->hw, E1000_ROC); 4475205869Sjfv adapter->stats.rjc += E1000_READ_REG(&adapter->hw, E1000_RJC); 4476205869Sjfv 4477205869Sjfv adapter->stats.tor += E1000_READ_REG(&adapter->hw, E1000_TORH); 4478205869Sjfv adapter->stats.tot += E1000_READ_REG(&adapter->hw, E1000_TOTH); 4479205869Sjfv 4480205869Sjfv adapter->stats.tpr += E1000_READ_REG(&adapter->hw, E1000_TPR); 4481205869Sjfv adapter->stats.tpt += E1000_READ_REG(&adapter->hw, E1000_TPT); 4482205869Sjfv adapter->stats.ptc64 += E1000_READ_REG(&adapter->hw, E1000_PTC64); 4483205869Sjfv adapter->stats.ptc127 += E1000_READ_REG(&adapter->hw, E1000_PTC127); 4484205869Sjfv adapter->stats.ptc255 += E1000_READ_REG(&adapter->hw, E1000_PTC255); 4485205869Sjfv adapter->stats.ptc511 += E1000_READ_REG(&adapter->hw, E1000_PTC511); 4486205869Sjfv adapter->stats.ptc1023 += E1000_READ_REG(&adapter->hw, E1000_PTC1023); 4487205869Sjfv adapter->stats.ptc1522 += E1000_READ_REG(&adapter->hw, E1000_PTC1522); 4488205869Sjfv adapter->stats.mptc += E1000_READ_REG(&adapter->hw, E1000_MPTC); 4489205869Sjfv adapter->stats.bptc += E1000_READ_REG(&adapter->hw, E1000_BPTC); 4490205869Sjfv 4491205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 4492205869Sjfv adapter->stats.algnerrc += 4493205869Sjfv E1000_READ_REG(&adapter->hw, E1000_ALGNERRC); 4494205869Sjfv adapter->stats.rxerrc += 4495205869Sjfv E1000_READ_REG(&adapter->hw, E1000_RXERRC); 4496205869Sjfv adapter->stats.tncrs += 4497205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TNCRS); 4498205869Sjfv adapter->stats.cexterr += 4499205869Sjfv E1000_READ_REG(&adapter->hw, E1000_CEXTERR); 4500205869Sjfv adapter->stats.tsctc += 4501205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TSCTC); 4502205869Sjfv adapter->stats.tsctfc += 4503205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TSCTFC); 4504205869Sjfv } 4505205869Sjfv ifp = adapter->ifp; 4506205869Sjfv 4507205869Sjfv ifp->if_collisions = adapter->stats.colc; 4508205869Sjfv 4509205869Sjfv /* Rx Errors */ 4510205869Sjfv ifp->if_ierrors = adapter->dropped_pkts + adapter->stats.rxerrc + 4511205869Sjfv adapter->stats.crcerrs + adapter->stats.algnerrc + 4512205869Sjfv adapter->stats.ruc + adapter->stats.roc + 4513205869Sjfv adapter->stats.mpc + adapter->stats.cexterr; 4514205869Sjfv 4515205869Sjfv /* Tx Errors */ 4516205869Sjfv ifp->if_oerrors = adapter->stats.ecol + 4517205869Sjfv adapter->stats.latecol + adapter->watchdog_events; 4518205869Sjfv} 4519205869Sjfv 4520212902Sjhb/* Export a single 32-bit register via a read-only sysctl. */ 4521212902Sjhbstatic int 4522212902Sjhblem_sysctl_reg_handler(SYSCTL_HANDLER_ARGS) 4523205869Sjfv{ 4524212902Sjhb struct adapter *adapter; 4525212902Sjhb u_int val; 4526205869Sjfv 4527212902Sjhb adapter = oidp->oid_arg1; 4528212902Sjhb val = E1000_READ_REG(&adapter->hw, oidp->oid_arg2); 4529212902Sjhb return (sysctl_handle_int(oidp, &val, 0, req)); 4530205869Sjfv} 4531205869Sjfv 4532212902Sjhb/* 4533212902Sjhb * Add sysctl variables, one per statistic, to the system. 4534212902Sjhb */ 4535205869Sjfvstatic void 4536212902Sjhblem_add_hw_stats(struct adapter *adapter) 4537205869Sjfv{ 4538205869Sjfv device_t dev = adapter->dev; 4539205869Sjfv 4540212902Sjhb struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 4541212902Sjhb struct sysctl_oid *tree = device_get_sysctl_tree(dev); 4542212902Sjhb struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 4543212902Sjhb struct e1000_hw_stats *stats = &adapter->stats; 4544212902Sjhb 4545212902Sjhb struct sysctl_oid *stat_node; 4546212902Sjhb struct sysctl_oid_list *stat_list; 4547212902Sjhb 4548212902Sjhb /* Driver Statistics */ 4549212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail", 4550212902Sjhb CTLFLAG_RD, &adapter->mbuf_cluster_failed, 4551212902Sjhb "Std mbuf cluster failed"); 4552294958Smarius SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail", 4553294958Smarius CTLFLAG_RD, &adapter->mbuf_defrag_failed, 4554294958Smarius "Defragmenting mbuf chain failed"); 4555212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 4556212902Sjhb CTLFLAG_RD, &adapter->dropped_pkts, 4557212902Sjhb "Driver dropped packets"); 4558212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail", 4559212902Sjhb CTLFLAG_RD, &adapter->no_tx_dma_setup, 4560212902Sjhb "Driver tx dma failure in xmit"); 4561212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_desc_fail1", 4562212902Sjhb CTLFLAG_RD, &adapter->no_tx_desc_avail1, 4563212902Sjhb "Not enough tx descriptors failure in xmit"); 4564212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_desc_fail2", 4565212902Sjhb CTLFLAG_RD, &adapter->no_tx_desc_avail2, 4566212902Sjhb "Not enough tx descriptors failure in xmit"); 4567212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns", 4568212902Sjhb CTLFLAG_RD, &adapter->rx_overruns, 4569212902Sjhb "RX overruns"); 4570212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_timeouts", 4571212902Sjhb CTLFLAG_RD, &adapter->watchdog_events, 4572212902Sjhb "Watchdog timeouts"); 4573212902Sjhb 4574212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "device_control", 4575217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_CTRL, 4576212902Sjhb lem_sysctl_reg_handler, "IU", 4577212902Sjhb "Device Control Register"); 4578212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_control", 4579217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RCTL, 4580212902Sjhb lem_sysctl_reg_handler, "IU", 4581212902Sjhb "Receiver Control Register"); 4582212902Sjhb SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_high_water", 4583212902Sjhb CTLFLAG_RD, &adapter->hw.fc.high_water, 0, 4584212902Sjhb "Flow Control High Watermark"); 4585212902Sjhb SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_low_water", 4586212902Sjhb CTLFLAG_RD, &adapter->hw.fc.low_water, 0, 4587212902Sjhb "Flow Control Low Watermark"); 4588217318Smdf SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_workaround", 4589212902Sjhb CTLFLAG_RD, &adapter->tx_fifo_wrk_cnt, 4590212902Sjhb "TX FIFO workaround events"); 4591217318Smdf SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_reset", 4592212902Sjhb CTLFLAG_RD, &adapter->tx_fifo_reset_cnt, 4593212902Sjhb "TX FIFO resets"); 4594212902Sjhb 4595212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_head", 4596217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDH(0), 4597212902Sjhb lem_sysctl_reg_handler, "IU", 4598212902Sjhb "Transmit Descriptor Head"); 4599212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_tail", 4600217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDT(0), 4601212902Sjhb lem_sysctl_reg_handler, "IU", 4602212902Sjhb "Transmit Descriptor Tail"); 4603212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_head", 4604217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDH(0), 4605212902Sjhb lem_sysctl_reg_handler, "IU", 4606212902Sjhb "Receive Descriptor Head"); 4607212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_tail", 4608217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDT(0), 4609212902Sjhb lem_sysctl_reg_handler, "IU", 4610212902Sjhb "Receive Descriptor Tail"); 4611212902Sjhb 4612212902Sjhb 4613212902Sjhb /* MAC stats get their own sub node */ 4614212902Sjhb 4615212902Sjhb stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 4616212902Sjhb CTLFLAG_RD, NULL, "Statistics"); 4617212902Sjhb stat_list = SYSCTL_CHILDREN(stat_node); 4618212902Sjhb 4619217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "excess_coll", 4620212902Sjhb CTLFLAG_RD, &stats->ecol, 4621212902Sjhb "Excessive collisions"); 4622217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "single_coll", 4623212902Sjhb CTLFLAG_RD, &stats->scc, 4624212902Sjhb "Single collisions"); 4625217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "multiple_coll", 4626212902Sjhb CTLFLAG_RD, &stats->mcc, 4627212902Sjhb "Multiple collisions"); 4628217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "late_coll", 4629212902Sjhb CTLFLAG_RD, &stats->latecol, 4630212902Sjhb "Late collisions"); 4631217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "collision_count", 4632212902Sjhb CTLFLAG_RD, &stats->colc, 4633212902Sjhb "Collision Count"); 4634217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "symbol_errors", 4635212902Sjhb CTLFLAG_RD, &adapter->stats.symerrs, 4636212902Sjhb "Symbol Errors"); 4637217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "sequence_errors", 4638212902Sjhb CTLFLAG_RD, &adapter->stats.sec, 4639212902Sjhb "Sequence Errors"); 4640217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "defer_count", 4641212902Sjhb CTLFLAG_RD, &adapter->stats.dc, 4642212902Sjhb "Defer Count"); 4643217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "missed_packets", 4644212902Sjhb CTLFLAG_RD, &adapter->stats.mpc, 4645212902Sjhb "Missed Packets"); 4646217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_no_buff", 4647212902Sjhb CTLFLAG_RD, &adapter->stats.rnbc, 4648212902Sjhb "Receive No Buffers"); 4649217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersize", 4650212902Sjhb CTLFLAG_RD, &adapter->stats.ruc, 4651212902Sjhb "Receive Undersize"); 4652217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", 4653212902Sjhb CTLFLAG_RD, &adapter->stats.rfc, 4654212902Sjhb "Fragmented Packets Received "); 4655217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversize", 4656212902Sjhb CTLFLAG_RD, &adapter->stats.roc, 4657212902Sjhb "Oversized Packets Received"); 4658217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabber", 4659212902Sjhb CTLFLAG_RD, &adapter->stats.rjc, 4660212902Sjhb "Recevied Jabber"); 4661217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_errs", 4662212902Sjhb CTLFLAG_RD, &adapter->stats.rxerrc, 4663212902Sjhb "Receive Errors"); 4664217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", 4665212902Sjhb CTLFLAG_RD, &adapter->stats.crcerrs, 4666212902Sjhb "CRC errors"); 4667217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "alignment_errs", 4668212902Sjhb CTLFLAG_RD, &adapter->stats.algnerrc, 4669212902Sjhb "Alignment Errors"); 4670217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs", 4671212902Sjhb CTLFLAG_RD, &adapter->stats.cexterr, 4672212902Sjhb "Collision/Carrier extension errors"); 4673217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", 4674212902Sjhb CTLFLAG_RD, &adapter->stats.xonrxc, 4675212902Sjhb "XON Received"); 4676217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", 4677212902Sjhb CTLFLAG_RD, &adapter->stats.xontxc, 4678212902Sjhb "XON Transmitted"); 4679217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", 4680212902Sjhb CTLFLAG_RD, &adapter->stats.xoffrxc, 4681212902Sjhb "XOFF Received"); 4682217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", 4683212902Sjhb CTLFLAG_RD, &adapter->stats.xofftxc, 4684212902Sjhb "XOFF Transmitted"); 4685212902Sjhb 4686212902Sjhb /* Packet Reception Stats */ 4687217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd", 4688212902Sjhb CTLFLAG_RD, &adapter->stats.tpr, 4689212902Sjhb "Total Packets Received "); 4690217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd", 4691212902Sjhb CTLFLAG_RD, &adapter->stats.gprc, 4692212902Sjhb "Good Packets Received"); 4693217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd", 4694212902Sjhb CTLFLAG_RD, &adapter->stats.bprc, 4695212902Sjhb "Broadcast Packets Received"); 4696217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd", 4697212902Sjhb CTLFLAG_RD, &adapter->stats.mprc, 4698212902Sjhb "Multicast Packets Received"); 4699217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", 4700212902Sjhb CTLFLAG_RD, &adapter->stats.prc64, 4701212902Sjhb "64 byte frames received "); 4702217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", 4703212902Sjhb CTLFLAG_RD, &adapter->stats.prc127, 4704212902Sjhb "65-127 byte frames received"); 4705217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", 4706212902Sjhb CTLFLAG_RD, &adapter->stats.prc255, 4707212902Sjhb "128-255 byte frames received"); 4708217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", 4709212902Sjhb CTLFLAG_RD, &adapter->stats.prc511, 4710212902Sjhb "256-511 byte frames received"); 4711217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", 4712212902Sjhb CTLFLAG_RD, &adapter->stats.prc1023, 4713212902Sjhb "512-1023 byte frames received"); 4714217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", 4715212902Sjhb CTLFLAG_RD, &adapter->stats.prc1522, 4716212902Sjhb "1023-1522 byte frames received"); 4717217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd", 4718212902Sjhb CTLFLAG_RD, &adapter->stats.gorc, 4719212902Sjhb "Good Octets Received"); 4720212902Sjhb 4721212902Sjhb /* Packet Transmission Stats */ 4722217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 4723212902Sjhb CTLFLAG_RD, &adapter->stats.gotc, 4724212902Sjhb "Good Octets Transmitted"); 4725217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", 4726212902Sjhb CTLFLAG_RD, &adapter->stats.tpt, 4727212902Sjhb "Total Packets Transmitted"); 4728217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 4729212902Sjhb CTLFLAG_RD, &adapter->stats.gptc, 4730212902Sjhb "Good Packets Transmitted"); 4731217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 4732212902Sjhb CTLFLAG_RD, &adapter->stats.bptc, 4733212902Sjhb "Broadcast Packets Transmitted"); 4734217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 4735212902Sjhb CTLFLAG_RD, &adapter->stats.mptc, 4736212902Sjhb "Multicast Packets Transmitted"); 4737217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", 4738212902Sjhb CTLFLAG_RD, &adapter->stats.ptc64, 4739212902Sjhb "64 byte frames transmitted "); 4740217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", 4741212902Sjhb CTLFLAG_RD, &adapter->stats.ptc127, 4742212902Sjhb "65-127 byte frames transmitted"); 4743217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", 4744212902Sjhb CTLFLAG_RD, &adapter->stats.ptc255, 4745212902Sjhb "128-255 byte frames transmitted"); 4746217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", 4747212902Sjhb CTLFLAG_RD, &adapter->stats.ptc511, 4748212902Sjhb "256-511 byte frames transmitted"); 4749217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", 4750212902Sjhb CTLFLAG_RD, &adapter->stats.ptc1023, 4751212902Sjhb "512-1023 byte frames transmitted"); 4752217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", 4753212902Sjhb CTLFLAG_RD, &adapter->stats.ptc1522, 4754212902Sjhb "1024-1522 byte frames transmitted"); 4755217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_txd", 4756212902Sjhb CTLFLAG_RD, &adapter->stats.tsctc, 4757212902Sjhb "TSO Contexts Transmitted"); 4758217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail", 4759212902Sjhb CTLFLAG_RD, &adapter->stats.tsctfc, 4760212902Sjhb "TSO Contexts Failed"); 4761205869Sjfv} 4762205869Sjfv 4763205869Sjfv/********************************************************************** 4764205869Sjfv * 4765205869Sjfv * This routine provides a way to dump out the adapter eeprom, 4766205869Sjfv * often a useful debug/service tool. This only dumps the first 4767205869Sjfv * 32 words, stuff that matters is in that extent. 4768205869Sjfv * 4769205869Sjfv **********************************************************************/ 4770205869Sjfv 4771205869Sjfvstatic int 4772212902Sjhblem_sysctl_nvm_info(SYSCTL_HANDLER_ARGS) 4773205869Sjfv{ 4774205869Sjfv struct adapter *adapter; 4775205869Sjfv int error; 4776205869Sjfv int result; 4777205869Sjfv 4778205869Sjfv result = -1; 4779205869Sjfv error = sysctl_handle_int(oidp, &result, 0, req); 4780205869Sjfv 4781205869Sjfv if (error || !req->newptr) 4782205869Sjfv return (error); 4783205869Sjfv 4784205869Sjfv /* 4785205869Sjfv * This value will cause a hex dump of the 4786205869Sjfv * first 32 16-bit words of the EEPROM to 4787205869Sjfv * the screen. 4788205869Sjfv */ 4789212902Sjhb if (result == 1) { 4790205869Sjfv adapter = (struct adapter *)arg1; 4791205869Sjfv lem_print_nvm_info(adapter); 4792205869Sjfv } 4793205869Sjfv 4794205869Sjfv return (error); 4795205869Sjfv} 4796205869Sjfv 4797212902Sjhbstatic void 4798212902Sjhblem_print_nvm_info(struct adapter *adapter) 4799205869Sjfv{ 4800212902Sjhb u16 eeprom_data; 4801212902Sjhb int i, j, row = 0; 4802205869Sjfv 4803212902Sjhb /* Its a bit crude, but it gets the job done */ 4804212902Sjhb printf("\nInterface EEPROM Dump:\n"); 4805212902Sjhb printf("Offset\n0x0000 "); 4806212902Sjhb for (i = 0, j = 0; i < 32; i++, j++) { 4807212902Sjhb if (j == 8) { /* Make the offset block */ 4808212902Sjhb j = 0; ++row; 4809212902Sjhb printf("\n0x00%x0 ",row); 4810212902Sjhb } 4811212902Sjhb e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data); 4812212902Sjhb printf("%04x ", eeprom_data); 4813205869Sjfv } 4814212902Sjhb printf("\n"); 4815205869Sjfv} 4816205869Sjfv 4817205869Sjfvstatic int 4818205869Sjfvlem_sysctl_int_delay(SYSCTL_HANDLER_ARGS) 4819205869Sjfv{ 4820205869Sjfv struct em_int_delay_info *info; 4821205869Sjfv struct adapter *adapter; 4822205869Sjfv u32 regval; 4823205869Sjfv int error; 4824205869Sjfv int usecs; 4825205869Sjfv int ticks; 4826205869Sjfv 4827205869Sjfv info = (struct em_int_delay_info *)arg1; 4828205869Sjfv usecs = info->value; 4829205869Sjfv error = sysctl_handle_int(oidp, &usecs, 0, req); 4830205869Sjfv if (error != 0 || req->newptr == NULL) 4831205869Sjfv return (error); 4832205869Sjfv if (usecs < 0 || usecs > EM_TICKS_TO_USECS(65535)) 4833205869Sjfv return (EINVAL); 4834205869Sjfv info->value = usecs; 4835205869Sjfv ticks = EM_USECS_TO_TICKS(usecs); 4836250414Sluigi if (info->offset == E1000_ITR) /* units are 256ns here */ 4837250414Sluigi ticks *= 4; 4838205869Sjfv 4839205869Sjfv adapter = info->adapter; 4840205869Sjfv 4841205869Sjfv EM_CORE_LOCK(adapter); 4842205869Sjfv regval = E1000_READ_OFFSET(&adapter->hw, info->offset); 4843205869Sjfv regval = (regval & ~0xffff) | (ticks & 0xffff); 4844205869Sjfv /* Handle a few special cases. */ 4845205869Sjfv switch (info->offset) { 4846205869Sjfv case E1000_RDTR: 4847205869Sjfv break; 4848205869Sjfv case E1000_TIDV: 4849205869Sjfv if (ticks == 0) { 4850205869Sjfv adapter->txd_cmd &= ~E1000_TXD_CMD_IDE; 4851205869Sjfv /* Don't write 0 into the TIDV register. */ 4852205869Sjfv regval++; 4853205869Sjfv } else 4854205869Sjfv adapter->txd_cmd |= E1000_TXD_CMD_IDE; 4855205869Sjfv break; 4856205869Sjfv } 4857205869Sjfv E1000_WRITE_OFFSET(&adapter->hw, info->offset, regval); 4858205869Sjfv EM_CORE_UNLOCK(adapter); 4859205869Sjfv return (0); 4860205869Sjfv} 4861205869Sjfv 4862205869Sjfvstatic void 4863205869Sjfvlem_add_int_delay_sysctl(struct adapter *adapter, const char *name, 4864205869Sjfv const char *description, struct em_int_delay_info *info, 4865205869Sjfv int offset, int value) 4866205869Sjfv{ 4867205869Sjfv info->adapter = adapter; 4868205869Sjfv info->offset = offset; 4869205869Sjfv info->value = value; 4870205869Sjfv SYSCTL_ADD_PROC(device_get_sysctl_ctx(adapter->dev), 4871205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4872205869Sjfv OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, 4873205869Sjfv info, 0, lem_sysctl_int_delay, "I", description); 4874205869Sjfv} 4875205869Sjfv 4876214646Sjfvstatic void 4877214646Sjfvlem_set_flow_cntrl(struct adapter *adapter, const char *name, 4878214646Sjfv const char *description, int *limit, int value) 4879214646Sjfv{ 4880214646Sjfv *limit = value; 4881214646Sjfv SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 4882214646Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4883273736Shselasky OID_AUTO, name, CTLFLAG_RW, limit, value, description); 4884214646Sjfv} 4885214646Sjfv 4886205869Sjfvstatic void 4887205869Sjfvlem_add_rx_process_limit(struct adapter *adapter, const char *name, 4888205869Sjfv const char *description, int *limit, int value) 4889205869Sjfv{ 4890205869Sjfv *limit = value; 4891205869Sjfv SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 4892205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4893273736Shselasky OID_AUTO, name, CTLFLAG_RW, limit, value, description); 4894205869Sjfv} 4895