1205869Sjfv/****************************************************************************** 2205869Sjfv 3238953Sjfv Copyright (c) 2001-2012, Intel Corporation 4205869Sjfv All rights reserved. 5205869Sjfv 6205869Sjfv Redistribution and use in source and binary forms, with or without 7205869Sjfv modification, are permitted provided that the following conditions are met: 8205869Sjfv 9205869Sjfv 1. Redistributions of source code must retain the above copyright notice, 10205869Sjfv this list of conditions and the following disclaimer. 11205869Sjfv 12205869Sjfv 2. Redistributions in binary form must reproduce the above copyright 13205869Sjfv notice, this list of conditions and the following disclaimer in the 14205869Sjfv documentation and/or other materials provided with the distribution. 15205869Sjfv 16205869Sjfv 3. Neither the name of the Intel Corporation nor the names of its 17205869Sjfv contributors may be used to endorse or promote products derived from 18205869Sjfv this software without specific prior written permission. 19205869Sjfv 20205869Sjfv THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21205869Sjfv AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22205869Sjfv IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23205869Sjfv ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24205869Sjfv LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25205869Sjfv CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26205869Sjfv SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27205869Sjfv INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28205869Sjfv CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29205869Sjfv ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30205869Sjfv POSSIBILITY OF SUCH DAMAGE. 31205869Sjfv 32205869Sjfv******************************************************************************/ 33205869Sjfv/*$FreeBSD$*/ 34205869Sjfv 35253303Sjfv#include "opt_inet.h" 36253303Sjfv#include "opt_inet6.h" 37253303Sjfv 38205869Sjfv#ifdef HAVE_KERNEL_OPTION_HEADERS 39205869Sjfv#include "opt_device_polling.h" 40205869Sjfv#endif 41205869Sjfv 42205869Sjfv#include <sys/param.h> 43205869Sjfv#include <sys/systm.h> 44205869Sjfv#include <sys/bus.h> 45205869Sjfv#include <sys/endian.h> 46205869Sjfv#include <sys/kernel.h> 47205869Sjfv#include <sys/kthread.h> 48205869Sjfv#include <sys/malloc.h> 49205869Sjfv#include <sys/mbuf.h> 50205869Sjfv#include <sys/module.h> 51205869Sjfv#include <sys/rman.h> 52205869Sjfv#include <sys/socket.h> 53205869Sjfv#include <sys/sockio.h> 54205869Sjfv#include <sys/sysctl.h> 55205869Sjfv#include <sys/taskqueue.h> 56205869Sjfv#include <sys/eventhandler.h> 57205869Sjfv#include <machine/bus.h> 58205869Sjfv#include <machine/resource.h> 59205869Sjfv 60205869Sjfv#include <net/bpf.h> 61205869Sjfv#include <net/ethernet.h> 62205869Sjfv#include <net/if.h> 63205869Sjfv#include <net/if_arp.h> 64205869Sjfv#include <net/if_dl.h> 65205869Sjfv#include <net/if_media.h> 66205869Sjfv 67205869Sjfv#include <net/if_types.h> 68205869Sjfv#include <net/if_vlan_var.h> 69205869Sjfv 70205869Sjfv#include <netinet/in_systm.h> 71205869Sjfv#include <netinet/in.h> 72205869Sjfv#include <netinet/if_ether.h> 73205869Sjfv#include <netinet/ip.h> 74205869Sjfv#include <netinet/ip6.h> 75205869Sjfv#include <netinet/tcp.h> 76205869Sjfv#include <netinet/udp.h> 77205869Sjfv 78205869Sjfv#include <machine/in_cksum.h> 79206001Smarius#include <dev/led/led.h> 80205869Sjfv#include <dev/pci/pcivar.h> 81205869Sjfv#include <dev/pci/pcireg.h> 82205869Sjfv 83205869Sjfv#include "e1000_api.h" 84205869Sjfv#include "if_lem.h" 85205869Sjfv 86205869Sjfv/********************************************************************* 87205869Sjfv * Legacy Em Driver version: 88205869Sjfv *********************************************************************/ 89249074Sjfvchar lem_driver_version[] = "1.0.6"; 90205869Sjfv 91205869Sjfv/********************************************************************* 92205869Sjfv * PCI Device ID Table 93205869Sjfv * 94205869Sjfv * Used by probe to select devices to load on 95205869Sjfv * Last field stores an index into e1000_strings 96205869Sjfv * Last entry must be all 0s 97205869Sjfv * 98205869Sjfv * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 99205869Sjfv *********************************************************************/ 100205869Sjfv 101205869Sjfvstatic em_vendor_info_t lem_vendor_info_array[] = 102205869Sjfv{ 103205869Sjfv /* Intel(R) PRO/1000 Network Connection */ 104205869Sjfv { 0x8086, E1000_DEV_ID_82540EM, PCI_ANY_ID, PCI_ANY_ID, 0}, 105205869Sjfv { 0x8086, E1000_DEV_ID_82540EM_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 106205869Sjfv { 0x8086, E1000_DEV_ID_82540EP, PCI_ANY_ID, PCI_ANY_ID, 0}, 107205869Sjfv { 0x8086, E1000_DEV_ID_82540EP_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 108205869Sjfv { 0x8086, E1000_DEV_ID_82540EP_LP, PCI_ANY_ID, PCI_ANY_ID, 0}, 109205869Sjfv 110205869Sjfv { 0x8086, E1000_DEV_ID_82541EI, PCI_ANY_ID, PCI_ANY_ID, 0}, 111205869Sjfv { 0x8086, E1000_DEV_ID_82541ER, PCI_ANY_ID, PCI_ANY_ID, 0}, 112205869Sjfv { 0x8086, E1000_DEV_ID_82541ER_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 113205869Sjfv { 0x8086, E1000_DEV_ID_82541EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, 114205869Sjfv { 0x8086, E1000_DEV_ID_82541GI, PCI_ANY_ID, PCI_ANY_ID, 0}, 115205869Sjfv { 0x8086, E1000_DEV_ID_82541GI_LF, PCI_ANY_ID, PCI_ANY_ID, 0}, 116205869Sjfv { 0x8086, E1000_DEV_ID_82541GI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, 117205869Sjfv 118205869Sjfv { 0x8086, E1000_DEV_ID_82542, PCI_ANY_ID, PCI_ANY_ID, 0}, 119205869Sjfv 120205869Sjfv { 0x8086, E1000_DEV_ID_82543GC_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 121205869Sjfv { 0x8086, E1000_DEV_ID_82543GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 122205869Sjfv 123205869Sjfv { 0x8086, E1000_DEV_ID_82544EI_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 124205869Sjfv { 0x8086, E1000_DEV_ID_82544EI_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 125205869Sjfv { 0x8086, E1000_DEV_ID_82544GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 126205869Sjfv { 0x8086, E1000_DEV_ID_82544GC_LOM, PCI_ANY_ID, PCI_ANY_ID, 0}, 127205869Sjfv 128205869Sjfv { 0x8086, E1000_DEV_ID_82545EM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 129205869Sjfv { 0x8086, E1000_DEV_ID_82545EM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 130205869Sjfv { 0x8086, E1000_DEV_ID_82545GM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 131205869Sjfv { 0x8086, E1000_DEV_ID_82545GM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 132205869Sjfv { 0x8086, E1000_DEV_ID_82545GM_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, 133205869Sjfv 134205869Sjfv { 0x8086, E1000_DEV_ID_82546EB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 135205869Sjfv { 0x8086, E1000_DEV_ID_82546EB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 136205869Sjfv { 0x8086, E1000_DEV_ID_82546EB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 137205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 138205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, 139205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, 140205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_PCIE, PCI_ANY_ID, PCI_ANY_ID, 0}, 141205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, 142205869Sjfv { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3, 143205869Sjfv PCI_ANY_ID, PCI_ANY_ID, 0}, 144205869Sjfv 145205869Sjfv { 0x8086, E1000_DEV_ID_82547EI, PCI_ANY_ID, PCI_ANY_ID, 0}, 146205869Sjfv { 0x8086, E1000_DEV_ID_82547EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0}, 147205869Sjfv { 0x8086, E1000_DEV_ID_82547GI, PCI_ANY_ID, PCI_ANY_ID, 0}, 148205869Sjfv /* required last entry */ 149205869Sjfv { 0, 0, 0, 0, 0} 150205869Sjfv}; 151205869Sjfv 152205869Sjfv/********************************************************************* 153205869Sjfv * Table of branding strings for all supported NICs. 154205869Sjfv *********************************************************************/ 155205869Sjfv 156205869Sjfvstatic char *lem_strings[] = { 157205869Sjfv "Intel(R) PRO/1000 Legacy Network Connection" 158205869Sjfv}; 159205869Sjfv 160205869Sjfv/********************************************************************* 161205869Sjfv * Function prototypes 162205869Sjfv *********************************************************************/ 163205869Sjfvstatic int lem_probe(device_t); 164205869Sjfvstatic int lem_attach(device_t); 165205869Sjfvstatic int lem_detach(device_t); 166205869Sjfvstatic int lem_shutdown(device_t); 167205869Sjfvstatic int lem_suspend(device_t); 168205869Sjfvstatic int lem_resume(device_t); 169205869Sjfvstatic void lem_start(struct ifnet *); 170205869Sjfvstatic void lem_start_locked(struct ifnet *ifp); 171205869Sjfvstatic int lem_ioctl(struct ifnet *, u_long, caddr_t); 172205869Sjfvstatic void lem_init(void *); 173205869Sjfvstatic void lem_init_locked(struct adapter *); 174205869Sjfvstatic void lem_stop(void *); 175205869Sjfvstatic void lem_media_status(struct ifnet *, struct ifmediareq *); 176205869Sjfvstatic int lem_media_change(struct ifnet *); 177205869Sjfvstatic void lem_identify_hardware(struct adapter *); 178205869Sjfvstatic int lem_allocate_pci_resources(struct adapter *); 179205869Sjfvstatic int lem_allocate_irq(struct adapter *adapter); 180205869Sjfvstatic void lem_free_pci_resources(struct adapter *); 181205869Sjfvstatic void lem_local_timer(void *); 182205869Sjfvstatic int lem_hardware_init(struct adapter *); 183211907Syongaristatic int lem_setup_interface(device_t, struct adapter *); 184205869Sjfvstatic void lem_setup_transmit_structures(struct adapter *); 185205869Sjfvstatic void lem_initialize_transmit_unit(struct adapter *); 186205869Sjfvstatic int lem_setup_receive_structures(struct adapter *); 187205869Sjfvstatic void lem_initialize_receive_unit(struct adapter *); 188205869Sjfvstatic void lem_enable_intr(struct adapter *); 189205869Sjfvstatic void lem_disable_intr(struct adapter *); 190205869Sjfvstatic void lem_free_transmit_structures(struct adapter *); 191205869Sjfvstatic void lem_free_receive_structures(struct adapter *); 192205869Sjfvstatic void lem_update_stats_counters(struct adapter *); 193212902Sjhbstatic void lem_add_hw_stats(struct adapter *adapter); 194205869Sjfvstatic void lem_txeof(struct adapter *); 195205869Sjfvstatic void lem_tx_purge(struct adapter *); 196205869Sjfvstatic int lem_allocate_receive_structures(struct adapter *); 197205869Sjfvstatic int lem_allocate_transmit_structures(struct adapter *); 198209238Sjfvstatic bool lem_rxeof(struct adapter *, int, int *); 199205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 200205869Sjfvstatic int lem_fixup_rx(struct adapter *); 201205869Sjfv#endif 202205869Sjfvstatic void lem_receive_checksum(struct adapter *, struct e1000_rx_desc *, 203205869Sjfv struct mbuf *); 204205869Sjfvstatic void lem_transmit_checksum_setup(struct adapter *, struct mbuf *, 205205869Sjfv u32 *, u32 *); 206205869Sjfvstatic void lem_set_promisc(struct adapter *); 207205869Sjfvstatic void lem_disable_promisc(struct adapter *); 208205869Sjfvstatic void lem_set_multi(struct adapter *); 209205869Sjfvstatic void lem_update_link_status(struct adapter *); 210205869Sjfvstatic int lem_get_buf(struct adapter *, int); 211205869Sjfvstatic void lem_register_vlan(void *, struct ifnet *, u16); 212205869Sjfvstatic void lem_unregister_vlan(void *, struct ifnet *, u16); 213205869Sjfvstatic void lem_setup_vlan_hw_support(struct adapter *); 214205869Sjfvstatic int lem_xmit(struct adapter *, struct mbuf **); 215205869Sjfvstatic void lem_smartspeed(struct adapter *); 216205869Sjfvstatic int lem_82547_fifo_workaround(struct adapter *, int); 217205869Sjfvstatic void lem_82547_update_fifo_head(struct adapter *, int); 218205869Sjfvstatic int lem_82547_tx_fifo_reset(struct adapter *); 219205869Sjfvstatic void lem_82547_move_tail(void *); 220205869Sjfvstatic int lem_dma_malloc(struct adapter *, bus_size_t, 221205869Sjfv struct em_dma_alloc *, int); 222205869Sjfvstatic void lem_dma_free(struct adapter *, struct em_dma_alloc *); 223212902Sjhbstatic int lem_sysctl_nvm_info(SYSCTL_HANDLER_ARGS); 224205869Sjfvstatic void lem_print_nvm_info(struct adapter *); 225205869Sjfvstatic int lem_is_valid_ether_addr(u8 *); 226205869Sjfvstatic u32 lem_fill_descriptors (bus_addr_t address, u32 length, 227205869Sjfv PDESC_ARRAY desc_array); 228205869Sjfvstatic int lem_sysctl_int_delay(SYSCTL_HANDLER_ARGS); 229205869Sjfvstatic void lem_add_int_delay_sysctl(struct adapter *, const char *, 230205869Sjfv const char *, struct em_int_delay_info *, int, int); 231214646Sjfvstatic void lem_set_flow_cntrl(struct adapter *, const char *, 232214646Sjfv const char *, int *, int); 233205869Sjfv/* Management and WOL Support */ 234205869Sjfvstatic void lem_init_manageability(struct adapter *); 235205869Sjfvstatic void lem_release_manageability(struct adapter *); 236205869Sjfvstatic void lem_get_hw_control(struct adapter *); 237205869Sjfvstatic void lem_release_hw_control(struct adapter *); 238205869Sjfvstatic void lem_get_wakeup(device_t); 239205869Sjfvstatic void lem_enable_wakeup(device_t); 240205869Sjfvstatic int lem_enable_phy_wakeup(struct adapter *); 241206001Smariusstatic void lem_led_func(void *, int); 242205869Sjfv 243205869Sjfvstatic void lem_intr(void *); 244205869Sjfvstatic int lem_irq_fast(void *); 245205869Sjfvstatic void lem_handle_rxtx(void *context, int pending); 246205869Sjfvstatic void lem_handle_link(void *context, int pending); 247205869Sjfvstatic void lem_add_rx_process_limit(struct adapter *, const char *, 248205869Sjfv const char *, int *, int); 249205869Sjfv 250205869Sjfv#ifdef DEVICE_POLLING 251205987Sjfvstatic poll_handler_t lem_poll; 252205869Sjfv#endif /* POLLING */ 253205869Sjfv 254205869Sjfv/********************************************************************* 255205869Sjfv * FreeBSD Device Interface Entry Points 256205869Sjfv *********************************************************************/ 257205869Sjfv 258205869Sjfvstatic device_method_t lem_methods[] = { 259205869Sjfv /* Device interface */ 260205869Sjfv DEVMETHOD(device_probe, lem_probe), 261205869Sjfv DEVMETHOD(device_attach, lem_attach), 262205869Sjfv DEVMETHOD(device_detach, lem_detach), 263205869Sjfv DEVMETHOD(device_shutdown, lem_shutdown), 264205869Sjfv DEVMETHOD(device_suspend, lem_suspend), 265205869Sjfv DEVMETHOD(device_resume, lem_resume), 266246128Ssbz DEVMETHOD_END 267205869Sjfv}; 268205869Sjfv 269205869Sjfvstatic driver_t lem_driver = { 270205869Sjfv "em", lem_methods, sizeof(struct adapter), 271205869Sjfv}; 272205869Sjfv 273205869Sjfvextern devclass_t em_devclass; 274205869SjfvDRIVER_MODULE(lem, pci, lem_driver, em_devclass, 0, 0); 275205869SjfvMODULE_DEPEND(lem, pci, 1, 1, 1); 276205869SjfvMODULE_DEPEND(lem, ether, 1, 1, 1); 277205869Sjfv 278205869Sjfv/********************************************************************* 279205869Sjfv * Tunable default values. 280205869Sjfv *********************************************************************/ 281205869Sjfv 282205869Sjfv#define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) 283205869Sjfv#define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) 284205869Sjfv 285250414Sluigi#define MAX_INTS_PER_SEC 8000 286250414Sluigi#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) 287250414Sluigi 288205869Sjfvstatic int lem_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV); 289205869Sjfvstatic int lem_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR); 290205869Sjfvstatic int lem_tx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_TADV); 291205869Sjfvstatic int lem_rx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_RADV); 292205869Sjfvstatic int lem_rxd = EM_DEFAULT_RXD; 293205869Sjfvstatic int lem_txd = EM_DEFAULT_TXD; 294205869Sjfvstatic int lem_smart_pwr_down = FALSE; 295205869Sjfv 296205869Sjfv/* Controls whether promiscuous also shows bad packets */ 297205869Sjfvstatic int lem_debug_sbp = FALSE; 298205869Sjfv 299205869SjfvTUNABLE_INT("hw.em.tx_int_delay", &lem_tx_int_delay_dflt); 300205869SjfvTUNABLE_INT("hw.em.rx_int_delay", &lem_rx_int_delay_dflt); 301205869SjfvTUNABLE_INT("hw.em.tx_abs_int_delay", &lem_tx_abs_int_delay_dflt); 302205869SjfvTUNABLE_INT("hw.em.rx_abs_int_delay", &lem_rx_abs_int_delay_dflt); 303205869SjfvTUNABLE_INT("hw.em.rxd", &lem_rxd); 304205869SjfvTUNABLE_INT("hw.em.txd", &lem_txd); 305205869SjfvTUNABLE_INT("hw.em.smart_pwr_down", &lem_smart_pwr_down); 306205869SjfvTUNABLE_INT("hw.em.sbp", &lem_debug_sbp); 307205869Sjfv 308238953Sjfv/* Interrupt style - default to fast */ 309238953Sjfvstatic int lem_use_legacy_irq = 0; 310238953SjfvTUNABLE_INT("hw.em.use_legacy_irq", &lem_use_legacy_irq); 311238953Sjfv 312205869Sjfv/* How many packets rxeof tries to clean at a time */ 313205869Sjfvstatic int lem_rx_process_limit = 100; 314205869SjfvTUNABLE_INT("hw.em.rx_process_limit", &lem_rx_process_limit); 315205869Sjfv 316205869Sjfv/* Flow control setting - default to FULL */ 317205869Sjfvstatic int lem_fc_setting = e1000_fc_full; 318205869SjfvTUNABLE_INT("hw.em.fc_setting", &lem_fc_setting); 319205869Sjfv 320205869Sjfv/* Global used in WOL setup with multiport cards */ 321205869Sjfvstatic int global_quad_port_a = 0; 322205869Sjfv 323228281Sluigi#ifdef DEV_NETMAP /* see ixgbe.c for details */ 324228281Sluigi#include <dev/netmap/if_lem_netmap.h> 325228281Sluigi#endif /* DEV_NETMAP */ 326228281Sluigi 327205869Sjfv/********************************************************************* 328205869Sjfv * Device identification routine 329205869Sjfv * 330205869Sjfv * em_probe determines if the driver should be loaded on 331205869Sjfv * adapter based on PCI vendor/device id of the adapter. 332205869Sjfv * 333205869Sjfv * return BUS_PROBE_DEFAULT on success, positive on failure 334205869Sjfv *********************************************************************/ 335205869Sjfv 336205869Sjfvstatic int 337205869Sjfvlem_probe(device_t dev) 338205869Sjfv{ 339205869Sjfv char adapter_name[60]; 340205869Sjfv u16 pci_vendor_id = 0; 341205869Sjfv u16 pci_device_id = 0; 342205869Sjfv u16 pci_subvendor_id = 0; 343205869Sjfv u16 pci_subdevice_id = 0; 344205869Sjfv em_vendor_info_t *ent; 345205869Sjfv 346205869Sjfv INIT_DEBUGOUT("em_probe: begin"); 347205869Sjfv 348205869Sjfv pci_vendor_id = pci_get_vendor(dev); 349205869Sjfv if (pci_vendor_id != EM_VENDOR_ID) 350205869Sjfv return (ENXIO); 351205869Sjfv 352205869Sjfv pci_device_id = pci_get_device(dev); 353205869Sjfv pci_subvendor_id = pci_get_subvendor(dev); 354205869Sjfv pci_subdevice_id = pci_get_subdevice(dev); 355205869Sjfv 356205869Sjfv ent = lem_vendor_info_array; 357205869Sjfv while (ent->vendor_id != 0) { 358205869Sjfv if ((pci_vendor_id == ent->vendor_id) && 359205869Sjfv (pci_device_id == ent->device_id) && 360205869Sjfv 361205869Sjfv ((pci_subvendor_id == ent->subvendor_id) || 362205869Sjfv (ent->subvendor_id == PCI_ANY_ID)) && 363205869Sjfv 364205869Sjfv ((pci_subdevice_id == ent->subdevice_id) || 365205869Sjfv (ent->subdevice_id == PCI_ANY_ID))) { 366205869Sjfv sprintf(adapter_name, "%s %s", 367205869Sjfv lem_strings[ent->index], 368205869Sjfv lem_driver_version); 369205869Sjfv device_set_desc_copy(dev, adapter_name); 370205869Sjfv return (BUS_PROBE_DEFAULT); 371205869Sjfv } 372205869Sjfv ent++; 373205869Sjfv } 374205869Sjfv 375205869Sjfv return (ENXIO); 376205869Sjfv} 377205869Sjfv 378205869Sjfv/********************************************************************* 379205869Sjfv * Device initialization routine 380205869Sjfv * 381205869Sjfv * The attach entry point is called when the driver is being loaded. 382205869Sjfv * This routine identifies the type of hardware, allocates all resources 383205869Sjfv * and initializes the hardware. 384205869Sjfv * 385205869Sjfv * return 0 on success, positive on failure 386205869Sjfv *********************************************************************/ 387205869Sjfv 388205869Sjfvstatic int 389205869Sjfvlem_attach(device_t dev) 390205869Sjfv{ 391205869Sjfv struct adapter *adapter; 392205869Sjfv int tsize, rsize; 393205869Sjfv int error = 0; 394205869Sjfv 395205869Sjfv INIT_DEBUGOUT("lem_attach: begin"); 396205869Sjfv 397205869Sjfv adapter = device_get_softc(dev); 398205869Sjfv adapter->dev = adapter->osdep.dev = dev; 399205869Sjfv EM_CORE_LOCK_INIT(adapter, device_get_nameunit(dev)); 400205869Sjfv EM_TX_LOCK_INIT(adapter, device_get_nameunit(dev)); 401205869Sjfv EM_RX_LOCK_INIT(adapter, device_get_nameunit(dev)); 402205869Sjfv 403205869Sjfv /* SYSCTL stuff */ 404205869Sjfv SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 405205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 406212902Sjhb OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0, 407212902Sjhb lem_sysctl_nvm_info, "I", "NVM Information"); 408205869Sjfv 409205869Sjfv callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0); 410205869Sjfv callout_init_mtx(&adapter->tx_fifo_timer, &adapter->tx_mtx, 0); 411205869Sjfv 412205869Sjfv /* Determine hardware and mac info */ 413205869Sjfv lem_identify_hardware(adapter); 414205869Sjfv 415205869Sjfv /* Setup PCI resources */ 416205869Sjfv if (lem_allocate_pci_resources(adapter)) { 417205869Sjfv device_printf(dev, "Allocation of PCI resources failed\n"); 418205869Sjfv error = ENXIO; 419205869Sjfv goto err_pci; 420205869Sjfv } 421205869Sjfv 422205869Sjfv /* Do Shared Code initialization */ 423205869Sjfv if (e1000_setup_init_funcs(&adapter->hw, TRUE)) { 424205869Sjfv device_printf(dev, "Setup of Shared code failed\n"); 425205869Sjfv error = ENXIO; 426205869Sjfv goto err_pci; 427205869Sjfv } 428205869Sjfv 429205869Sjfv e1000_get_bus_info(&adapter->hw); 430205869Sjfv 431205869Sjfv /* Set up some sysctls for the tunable interrupt delays */ 432205869Sjfv lem_add_int_delay_sysctl(adapter, "rx_int_delay", 433205869Sjfv "receive interrupt delay in usecs", &adapter->rx_int_delay, 434205869Sjfv E1000_REGISTER(&adapter->hw, E1000_RDTR), lem_rx_int_delay_dflt); 435205869Sjfv lem_add_int_delay_sysctl(adapter, "tx_int_delay", 436205869Sjfv "transmit interrupt delay in usecs", &adapter->tx_int_delay, 437205869Sjfv E1000_REGISTER(&adapter->hw, E1000_TIDV), lem_tx_int_delay_dflt); 438205869Sjfv if (adapter->hw.mac.type >= e1000_82540) { 439205869Sjfv lem_add_int_delay_sysctl(adapter, "rx_abs_int_delay", 440205869Sjfv "receive interrupt delay limit in usecs", 441205869Sjfv &adapter->rx_abs_int_delay, 442205869Sjfv E1000_REGISTER(&adapter->hw, E1000_RADV), 443205869Sjfv lem_rx_abs_int_delay_dflt); 444205869Sjfv lem_add_int_delay_sysctl(adapter, "tx_abs_int_delay", 445205869Sjfv "transmit interrupt delay limit in usecs", 446205869Sjfv &adapter->tx_abs_int_delay, 447205869Sjfv E1000_REGISTER(&adapter->hw, E1000_TADV), 448205869Sjfv lem_tx_abs_int_delay_dflt); 449250414Sluigi lem_add_int_delay_sysctl(adapter, "itr", 450250414Sluigi "interrupt delay limit in usecs/4", 451250414Sluigi &adapter->tx_itr, 452250414Sluigi E1000_REGISTER(&adapter->hw, E1000_ITR), 453250414Sluigi DEFAULT_ITR); 454205869Sjfv } 455205869Sjfv 456205869Sjfv /* Sysctls for limiting the amount of work done in the taskqueue */ 457205869Sjfv lem_add_rx_process_limit(adapter, "rx_processing_limit", 458205869Sjfv "max number of rx packets to process", &adapter->rx_process_limit, 459205869Sjfv lem_rx_process_limit); 460205869Sjfv 461214646Sjfv /* Sysctl for setting the interface flow control */ 462214646Sjfv lem_set_flow_cntrl(adapter, "flow_control", 463228387Sjfv "flow control setting", 464214646Sjfv &adapter->fc_setting, lem_fc_setting); 465214646Sjfv 466205869Sjfv /* 467205869Sjfv * Validate number of transmit and receive descriptors. It 468205869Sjfv * must not exceed hardware maximum, and must be multiple 469205869Sjfv * of E1000_DBA_ALIGN. 470205869Sjfv */ 471205869Sjfv if (((lem_txd * sizeof(struct e1000_tx_desc)) % EM_DBA_ALIGN) != 0 || 472205869Sjfv (adapter->hw.mac.type >= e1000_82544 && lem_txd > EM_MAX_TXD) || 473205869Sjfv (adapter->hw.mac.type < e1000_82544 && lem_txd > EM_MAX_TXD_82543) || 474205869Sjfv (lem_txd < EM_MIN_TXD)) { 475205869Sjfv device_printf(dev, "Using %d TX descriptors instead of %d!\n", 476205869Sjfv EM_DEFAULT_TXD, lem_txd); 477205869Sjfv adapter->num_tx_desc = EM_DEFAULT_TXD; 478205869Sjfv } else 479205869Sjfv adapter->num_tx_desc = lem_txd; 480205869Sjfv if (((lem_rxd * sizeof(struct e1000_rx_desc)) % EM_DBA_ALIGN) != 0 || 481205869Sjfv (adapter->hw.mac.type >= e1000_82544 && lem_rxd > EM_MAX_RXD) || 482205869Sjfv (adapter->hw.mac.type < e1000_82544 && lem_rxd > EM_MAX_RXD_82543) || 483205869Sjfv (lem_rxd < EM_MIN_RXD)) { 484205869Sjfv device_printf(dev, "Using %d RX descriptors instead of %d!\n", 485205869Sjfv EM_DEFAULT_RXD, lem_rxd); 486205869Sjfv adapter->num_rx_desc = EM_DEFAULT_RXD; 487205869Sjfv } else 488205869Sjfv adapter->num_rx_desc = lem_rxd; 489205869Sjfv 490205869Sjfv adapter->hw.mac.autoneg = DO_AUTO_NEG; 491205869Sjfv adapter->hw.phy.autoneg_wait_to_complete = FALSE; 492205869Sjfv adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; 493205869Sjfv adapter->rx_buffer_len = 2048; 494205869Sjfv 495205869Sjfv e1000_init_script_state_82541(&adapter->hw, TRUE); 496205869Sjfv e1000_set_tbi_compatibility_82543(&adapter->hw, TRUE); 497205869Sjfv 498205869Sjfv /* Copper options */ 499205869Sjfv if (adapter->hw.phy.media_type == e1000_media_type_copper) { 500205869Sjfv adapter->hw.phy.mdix = AUTO_ALL_MODES; 501205869Sjfv adapter->hw.phy.disable_polarity_correction = FALSE; 502205869Sjfv adapter->hw.phy.ms_type = EM_MASTER_SLAVE; 503205869Sjfv } 504205869Sjfv 505205869Sjfv /* 506205869Sjfv * Set the frame limits assuming 507205869Sjfv * standard ethernet sized frames. 508205869Sjfv */ 509205869Sjfv adapter->max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE; 510205869Sjfv adapter->min_frame_size = ETH_ZLEN + ETHERNET_FCS_SIZE; 511205869Sjfv 512205869Sjfv /* 513205869Sjfv * This controls when hardware reports transmit completion 514205869Sjfv * status. 515205869Sjfv */ 516205869Sjfv adapter->hw.mac.report_tx_early = 1; 517205869Sjfv 518205869Sjfv tsize = roundup2(adapter->num_tx_desc * sizeof(struct e1000_tx_desc), 519205869Sjfv EM_DBA_ALIGN); 520205869Sjfv 521205869Sjfv /* Allocate Transmit Descriptor ring */ 522205869Sjfv if (lem_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) { 523205869Sjfv device_printf(dev, "Unable to allocate tx_desc memory\n"); 524205869Sjfv error = ENOMEM; 525205869Sjfv goto err_tx_desc; 526205869Sjfv } 527205869Sjfv adapter->tx_desc_base = 528205869Sjfv (struct e1000_tx_desc *)adapter->txdma.dma_vaddr; 529205869Sjfv 530205869Sjfv rsize = roundup2(adapter->num_rx_desc * sizeof(struct e1000_rx_desc), 531205869Sjfv EM_DBA_ALIGN); 532205869Sjfv 533205869Sjfv /* Allocate Receive Descriptor ring */ 534205869Sjfv if (lem_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) { 535205869Sjfv device_printf(dev, "Unable to allocate rx_desc memory\n"); 536205869Sjfv error = ENOMEM; 537205869Sjfv goto err_rx_desc; 538205869Sjfv } 539205869Sjfv adapter->rx_desc_base = 540205869Sjfv (struct e1000_rx_desc *)adapter->rxdma.dma_vaddr; 541205869Sjfv 542211913Syongari /* Allocate multicast array memory. */ 543211913Syongari adapter->mta = malloc(sizeof(u8) * ETH_ADDR_LEN * 544211913Syongari MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT); 545211913Syongari if (adapter->mta == NULL) { 546211913Syongari device_printf(dev, "Can not allocate multicast setup array\n"); 547211913Syongari error = ENOMEM; 548211913Syongari goto err_hw_init; 549211913Syongari } 550211913Syongari 551205869Sjfv /* 552205869Sjfv ** Start from a known state, this is 553205869Sjfv ** important in reading the nvm and 554205869Sjfv ** mac from that. 555205869Sjfv */ 556205869Sjfv e1000_reset_hw(&adapter->hw); 557205869Sjfv 558205869Sjfv /* Make sure we have a good EEPROM before we read from it */ 559205869Sjfv if (e1000_validate_nvm_checksum(&adapter->hw) < 0) { 560205869Sjfv /* 561205869Sjfv ** Some PCI-E parts fail the first check due to 562205869Sjfv ** the link being in sleep state, call it again, 563205869Sjfv ** if it fails a second time its a real issue. 564205869Sjfv */ 565205869Sjfv if (e1000_validate_nvm_checksum(&adapter->hw) < 0) { 566205869Sjfv device_printf(dev, 567205869Sjfv "The EEPROM Checksum Is Not Valid\n"); 568205869Sjfv error = EIO; 569205869Sjfv goto err_hw_init; 570205869Sjfv } 571205869Sjfv } 572205869Sjfv 573205869Sjfv /* Copy the permanent MAC address out of the EEPROM */ 574205869Sjfv if (e1000_read_mac_addr(&adapter->hw) < 0) { 575205869Sjfv device_printf(dev, "EEPROM read error while reading MAC" 576205869Sjfv " address\n"); 577205869Sjfv error = EIO; 578205869Sjfv goto err_hw_init; 579205869Sjfv } 580205869Sjfv 581205869Sjfv if (!lem_is_valid_ether_addr(adapter->hw.mac.addr)) { 582205869Sjfv device_printf(dev, "Invalid MAC address\n"); 583205869Sjfv error = EIO; 584205869Sjfv goto err_hw_init; 585205869Sjfv } 586205869Sjfv 587205869Sjfv /* Initialize the hardware */ 588205869Sjfv if (lem_hardware_init(adapter)) { 589205869Sjfv device_printf(dev, "Unable to initialize the hardware\n"); 590205869Sjfv error = EIO; 591205869Sjfv goto err_hw_init; 592205869Sjfv } 593205869Sjfv 594205869Sjfv /* Allocate transmit descriptors and buffers */ 595205869Sjfv if (lem_allocate_transmit_structures(adapter)) { 596205869Sjfv device_printf(dev, "Could not setup transmit structures\n"); 597205869Sjfv error = ENOMEM; 598205869Sjfv goto err_tx_struct; 599205869Sjfv } 600205869Sjfv 601205869Sjfv /* Allocate receive descriptors and buffers */ 602205869Sjfv if (lem_allocate_receive_structures(adapter)) { 603205869Sjfv device_printf(dev, "Could not setup receive structures\n"); 604205869Sjfv error = ENOMEM; 605205869Sjfv goto err_rx_struct; 606205869Sjfv } 607205869Sjfv 608205869Sjfv /* 609205869Sjfv ** Do interrupt configuration 610205869Sjfv */ 611205869Sjfv error = lem_allocate_irq(adapter); 612205869Sjfv if (error) 613205869Sjfv goto err_rx_struct; 614205869Sjfv 615205869Sjfv /* 616205869Sjfv * Get Wake-on-Lan and Management info for later use 617205869Sjfv */ 618205869Sjfv lem_get_wakeup(dev); 619205869Sjfv 620205869Sjfv /* Setup OS specific network interface */ 621211907Syongari if (lem_setup_interface(dev, adapter) != 0) 622211907Syongari goto err_rx_struct; 623205869Sjfv 624205869Sjfv /* Initialize statistics */ 625205869Sjfv lem_update_stats_counters(adapter); 626205869Sjfv 627205869Sjfv adapter->hw.mac.get_link_status = 1; 628205869Sjfv lem_update_link_status(adapter); 629205869Sjfv 630205869Sjfv /* Indicate SOL/IDER usage */ 631205869Sjfv if (e1000_check_reset_block(&adapter->hw)) 632205869Sjfv device_printf(dev, 633205869Sjfv "PHY reset is blocked due to SOL/IDER session.\n"); 634205869Sjfv 635205869Sjfv /* Do we need workaround for 82544 PCI-X adapter? */ 636205869Sjfv if (adapter->hw.bus.type == e1000_bus_type_pcix && 637205869Sjfv adapter->hw.mac.type == e1000_82544) 638205869Sjfv adapter->pcix_82544 = TRUE; 639205869Sjfv else 640205869Sjfv adapter->pcix_82544 = FALSE; 641205869Sjfv 642205869Sjfv /* Register for VLAN events */ 643205869Sjfv adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 644205869Sjfv lem_register_vlan, adapter, EVENTHANDLER_PRI_FIRST); 645205869Sjfv adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 646205869Sjfv lem_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST); 647205869Sjfv 648212902Sjhb lem_add_hw_stats(adapter); 649212902Sjhb 650205869Sjfv /* Non-AMT based hardware can now take control from firmware */ 651205869Sjfv if (adapter->has_manage && !adapter->has_amt) 652205869Sjfv lem_get_hw_control(adapter); 653205869Sjfv 654205869Sjfv /* Tell the stack that the interface is not active */ 655205869Sjfv adapter->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 656205869Sjfv 657206001Smarius adapter->led_dev = led_create(lem_led_func, adapter, 658206001Smarius device_get_nameunit(dev)); 659206001Smarius 660228281Sluigi#ifdef DEV_NETMAP 661228281Sluigi lem_netmap_attach(adapter); 662228281Sluigi#endif /* DEV_NETMAP */ 663205869Sjfv INIT_DEBUGOUT("lem_attach: end"); 664205869Sjfv 665205869Sjfv return (0); 666205869Sjfv 667205869Sjfverr_rx_struct: 668205869Sjfv lem_free_transmit_structures(adapter); 669205869Sjfverr_tx_struct: 670205869Sjfverr_hw_init: 671205869Sjfv lem_release_hw_control(adapter); 672205869Sjfv lem_dma_free(adapter, &adapter->rxdma); 673205869Sjfverr_rx_desc: 674205869Sjfv lem_dma_free(adapter, &adapter->txdma); 675205869Sjfverr_tx_desc: 676205869Sjfverr_pci: 677211907Syongari if (adapter->ifp != NULL) 678211907Syongari if_free(adapter->ifp); 679205869Sjfv lem_free_pci_resources(adapter); 680211913Syongari free(adapter->mta, M_DEVBUF); 681205869Sjfv EM_TX_LOCK_DESTROY(adapter); 682205869Sjfv EM_RX_LOCK_DESTROY(adapter); 683205869Sjfv EM_CORE_LOCK_DESTROY(adapter); 684205869Sjfv 685205869Sjfv return (error); 686205869Sjfv} 687205869Sjfv 688205869Sjfv/********************************************************************* 689205869Sjfv * Device removal routine 690205869Sjfv * 691205869Sjfv * The detach entry point is called when the driver is being removed. 692205869Sjfv * This routine stops the adapter and deallocates all the resources 693205869Sjfv * that were allocated for driver operation. 694205869Sjfv * 695205869Sjfv * return 0 on success, positive on failure 696205869Sjfv *********************************************************************/ 697205869Sjfv 698205869Sjfvstatic int 699205869Sjfvlem_detach(device_t dev) 700205869Sjfv{ 701205869Sjfv struct adapter *adapter = device_get_softc(dev); 702205869Sjfv struct ifnet *ifp = adapter->ifp; 703205869Sjfv 704205869Sjfv INIT_DEBUGOUT("em_detach: begin"); 705205869Sjfv 706205869Sjfv /* Make sure VLANS are not using driver */ 707205869Sjfv if (adapter->ifp->if_vlantrunk != NULL) { 708205869Sjfv device_printf(dev,"Vlan in use, detach first\n"); 709205869Sjfv return (EBUSY); 710205869Sjfv } 711205869Sjfv 712205869Sjfv#ifdef DEVICE_POLLING 713205869Sjfv if (ifp->if_capenable & IFCAP_POLLING) 714205869Sjfv ether_poll_deregister(ifp); 715205869Sjfv#endif 716205869Sjfv 717206001Smarius if (adapter->led_dev != NULL) 718206001Smarius led_destroy(adapter->led_dev); 719206001Smarius 720205869Sjfv EM_CORE_LOCK(adapter); 721205869Sjfv EM_TX_LOCK(adapter); 722205869Sjfv adapter->in_detach = 1; 723205869Sjfv lem_stop(adapter); 724205869Sjfv e1000_phy_hw_reset(&adapter->hw); 725205869Sjfv 726205869Sjfv lem_release_manageability(adapter); 727205869Sjfv 728205869Sjfv EM_TX_UNLOCK(adapter); 729205869Sjfv EM_CORE_UNLOCK(adapter); 730205869Sjfv 731205869Sjfv /* Unregister VLAN events */ 732205869Sjfv if (adapter->vlan_attach != NULL) 733205869Sjfv EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach); 734205869Sjfv if (adapter->vlan_detach != NULL) 735205869Sjfv EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); 736205869Sjfv 737205869Sjfv ether_ifdetach(adapter->ifp); 738205869Sjfv callout_drain(&adapter->timer); 739205869Sjfv callout_drain(&adapter->tx_fifo_timer); 740205869Sjfv 741228281Sluigi#ifdef DEV_NETMAP 742228281Sluigi netmap_detach(ifp); 743228281Sluigi#endif /* DEV_NETMAP */ 744205869Sjfv lem_free_pci_resources(adapter); 745205869Sjfv bus_generic_detach(dev); 746205869Sjfv if_free(ifp); 747205869Sjfv 748205869Sjfv lem_free_transmit_structures(adapter); 749205869Sjfv lem_free_receive_structures(adapter); 750205869Sjfv 751205869Sjfv /* Free Transmit Descriptor ring */ 752205869Sjfv if (adapter->tx_desc_base) { 753205869Sjfv lem_dma_free(adapter, &adapter->txdma); 754205869Sjfv adapter->tx_desc_base = NULL; 755205869Sjfv } 756205869Sjfv 757205869Sjfv /* Free Receive Descriptor ring */ 758205869Sjfv if (adapter->rx_desc_base) { 759205869Sjfv lem_dma_free(adapter, &adapter->rxdma); 760205869Sjfv adapter->rx_desc_base = NULL; 761205869Sjfv } 762205869Sjfv 763205869Sjfv lem_release_hw_control(adapter); 764211913Syongari free(adapter->mta, M_DEVBUF); 765205869Sjfv EM_TX_LOCK_DESTROY(adapter); 766205869Sjfv EM_RX_LOCK_DESTROY(adapter); 767205869Sjfv EM_CORE_LOCK_DESTROY(adapter); 768205869Sjfv 769205869Sjfv return (0); 770205869Sjfv} 771205869Sjfv 772205869Sjfv/********************************************************************* 773205869Sjfv * 774205869Sjfv * Shutdown entry point 775205869Sjfv * 776205869Sjfv **********************************************************************/ 777205869Sjfv 778205869Sjfvstatic int 779205869Sjfvlem_shutdown(device_t dev) 780205869Sjfv{ 781205869Sjfv return lem_suspend(dev); 782205869Sjfv} 783205869Sjfv 784205869Sjfv/* 785205869Sjfv * Suspend/resume device methods. 786205869Sjfv */ 787205869Sjfvstatic int 788205869Sjfvlem_suspend(device_t dev) 789205869Sjfv{ 790205869Sjfv struct adapter *adapter = device_get_softc(dev); 791205869Sjfv 792205869Sjfv EM_CORE_LOCK(adapter); 793205869Sjfv 794205869Sjfv lem_release_manageability(adapter); 795205869Sjfv lem_release_hw_control(adapter); 796205869Sjfv lem_enable_wakeup(dev); 797205869Sjfv 798205869Sjfv EM_CORE_UNLOCK(adapter); 799205869Sjfv 800205869Sjfv return bus_generic_suspend(dev); 801205869Sjfv} 802205869Sjfv 803205869Sjfvstatic int 804205869Sjfvlem_resume(device_t dev) 805205869Sjfv{ 806205869Sjfv struct adapter *adapter = device_get_softc(dev); 807205869Sjfv struct ifnet *ifp = adapter->ifp; 808205869Sjfv 809205869Sjfv EM_CORE_LOCK(adapter); 810205869Sjfv lem_init_locked(adapter); 811205869Sjfv lem_init_manageability(adapter); 812205869Sjfv EM_CORE_UNLOCK(adapter); 813205869Sjfv lem_start(ifp); 814205869Sjfv 815205869Sjfv return bus_generic_resume(dev); 816205869Sjfv} 817205869Sjfv 818205869Sjfv 819205869Sjfvstatic void 820205869Sjfvlem_start_locked(struct ifnet *ifp) 821205869Sjfv{ 822205869Sjfv struct adapter *adapter = ifp->if_softc; 823205869Sjfv struct mbuf *m_head; 824205869Sjfv 825205869Sjfv EM_TX_LOCK_ASSERT(adapter); 826205869Sjfv 827205869Sjfv if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) != 828205869Sjfv IFF_DRV_RUNNING) 829205869Sjfv return; 830205869Sjfv if (!adapter->link_active) 831205869Sjfv return; 832205869Sjfv 833214646Sjfv /* 834214646Sjfv * Force a cleanup if number of TX descriptors 835214646Sjfv * available hits the threshold 836214646Sjfv */ 837214646Sjfv if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) { 838214646Sjfv lem_txeof(adapter); 839214646Sjfv /* Now do we at least have a minimal? */ 840214646Sjfv if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) { 841214646Sjfv adapter->no_tx_desc_avail1++; 842214646Sjfv return; 843214646Sjfv } 844214646Sjfv } 845214646Sjfv 846205869Sjfv while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 847205869Sjfv 848205869Sjfv IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 849205869Sjfv if (m_head == NULL) 850205869Sjfv break; 851205869Sjfv /* 852205869Sjfv * Encapsulation can modify our pointer, and or make it 853205869Sjfv * NULL on failure. In that event, we can't requeue. 854205869Sjfv */ 855205869Sjfv if (lem_xmit(adapter, &m_head)) { 856205869Sjfv if (m_head == NULL) 857205869Sjfv break; 858205869Sjfv ifp->if_drv_flags |= IFF_DRV_OACTIVE; 859205869Sjfv IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 860205869Sjfv break; 861205869Sjfv } 862205869Sjfv 863205869Sjfv /* Send a copy of the frame to the BPF listener */ 864205869Sjfv ETHER_BPF_MTAP(ifp, m_head); 865205869Sjfv 866205869Sjfv /* Set timeout in case hardware has problems transmitting. */ 867205869Sjfv adapter->watchdog_check = TRUE; 868206614Sjfv adapter->watchdog_time = ticks; 869205869Sjfv } 870205869Sjfv if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) 871205869Sjfv ifp->if_drv_flags |= IFF_DRV_OACTIVE; 872205869Sjfv 873205869Sjfv return; 874205869Sjfv} 875205869Sjfv 876205869Sjfvstatic void 877205869Sjfvlem_start(struct ifnet *ifp) 878205869Sjfv{ 879205869Sjfv struct adapter *adapter = ifp->if_softc; 880205869Sjfv 881205869Sjfv EM_TX_LOCK(adapter); 882205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) 883205869Sjfv lem_start_locked(ifp); 884205869Sjfv EM_TX_UNLOCK(adapter); 885205869Sjfv} 886205869Sjfv 887205869Sjfv/********************************************************************* 888205869Sjfv * Ioctl entry point 889205869Sjfv * 890205869Sjfv * em_ioctl is called when the user wants to configure the 891205869Sjfv * interface. 892205869Sjfv * 893205869Sjfv * return 0 on success, positive on failure 894205869Sjfv **********************************************************************/ 895205869Sjfv 896205869Sjfvstatic int 897205869Sjfvlem_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 898205869Sjfv{ 899205869Sjfv struct adapter *adapter = ifp->if_softc; 900228387Sjfv struct ifreq *ifr = (struct ifreq *)data; 901228387Sjfv#if defined(INET) || defined(INET6) 902228387Sjfv struct ifaddr *ifa = (struct ifaddr *)data; 903205869Sjfv#endif 904228387Sjfv bool avoid_reset = FALSE; 905228387Sjfv int error = 0; 906205869Sjfv 907205869Sjfv if (adapter->in_detach) 908205869Sjfv return (error); 909205869Sjfv 910205869Sjfv switch (command) { 911205869Sjfv case SIOCSIFADDR: 912205869Sjfv#ifdef INET 913228387Sjfv if (ifa->ifa_addr->sa_family == AF_INET) 914228387Sjfv avoid_reset = TRUE; 915228387Sjfv#endif 916228387Sjfv#ifdef INET6 917228387Sjfv if (ifa->ifa_addr->sa_family == AF_INET6) 918228387Sjfv avoid_reset = TRUE; 919228387Sjfv#endif 920228387Sjfv /* 921228387Sjfv ** Calling init results in link renegotiation, 922228387Sjfv ** so we avoid doing it when possible. 923228387Sjfv */ 924228387Sjfv if (avoid_reset) { 925205869Sjfv ifp->if_flags |= IFF_UP; 926228387Sjfv if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 927228387Sjfv lem_init(adapter); 928228387Sjfv#ifdef INET 929228387Sjfv if (!(ifp->if_flags & IFF_NOARP)) 930228387Sjfv arp_ifinit(ifp, ifa); 931228387Sjfv#endif 932205869Sjfv } else 933205869Sjfv error = ether_ioctl(ifp, command, data); 934205869Sjfv break; 935205869Sjfv case SIOCSIFMTU: 936205869Sjfv { 937205869Sjfv int max_frame_size; 938205869Sjfv 939205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); 940205869Sjfv 941205869Sjfv EM_CORE_LOCK(adapter); 942205869Sjfv switch (adapter->hw.mac.type) { 943205869Sjfv case e1000_82542: 944205869Sjfv max_frame_size = ETHER_MAX_LEN; 945205869Sjfv break; 946205869Sjfv default: 947205869Sjfv max_frame_size = MAX_JUMBO_FRAME_SIZE; 948205869Sjfv } 949205869Sjfv if (ifr->ifr_mtu > max_frame_size - ETHER_HDR_LEN - 950205869Sjfv ETHER_CRC_LEN) { 951205869Sjfv EM_CORE_UNLOCK(adapter); 952205869Sjfv error = EINVAL; 953205869Sjfv break; 954205869Sjfv } 955205869Sjfv 956205869Sjfv ifp->if_mtu = ifr->ifr_mtu; 957205869Sjfv adapter->max_frame_size = 958205869Sjfv ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 959205869Sjfv lem_init_locked(adapter); 960205869Sjfv EM_CORE_UNLOCK(adapter); 961205869Sjfv break; 962205869Sjfv } 963205869Sjfv case SIOCSIFFLAGS: 964205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd:\ 965205869Sjfv SIOCSIFFLAGS (Set Interface Flags)"); 966205869Sjfv EM_CORE_LOCK(adapter); 967205869Sjfv if (ifp->if_flags & IFF_UP) { 968205869Sjfv if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) { 969205869Sjfv if ((ifp->if_flags ^ adapter->if_flags) & 970205869Sjfv (IFF_PROMISC | IFF_ALLMULTI)) { 971205869Sjfv lem_disable_promisc(adapter); 972205869Sjfv lem_set_promisc(adapter); 973205869Sjfv } 974205869Sjfv } else 975205869Sjfv lem_init_locked(adapter); 976205869Sjfv } else 977205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 978205869Sjfv EM_TX_LOCK(adapter); 979205869Sjfv lem_stop(adapter); 980205869Sjfv EM_TX_UNLOCK(adapter); 981205869Sjfv } 982205869Sjfv adapter->if_flags = ifp->if_flags; 983205869Sjfv EM_CORE_UNLOCK(adapter); 984205869Sjfv break; 985205869Sjfv case SIOCADDMULTI: 986205869Sjfv case SIOCDELMULTI: 987205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI"); 988205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 989205869Sjfv EM_CORE_LOCK(adapter); 990205869Sjfv lem_disable_intr(adapter); 991205869Sjfv lem_set_multi(adapter); 992205869Sjfv if (adapter->hw.mac.type == e1000_82542 && 993205869Sjfv adapter->hw.revision_id == E1000_REVISION_2) { 994205869Sjfv lem_initialize_receive_unit(adapter); 995205869Sjfv } 996205869Sjfv#ifdef DEVICE_POLLING 997205869Sjfv if (!(ifp->if_capenable & IFCAP_POLLING)) 998205869Sjfv#endif 999205869Sjfv lem_enable_intr(adapter); 1000205869Sjfv EM_CORE_UNLOCK(adapter); 1001205869Sjfv } 1002205869Sjfv break; 1003205869Sjfv case SIOCSIFMEDIA: 1004205869Sjfv /* Check SOL/IDER usage */ 1005205869Sjfv EM_CORE_LOCK(adapter); 1006205869Sjfv if (e1000_check_reset_block(&adapter->hw)) { 1007205869Sjfv EM_CORE_UNLOCK(adapter); 1008205869Sjfv device_printf(adapter->dev, "Media change is" 1009205869Sjfv " blocked due to SOL/IDER session.\n"); 1010205869Sjfv break; 1011205869Sjfv } 1012205869Sjfv EM_CORE_UNLOCK(adapter); 1013205869Sjfv case SIOCGIFMEDIA: 1014205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: \ 1015205869Sjfv SIOCxIFMEDIA (Get/Set Interface Media)"); 1016205869Sjfv error = ifmedia_ioctl(ifp, ifr, &adapter->media, command); 1017205869Sjfv break; 1018205869Sjfv case SIOCSIFCAP: 1019205869Sjfv { 1020205869Sjfv int mask, reinit; 1021205869Sjfv 1022205869Sjfv IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)"); 1023205869Sjfv reinit = 0; 1024205869Sjfv mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1025205869Sjfv#ifdef DEVICE_POLLING 1026205869Sjfv if (mask & IFCAP_POLLING) { 1027205869Sjfv if (ifr->ifr_reqcap & IFCAP_POLLING) { 1028205869Sjfv error = ether_poll_register(lem_poll, ifp); 1029205869Sjfv if (error) 1030205869Sjfv return (error); 1031205869Sjfv EM_CORE_LOCK(adapter); 1032205869Sjfv lem_disable_intr(adapter); 1033205869Sjfv ifp->if_capenable |= IFCAP_POLLING; 1034205869Sjfv EM_CORE_UNLOCK(adapter); 1035205869Sjfv } else { 1036205869Sjfv error = ether_poll_deregister(ifp); 1037205869Sjfv /* Enable interrupt even in error case */ 1038205869Sjfv EM_CORE_LOCK(adapter); 1039205869Sjfv lem_enable_intr(adapter); 1040205869Sjfv ifp->if_capenable &= ~IFCAP_POLLING; 1041205869Sjfv EM_CORE_UNLOCK(adapter); 1042205869Sjfv } 1043205869Sjfv } 1044205869Sjfv#endif 1045205869Sjfv if (mask & IFCAP_HWCSUM) { 1046205869Sjfv ifp->if_capenable ^= IFCAP_HWCSUM; 1047205869Sjfv reinit = 1; 1048205869Sjfv } 1049205869Sjfv if (mask & IFCAP_VLAN_HWTAGGING) { 1050205869Sjfv ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 1051205869Sjfv reinit = 1; 1052205869Sjfv } 1053205869Sjfv if ((mask & IFCAP_WOL) && 1054205869Sjfv (ifp->if_capabilities & IFCAP_WOL) != 0) { 1055205869Sjfv if (mask & IFCAP_WOL_MCAST) 1056205869Sjfv ifp->if_capenable ^= IFCAP_WOL_MCAST; 1057205869Sjfv if (mask & IFCAP_WOL_MAGIC) 1058205869Sjfv ifp->if_capenable ^= IFCAP_WOL_MAGIC; 1059205869Sjfv } 1060205869Sjfv if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING)) 1061205869Sjfv lem_init(adapter); 1062205869Sjfv VLAN_CAPABILITIES(ifp); 1063205869Sjfv break; 1064205869Sjfv } 1065205869Sjfv 1066205869Sjfv default: 1067205869Sjfv error = ether_ioctl(ifp, command, data); 1068205869Sjfv break; 1069205869Sjfv } 1070205869Sjfv 1071205869Sjfv return (error); 1072205869Sjfv} 1073205869Sjfv 1074205869Sjfv 1075205869Sjfv/********************************************************************* 1076205869Sjfv * Init entry point 1077205869Sjfv * 1078205869Sjfv * This routine is used in two ways. It is used by the stack as 1079205869Sjfv * init entry point in network interface structure. It is also used 1080205869Sjfv * by the driver as a hw/sw initialization routine to get to a 1081205869Sjfv * consistent state. 1082205869Sjfv * 1083205869Sjfv * return 0 on success, positive on failure 1084205869Sjfv **********************************************************************/ 1085205869Sjfv 1086205869Sjfvstatic void 1087205869Sjfvlem_init_locked(struct adapter *adapter) 1088205869Sjfv{ 1089205869Sjfv struct ifnet *ifp = adapter->ifp; 1090205869Sjfv device_t dev = adapter->dev; 1091205869Sjfv u32 pba; 1092205869Sjfv 1093205869Sjfv INIT_DEBUGOUT("lem_init: begin"); 1094205869Sjfv 1095205869Sjfv EM_CORE_LOCK_ASSERT(adapter); 1096205869Sjfv 1097205869Sjfv EM_TX_LOCK(adapter); 1098205869Sjfv lem_stop(adapter); 1099205869Sjfv EM_TX_UNLOCK(adapter); 1100205869Sjfv 1101205869Sjfv /* 1102205869Sjfv * Packet Buffer Allocation (PBA) 1103205869Sjfv * Writing PBA sets the receive portion of the buffer 1104205869Sjfv * the remainder is used for the transmit buffer. 1105205869Sjfv * 1106205869Sjfv * Devices before the 82547 had a Packet Buffer of 64K. 1107205869Sjfv * Default allocation: PBA=48K for Rx, leaving 16K for Tx. 1108205869Sjfv * After the 82547 the buffer was reduced to 40K. 1109205869Sjfv * Default allocation: PBA=30K for Rx, leaving 10K for Tx. 1110205869Sjfv * Note: default does not leave enough room for Jumbo Frame >10k. 1111205869Sjfv */ 1112205869Sjfv switch (adapter->hw.mac.type) { 1113205869Sjfv case e1000_82547: 1114205869Sjfv case e1000_82547_rev_2: /* 82547: Total Packet Buffer is 40K */ 1115205869Sjfv if (adapter->max_frame_size > 8192) 1116205869Sjfv pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */ 1117205869Sjfv else 1118205869Sjfv pba = E1000_PBA_30K; /* 30K for Rx, 10K for Tx */ 1119205869Sjfv adapter->tx_fifo_head = 0; 1120205869Sjfv adapter->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT; 1121205869Sjfv adapter->tx_fifo_size = 1122205869Sjfv (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT; 1123205869Sjfv break; 1124205869Sjfv default: 1125205869Sjfv /* Devices before 82547 had a Packet Buffer of 64K. */ 1126205869Sjfv if (adapter->max_frame_size > 8192) 1127205869Sjfv pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */ 1128205869Sjfv else 1129205869Sjfv pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */ 1130205869Sjfv } 1131205869Sjfv 1132205869Sjfv INIT_DEBUGOUT1("lem_init: pba=%dK",pba); 1133205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_PBA, pba); 1134205869Sjfv 1135205869Sjfv /* Get the latest mac address, User can use a LAA */ 1136205869Sjfv bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr, 1137205869Sjfv ETHER_ADDR_LEN); 1138205869Sjfv 1139205869Sjfv /* Put the address into the Receive Address Array */ 1140205869Sjfv e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0); 1141205869Sjfv 1142205869Sjfv /* Initialize the hardware */ 1143205869Sjfv if (lem_hardware_init(adapter)) { 1144205869Sjfv device_printf(dev, "Unable to initialize the hardware\n"); 1145205869Sjfv return; 1146205869Sjfv } 1147205869Sjfv lem_update_link_status(adapter); 1148205869Sjfv 1149205869Sjfv /* Setup VLAN support, basic and offload if available */ 1150205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN); 1151205869Sjfv 1152205869Sjfv /* Set hardware offload abilities */ 1153205869Sjfv ifp->if_hwassist = 0; 1154205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 1155205869Sjfv if (ifp->if_capenable & IFCAP_TXCSUM) 1156205869Sjfv ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); 1157205869Sjfv } 1158205869Sjfv 1159205869Sjfv /* Configure for OS presence */ 1160205869Sjfv lem_init_manageability(adapter); 1161205869Sjfv 1162205869Sjfv /* Prepare transmit descriptors and buffers */ 1163205869Sjfv lem_setup_transmit_structures(adapter); 1164205869Sjfv lem_initialize_transmit_unit(adapter); 1165205869Sjfv 1166205869Sjfv /* Setup Multicast table */ 1167205869Sjfv lem_set_multi(adapter); 1168205869Sjfv 1169205869Sjfv /* Prepare receive descriptors and buffers */ 1170205869Sjfv if (lem_setup_receive_structures(adapter)) { 1171205869Sjfv device_printf(dev, "Could not setup receive structures\n"); 1172205869Sjfv EM_TX_LOCK(adapter); 1173205869Sjfv lem_stop(adapter); 1174205869Sjfv EM_TX_UNLOCK(adapter); 1175205869Sjfv return; 1176205869Sjfv } 1177205869Sjfv lem_initialize_receive_unit(adapter); 1178205869Sjfv 1179214646Sjfv /* Use real VLAN Filter support? */ 1180214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { 1181214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 1182214646Sjfv /* Use real VLAN Filter support */ 1183214646Sjfv lem_setup_vlan_hw_support(adapter); 1184214646Sjfv else { 1185214646Sjfv u32 ctrl; 1186214646Sjfv ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); 1187214646Sjfv ctrl |= E1000_CTRL_VME; 1188214646Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); 1189214646Sjfv } 1190214646Sjfv } 1191214646Sjfv 1192205869Sjfv /* Don't lose promiscuous settings */ 1193205869Sjfv lem_set_promisc(adapter); 1194205869Sjfv 1195205869Sjfv ifp->if_drv_flags |= IFF_DRV_RUNNING; 1196205869Sjfv ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1197205869Sjfv 1198205869Sjfv callout_reset(&adapter->timer, hz, lem_local_timer, adapter); 1199205869Sjfv e1000_clear_hw_cntrs_base_generic(&adapter->hw); 1200205869Sjfv 1201205869Sjfv#ifdef DEVICE_POLLING 1202205869Sjfv /* 1203205869Sjfv * Only enable interrupts if we are not polling, make sure 1204205869Sjfv * they are off otherwise. 1205205869Sjfv */ 1206205869Sjfv if (ifp->if_capenable & IFCAP_POLLING) 1207205869Sjfv lem_disable_intr(adapter); 1208205869Sjfv else 1209205869Sjfv#endif /* DEVICE_POLLING */ 1210205869Sjfv lem_enable_intr(adapter); 1211205869Sjfv 1212205869Sjfv /* AMT based hardware can now take control from firmware */ 1213205869Sjfv if (adapter->has_manage && adapter->has_amt) 1214205869Sjfv lem_get_hw_control(adapter); 1215205869Sjfv} 1216205869Sjfv 1217205869Sjfvstatic void 1218205869Sjfvlem_init(void *arg) 1219205869Sjfv{ 1220205869Sjfv struct adapter *adapter = arg; 1221205869Sjfv 1222205869Sjfv EM_CORE_LOCK(adapter); 1223205869Sjfv lem_init_locked(adapter); 1224205869Sjfv EM_CORE_UNLOCK(adapter); 1225205869Sjfv} 1226205869Sjfv 1227205869Sjfv 1228205869Sjfv#ifdef DEVICE_POLLING 1229205869Sjfv/********************************************************************* 1230205869Sjfv * 1231205869Sjfv * Legacy polling routine 1232205869Sjfv * 1233205869Sjfv *********************************************************************/ 1234205869Sjfvstatic int 1235205869Sjfvlem_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 1236205869Sjfv{ 1237205869Sjfv struct adapter *adapter = ifp->if_softc; 1238205869Sjfv u32 reg_icr, rx_done = 0; 1239205869Sjfv 1240205869Sjfv EM_CORE_LOCK(adapter); 1241205869Sjfv if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1242205869Sjfv EM_CORE_UNLOCK(adapter); 1243205869Sjfv return (rx_done); 1244205869Sjfv } 1245205869Sjfv 1246205869Sjfv if (cmd == POLL_AND_CHECK_STATUS) { 1247205869Sjfv reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); 1248205869Sjfv if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 1249205869Sjfv callout_stop(&adapter->timer); 1250205869Sjfv adapter->hw.mac.get_link_status = 1; 1251205869Sjfv lem_update_link_status(adapter); 1252205869Sjfv callout_reset(&adapter->timer, hz, 1253205869Sjfv lem_local_timer, adapter); 1254205869Sjfv } 1255205869Sjfv } 1256205869Sjfv EM_CORE_UNLOCK(adapter); 1257205869Sjfv 1258209238Sjfv lem_rxeof(adapter, count, &rx_done); 1259205869Sjfv 1260205869Sjfv EM_TX_LOCK(adapter); 1261205869Sjfv lem_txeof(adapter); 1262205869Sjfv if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1263205869Sjfv lem_start_locked(ifp); 1264205869Sjfv EM_TX_UNLOCK(adapter); 1265205869Sjfv return (rx_done); 1266205869Sjfv} 1267205869Sjfv#endif /* DEVICE_POLLING */ 1268205869Sjfv 1269205869Sjfv/********************************************************************* 1270205869Sjfv * 1271205869Sjfv * Legacy Interrupt Service routine 1272205869Sjfv * 1273205869Sjfv *********************************************************************/ 1274205869Sjfvstatic void 1275205869Sjfvlem_intr(void *arg) 1276205869Sjfv{ 1277205869Sjfv struct adapter *adapter = arg; 1278205869Sjfv struct ifnet *ifp = adapter->ifp; 1279205869Sjfv u32 reg_icr; 1280205869Sjfv 1281205869Sjfv 1282238953Sjfv if ((ifp->if_capenable & IFCAP_POLLING) || 1283238953Sjfv ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)) 1284205869Sjfv return; 1285205869Sjfv 1286205869Sjfv EM_CORE_LOCK(adapter); 1287205869Sjfv reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); 1288205869Sjfv if (reg_icr & E1000_ICR_RXO) 1289205869Sjfv adapter->rx_overruns++; 1290205869Sjfv 1291238953Sjfv if ((reg_icr == 0xffffffff) || (reg_icr == 0)) { 1292238953Sjfv EM_CORE_UNLOCK(adapter); 1293238953Sjfv return; 1294238953Sjfv } 1295205869Sjfv 1296205869Sjfv if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 1297205869Sjfv callout_stop(&adapter->timer); 1298205869Sjfv adapter->hw.mac.get_link_status = 1; 1299205869Sjfv lem_update_link_status(adapter); 1300205869Sjfv /* Deal with TX cruft when link lost */ 1301205869Sjfv lem_tx_purge(adapter); 1302205869Sjfv callout_reset(&adapter->timer, hz, 1303205869Sjfv lem_local_timer, adapter); 1304238953Sjfv EM_CORE_UNLOCK(adapter); 1305238953Sjfv return; 1306205869Sjfv } 1307205869Sjfv 1308238953Sjfv EM_CORE_UNLOCK(adapter); 1309238953Sjfv lem_rxeof(adapter, -1, NULL); 1310238953Sjfv 1311205869Sjfv EM_TX_LOCK(adapter); 1312205869Sjfv lem_txeof(adapter); 1313205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING && 1314205869Sjfv !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1315205869Sjfv lem_start_locked(ifp); 1316205869Sjfv EM_TX_UNLOCK(adapter); 1317205869Sjfv return; 1318205869Sjfv} 1319205869Sjfv 1320205869Sjfv 1321205869Sjfvstatic void 1322205869Sjfvlem_handle_link(void *context, int pending) 1323205869Sjfv{ 1324205869Sjfv struct adapter *adapter = context; 1325205869Sjfv struct ifnet *ifp = adapter->ifp; 1326205869Sjfv 1327205869Sjfv if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 1328205869Sjfv return; 1329205869Sjfv 1330205869Sjfv EM_CORE_LOCK(adapter); 1331205869Sjfv callout_stop(&adapter->timer); 1332205869Sjfv lem_update_link_status(adapter); 1333205869Sjfv /* Deal with TX cruft when link lost */ 1334205869Sjfv lem_tx_purge(adapter); 1335205869Sjfv callout_reset(&adapter->timer, hz, lem_local_timer, adapter); 1336205869Sjfv EM_CORE_UNLOCK(adapter); 1337205869Sjfv} 1338205869Sjfv 1339205869Sjfv 1340205869Sjfv/* Combined RX/TX handler, used by Legacy and MSI */ 1341205869Sjfvstatic void 1342205869Sjfvlem_handle_rxtx(void *context, int pending) 1343205869Sjfv{ 1344205869Sjfv struct adapter *adapter = context; 1345205869Sjfv struct ifnet *ifp = adapter->ifp; 1346205869Sjfv 1347205869Sjfv 1348205869Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1349250414Sluigi bool more = lem_rxeof(adapter, adapter->rx_process_limit, NULL); 1350205869Sjfv EM_TX_LOCK(adapter); 1351205869Sjfv lem_txeof(adapter); 1352205869Sjfv if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1353205869Sjfv lem_start_locked(ifp); 1354205869Sjfv EM_TX_UNLOCK(adapter); 1355250414Sluigi if (more) { 1356250414Sluigi taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); 1357250414Sluigi return; 1358250414Sluigi } 1359205869Sjfv } 1360205869Sjfv 1361214646Sjfv if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1362214646Sjfv lem_enable_intr(adapter); 1363205869Sjfv} 1364205869Sjfv 1365205869Sjfv/********************************************************************* 1366205869Sjfv * 1367205869Sjfv * Fast Legacy/MSI Combined Interrupt Service routine 1368205869Sjfv * 1369205869Sjfv *********************************************************************/ 1370205869Sjfvstatic int 1371205869Sjfvlem_irq_fast(void *arg) 1372205869Sjfv{ 1373205869Sjfv struct adapter *adapter = arg; 1374205869Sjfv struct ifnet *ifp; 1375205869Sjfv u32 reg_icr; 1376205869Sjfv 1377205869Sjfv ifp = adapter->ifp; 1378205869Sjfv 1379205869Sjfv reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); 1380205869Sjfv 1381205869Sjfv /* Hot eject? */ 1382205869Sjfv if (reg_icr == 0xffffffff) 1383205869Sjfv return FILTER_STRAY; 1384205869Sjfv 1385205869Sjfv /* Definitely not our interrupt. */ 1386205869Sjfv if (reg_icr == 0x0) 1387205869Sjfv return FILTER_STRAY; 1388205869Sjfv 1389205869Sjfv /* 1390205869Sjfv * Mask interrupts until the taskqueue is finished running. This is 1391205869Sjfv * cheap, just assume that it is needed. This also works around the 1392205869Sjfv * MSI message reordering errata on certain systems. 1393205869Sjfv */ 1394205869Sjfv lem_disable_intr(adapter); 1395205869Sjfv taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); 1396205869Sjfv 1397205869Sjfv /* Link status change */ 1398205869Sjfv if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 1399205869Sjfv adapter->hw.mac.get_link_status = 1; 1400205869Sjfv taskqueue_enqueue(taskqueue_fast, &adapter->link_task); 1401205869Sjfv } 1402205869Sjfv 1403205869Sjfv if (reg_icr & E1000_ICR_RXO) 1404205869Sjfv adapter->rx_overruns++; 1405205869Sjfv return FILTER_HANDLED; 1406205869Sjfv} 1407205869Sjfv 1408205869Sjfv 1409205869Sjfv/********************************************************************* 1410205869Sjfv * 1411205869Sjfv * Media Ioctl callback 1412205869Sjfv * 1413205869Sjfv * This routine is called whenever the user queries the status of 1414205869Sjfv * the interface using ifconfig. 1415205869Sjfv * 1416205869Sjfv **********************************************************************/ 1417205869Sjfvstatic void 1418205869Sjfvlem_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 1419205869Sjfv{ 1420205869Sjfv struct adapter *adapter = ifp->if_softc; 1421205869Sjfv u_char fiber_type = IFM_1000_SX; 1422205869Sjfv 1423205869Sjfv INIT_DEBUGOUT("lem_media_status: begin"); 1424205869Sjfv 1425205869Sjfv EM_CORE_LOCK(adapter); 1426205869Sjfv lem_update_link_status(adapter); 1427205869Sjfv 1428205869Sjfv ifmr->ifm_status = IFM_AVALID; 1429205869Sjfv ifmr->ifm_active = IFM_ETHER; 1430205869Sjfv 1431205869Sjfv if (!adapter->link_active) { 1432205869Sjfv EM_CORE_UNLOCK(adapter); 1433205869Sjfv return; 1434205869Sjfv } 1435205869Sjfv 1436205869Sjfv ifmr->ifm_status |= IFM_ACTIVE; 1437205869Sjfv 1438205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 1439205869Sjfv (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) { 1440205869Sjfv if (adapter->hw.mac.type == e1000_82545) 1441205869Sjfv fiber_type = IFM_1000_LX; 1442205869Sjfv ifmr->ifm_active |= fiber_type | IFM_FDX; 1443205869Sjfv } else { 1444205869Sjfv switch (adapter->link_speed) { 1445205869Sjfv case 10: 1446205869Sjfv ifmr->ifm_active |= IFM_10_T; 1447205869Sjfv break; 1448205869Sjfv case 100: 1449205869Sjfv ifmr->ifm_active |= IFM_100_TX; 1450205869Sjfv break; 1451205869Sjfv case 1000: 1452205869Sjfv ifmr->ifm_active |= IFM_1000_T; 1453205869Sjfv break; 1454205869Sjfv } 1455205869Sjfv if (adapter->link_duplex == FULL_DUPLEX) 1456205869Sjfv ifmr->ifm_active |= IFM_FDX; 1457205869Sjfv else 1458205869Sjfv ifmr->ifm_active |= IFM_HDX; 1459205869Sjfv } 1460205869Sjfv EM_CORE_UNLOCK(adapter); 1461205869Sjfv} 1462205869Sjfv 1463205869Sjfv/********************************************************************* 1464205869Sjfv * 1465205869Sjfv * Media Ioctl callback 1466205869Sjfv * 1467205869Sjfv * This routine is called when the user changes speed/duplex using 1468205869Sjfv * media/mediopt option with ifconfig. 1469205869Sjfv * 1470205869Sjfv **********************************************************************/ 1471205869Sjfvstatic int 1472205869Sjfvlem_media_change(struct ifnet *ifp) 1473205869Sjfv{ 1474205869Sjfv struct adapter *adapter = ifp->if_softc; 1475205869Sjfv struct ifmedia *ifm = &adapter->media; 1476205869Sjfv 1477205869Sjfv INIT_DEBUGOUT("lem_media_change: begin"); 1478205869Sjfv 1479205869Sjfv if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1480205869Sjfv return (EINVAL); 1481205869Sjfv 1482205869Sjfv EM_CORE_LOCK(adapter); 1483205869Sjfv switch (IFM_SUBTYPE(ifm->ifm_media)) { 1484205869Sjfv case IFM_AUTO: 1485205869Sjfv adapter->hw.mac.autoneg = DO_AUTO_NEG; 1486205869Sjfv adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT; 1487205869Sjfv break; 1488205869Sjfv case IFM_1000_LX: 1489205869Sjfv case IFM_1000_SX: 1490205869Sjfv case IFM_1000_T: 1491205869Sjfv adapter->hw.mac.autoneg = DO_AUTO_NEG; 1492205869Sjfv adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; 1493205869Sjfv break; 1494205869Sjfv case IFM_100_TX: 1495205869Sjfv adapter->hw.mac.autoneg = FALSE; 1496205869Sjfv adapter->hw.phy.autoneg_advertised = 0; 1497205869Sjfv if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1498205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_FULL; 1499205869Sjfv else 1500205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_HALF; 1501205869Sjfv break; 1502205869Sjfv case IFM_10_T: 1503205869Sjfv adapter->hw.mac.autoneg = FALSE; 1504205869Sjfv adapter->hw.phy.autoneg_advertised = 0; 1505205869Sjfv if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1506205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_FULL; 1507205869Sjfv else 1508205869Sjfv adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_HALF; 1509205869Sjfv break; 1510205869Sjfv default: 1511205869Sjfv device_printf(adapter->dev, "Unsupported media type\n"); 1512205869Sjfv } 1513205869Sjfv 1514205869Sjfv lem_init_locked(adapter); 1515205869Sjfv EM_CORE_UNLOCK(adapter); 1516205869Sjfv 1517205869Sjfv return (0); 1518205869Sjfv} 1519205869Sjfv 1520205869Sjfv/********************************************************************* 1521205869Sjfv * 1522205869Sjfv * This routine maps the mbufs to tx descriptors. 1523205869Sjfv * 1524205869Sjfv * return 0 on success, positive on failure 1525205869Sjfv **********************************************************************/ 1526205869Sjfv 1527205869Sjfvstatic int 1528205869Sjfvlem_xmit(struct adapter *adapter, struct mbuf **m_headp) 1529205869Sjfv{ 1530205869Sjfv bus_dma_segment_t segs[EM_MAX_SCATTER]; 1531205869Sjfv bus_dmamap_t map; 1532205869Sjfv struct em_buffer *tx_buffer, *tx_buffer_mapped; 1533205869Sjfv struct e1000_tx_desc *ctxd = NULL; 1534205869Sjfv struct mbuf *m_head; 1535205869Sjfv u32 txd_upper, txd_lower, txd_used, txd_saved; 1536205869Sjfv int error, nsegs, i, j, first, last = 0; 1537214646Sjfv 1538205869Sjfv m_head = *m_headp; 1539205869Sjfv txd_upper = txd_lower = txd_used = txd_saved = 0; 1540205869Sjfv 1541205869Sjfv /* 1542209959Sjfv ** When doing checksum offload, it is critical to 1543209959Sjfv ** make sure the first mbuf has more than header, 1544209959Sjfv ** because that routine expects data to be present. 1545209959Sjfv */ 1546209959Sjfv if ((m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) && 1547209959Sjfv (m_head->m_len < ETHER_HDR_LEN + sizeof(struct ip))) { 1548209959Sjfv m_head = m_pullup(m_head, ETHER_HDR_LEN + sizeof(struct ip)); 1549209959Sjfv *m_headp = m_head; 1550209959Sjfv if (m_head == NULL) 1551209959Sjfv return (ENOBUFS); 1552209959Sjfv } 1553209959Sjfv 1554209959Sjfv /* 1555205869Sjfv * Map the packet for DMA 1556205869Sjfv * 1557205869Sjfv * Capture the first descriptor index, 1558205869Sjfv * this descriptor will have the index 1559205869Sjfv * of the EOP which is the only one that 1560205869Sjfv * now gets a DONE bit writeback. 1561205869Sjfv */ 1562205869Sjfv first = adapter->next_avail_tx_desc; 1563205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 1564205869Sjfv tx_buffer_mapped = tx_buffer; 1565205869Sjfv map = tx_buffer->map; 1566205869Sjfv 1567205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, 1568205869Sjfv *m_headp, segs, &nsegs, BUS_DMA_NOWAIT); 1569205869Sjfv 1570205869Sjfv /* 1571205869Sjfv * There are two types of errors we can (try) to handle: 1572205869Sjfv * - EFBIG means the mbuf chain was too long and bus_dma ran 1573205869Sjfv * out of segments. Defragment the mbuf chain and try again. 1574205869Sjfv * - ENOMEM means bus_dma could not obtain enough bounce buffers 1575205869Sjfv * at this point in time. Defer sending and try again later. 1576205869Sjfv * All other errors, in particular EINVAL, are fatal and prevent the 1577205869Sjfv * mbuf chain from ever going through. Drop it and report error. 1578205869Sjfv */ 1579205869Sjfv if (error == EFBIG) { 1580205869Sjfv struct mbuf *m; 1581205869Sjfv 1582243857Sglebius m = m_defrag(*m_headp, M_NOWAIT); 1583205869Sjfv if (m == NULL) { 1584205869Sjfv adapter->mbuf_alloc_failed++; 1585205869Sjfv m_freem(*m_headp); 1586205869Sjfv *m_headp = NULL; 1587205869Sjfv return (ENOBUFS); 1588205869Sjfv } 1589205869Sjfv *m_headp = m; 1590205869Sjfv 1591205869Sjfv /* Try it again */ 1592205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, 1593205869Sjfv *m_headp, segs, &nsegs, BUS_DMA_NOWAIT); 1594205869Sjfv 1595205869Sjfv if (error) { 1596205869Sjfv adapter->no_tx_dma_setup++; 1597205869Sjfv m_freem(*m_headp); 1598205869Sjfv *m_headp = NULL; 1599205869Sjfv return (error); 1600205869Sjfv } 1601205869Sjfv } else if (error != 0) { 1602205869Sjfv adapter->no_tx_dma_setup++; 1603205869Sjfv return (error); 1604205869Sjfv } 1605205869Sjfv 1606205869Sjfv if (nsegs > (adapter->num_tx_desc_avail - 2)) { 1607205869Sjfv adapter->no_tx_desc_avail2++; 1608205869Sjfv bus_dmamap_unload(adapter->txtag, map); 1609205869Sjfv return (ENOBUFS); 1610205869Sjfv } 1611205869Sjfv m_head = *m_headp; 1612205869Sjfv 1613205869Sjfv /* Do hardware assists */ 1614205869Sjfv if (m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) 1615205869Sjfv lem_transmit_checksum_setup(adapter, m_head, 1616205869Sjfv &txd_upper, &txd_lower); 1617205869Sjfv 1618205869Sjfv i = adapter->next_avail_tx_desc; 1619205869Sjfv if (adapter->pcix_82544) 1620205869Sjfv txd_saved = i; 1621205869Sjfv 1622205869Sjfv /* Set up our transmit descriptors */ 1623205869Sjfv for (j = 0; j < nsegs; j++) { 1624205869Sjfv bus_size_t seg_len; 1625205869Sjfv bus_addr_t seg_addr; 1626205869Sjfv /* If adapter is 82544 and on PCIX bus */ 1627205869Sjfv if(adapter->pcix_82544) { 1628205869Sjfv DESC_ARRAY desc_array; 1629205869Sjfv u32 array_elements, counter; 1630205869Sjfv /* 1631205869Sjfv * Check the Address and Length combination and 1632205869Sjfv * split the data accordingly 1633205869Sjfv */ 1634205869Sjfv array_elements = lem_fill_descriptors(segs[j].ds_addr, 1635205869Sjfv segs[j].ds_len, &desc_array); 1636205869Sjfv for (counter = 0; counter < array_elements; counter++) { 1637205869Sjfv if (txd_used == adapter->num_tx_desc_avail) { 1638205869Sjfv adapter->next_avail_tx_desc = txd_saved; 1639205869Sjfv adapter->no_tx_desc_avail2++; 1640205869Sjfv bus_dmamap_unload(adapter->txtag, map); 1641205869Sjfv return (ENOBUFS); 1642205869Sjfv } 1643205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 1644205869Sjfv ctxd = &adapter->tx_desc_base[i]; 1645205869Sjfv ctxd->buffer_addr = htole64( 1646205869Sjfv desc_array.descriptor[counter].address); 1647205869Sjfv ctxd->lower.data = htole32( 1648205869Sjfv (adapter->txd_cmd | txd_lower | (u16) 1649205869Sjfv desc_array.descriptor[counter].length)); 1650205869Sjfv ctxd->upper.data = 1651205869Sjfv htole32((txd_upper)); 1652205869Sjfv last = i; 1653205869Sjfv if (++i == adapter->num_tx_desc) 1654205869Sjfv i = 0; 1655205869Sjfv tx_buffer->m_head = NULL; 1656205869Sjfv tx_buffer->next_eop = -1; 1657205869Sjfv txd_used++; 1658205869Sjfv } 1659205869Sjfv } else { 1660205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 1661205869Sjfv ctxd = &adapter->tx_desc_base[i]; 1662205869Sjfv seg_addr = segs[j].ds_addr; 1663205869Sjfv seg_len = segs[j].ds_len; 1664205869Sjfv ctxd->buffer_addr = htole64(seg_addr); 1665205869Sjfv ctxd->lower.data = htole32( 1666205869Sjfv adapter->txd_cmd | txd_lower | seg_len); 1667205869Sjfv ctxd->upper.data = 1668205869Sjfv htole32(txd_upper); 1669205869Sjfv last = i; 1670205869Sjfv if (++i == adapter->num_tx_desc) 1671205869Sjfv i = 0; 1672205869Sjfv tx_buffer->m_head = NULL; 1673205869Sjfv tx_buffer->next_eop = -1; 1674205869Sjfv } 1675205869Sjfv } 1676205869Sjfv 1677205869Sjfv adapter->next_avail_tx_desc = i; 1678205869Sjfv 1679205869Sjfv if (adapter->pcix_82544) 1680205869Sjfv adapter->num_tx_desc_avail -= txd_used; 1681205869Sjfv else 1682205869Sjfv adapter->num_tx_desc_avail -= nsegs; 1683205869Sjfv 1684205869Sjfv if (m_head->m_flags & M_VLANTAG) { 1685205869Sjfv /* Set the vlan id. */ 1686205869Sjfv ctxd->upper.fields.special = 1687205869Sjfv htole16(m_head->m_pkthdr.ether_vtag); 1688205869Sjfv /* Tell hardware to add tag */ 1689205869Sjfv ctxd->lower.data |= htole32(E1000_TXD_CMD_VLE); 1690205869Sjfv } 1691205869Sjfv 1692205869Sjfv tx_buffer->m_head = m_head; 1693205869Sjfv tx_buffer_mapped->map = tx_buffer->map; 1694205869Sjfv tx_buffer->map = map; 1695205869Sjfv bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE); 1696205869Sjfv 1697205869Sjfv /* 1698205869Sjfv * Last Descriptor of Packet 1699205869Sjfv * needs End Of Packet (EOP) 1700205869Sjfv * and Report Status (RS) 1701205869Sjfv */ 1702205869Sjfv ctxd->lower.data |= 1703205869Sjfv htole32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS); 1704205869Sjfv /* 1705205869Sjfv * Keep track in the first buffer which 1706205869Sjfv * descriptor will be written back 1707205869Sjfv */ 1708205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 1709205869Sjfv tx_buffer->next_eop = last; 1710213234Sjfv adapter->watchdog_time = ticks; 1711205869Sjfv 1712205869Sjfv /* 1713205869Sjfv * Advance the Transmit Descriptor Tail (TDT), this tells the E1000 1714205869Sjfv * that this frame is available to transmit. 1715205869Sjfv */ 1716205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 1717205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1718205869Sjfv if (adapter->hw.mac.type == e1000_82547 && 1719205869Sjfv adapter->link_duplex == HALF_DUPLEX) 1720205869Sjfv lem_82547_move_tail(adapter); 1721205869Sjfv else { 1722205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), i); 1723205869Sjfv if (adapter->hw.mac.type == e1000_82547) 1724205869Sjfv lem_82547_update_fifo_head(adapter, 1725205869Sjfv m_head->m_pkthdr.len); 1726205869Sjfv } 1727205869Sjfv 1728205869Sjfv return (0); 1729205869Sjfv} 1730205869Sjfv 1731205869Sjfv/********************************************************************* 1732205869Sjfv * 1733205869Sjfv * 82547 workaround to avoid controller hang in half-duplex environment. 1734205869Sjfv * The workaround is to avoid queuing a large packet that would span 1735205869Sjfv * the internal Tx FIFO ring boundary. We need to reset the FIFO pointers 1736205869Sjfv * in this case. We do that only when FIFO is quiescent. 1737205869Sjfv * 1738205869Sjfv **********************************************************************/ 1739205869Sjfvstatic void 1740205869Sjfvlem_82547_move_tail(void *arg) 1741205869Sjfv{ 1742205869Sjfv struct adapter *adapter = arg; 1743205869Sjfv struct e1000_tx_desc *tx_desc; 1744205869Sjfv u16 hw_tdt, sw_tdt, length = 0; 1745205869Sjfv bool eop = 0; 1746205869Sjfv 1747205869Sjfv EM_TX_LOCK_ASSERT(adapter); 1748205869Sjfv 1749205869Sjfv hw_tdt = E1000_READ_REG(&adapter->hw, E1000_TDT(0)); 1750205869Sjfv sw_tdt = adapter->next_avail_tx_desc; 1751205869Sjfv 1752205869Sjfv while (hw_tdt != sw_tdt) { 1753205869Sjfv tx_desc = &adapter->tx_desc_base[hw_tdt]; 1754205869Sjfv length += tx_desc->lower.flags.length; 1755205869Sjfv eop = tx_desc->lower.data & E1000_TXD_CMD_EOP; 1756205869Sjfv if (++hw_tdt == adapter->num_tx_desc) 1757205869Sjfv hw_tdt = 0; 1758205869Sjfv 1759205869Sjfv if (eop) { 1760205869Sjfv if (lem_82547_fifo_workaround(adapter, length)) { 1761205869Sjfv adapter->tx_fifo_wrk_cnt++; 1762205869Sjfv callout_reset(&adapter->tx_fifo_timer, 1, 1763205869Sjfv lem_82547_move_tail, adapter); 1764205869Sjfv break; 1765205869Sjfv } 1766205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), hw_tdt); 1767205869Sjfv lem_82547_update_fifo_head(adapter, length); 1768205869Sjfv length = 0; 1769205869Sjfv } 1770205869Sjfv } 1771205869Sjfv} 1772205869Sjfv 1773205869Sjfvstatic int 1774205869Sjfvlem_82547_fifo_workaround(struct adapter *adapter, int len) 1775205869Sjfv{ 1776205869Sjfv int fifo_space, fifo_pkt_len; 1777205869Sjfv 1778205869Sjfv fifo_pkt_len = roundup2(len + EM_FIFO_HDR, EM_FIFO_HDR); 1779205869Sjfv 1780205869Sjfv if (adapter->link_duplex == HALF_DUPLEX) { 1781205869Sjfv fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; 1782205869Sjfv 1783205869Sjfv if (fifo_pkt_len >= (EM_82547_PKT_THRESH + fifo_space)) { 1784205869Sjfv if (lem_82547_tx_fifo_reset(adapter)) 1785205869Sjfv return (0); 1786205869Sjfv else 1787205869Sjfv return (1); 1788205869Sjfv } 1789205869Sjfv } 1790205869Sjfv 1791205869Sjfv return (0); 1792205869Sjfv} 1793205869Sjfv 1794205869Sjfvstatic void 1795205869Sjfvlem_82547_update_fifo_head(struct adapter *adapter, int len) 1796205869Sjfv{ 1797205869Sjfv int fifo_pkt_len = roundup2(len + EM_FIFO_HDR, EM_FIFO_HDR); 1798205869Sjfv 1799205869Sjfv /* tx_fifo_head is always 16 byte aligned */ 1800205869Sjfv adapter->tx_fifo_head += fifo_pkt_len; 1801205869Sjfv if (adapter->tx_fifo_head >= adapter->tx_fifo_size) { 1802205869Sjfv adapter->tx_fifo_head -= adapter->tx_fifo_size; 1803205869Sjfv } 1804205869Sjfv} 1805205869Sjfv 1806205869Sjfv 1807205869Sjfvstatic int 1808205869Sjfvlem_82547_tx_fifo_reset(struct adapter *adapter) 1809205869Sjfv{ 1810205869Sjfv u32 tctl; 1811205869Sjfv 1812205869Sjfv if ((E1000_READ_REG(&adapter->hw, E1000_TDT(0)) == 1813205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDH(0))) && 1814205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_TDFT) == 1815205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDFH)) && 1816205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_TDFTS) == 1817205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDFHS)) && 1818205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_TDFPC) == 0)) { 1819205869Sjfv /* Disable TX unit */ 1820205869Sjfv tctl = E1000_READ_REG(&adapter->hw, E1000_TCTL); 1821205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, 1822205869Sjfv tctl & ~E1000_TCTL_EN); 1823205869Sjfv 1824205869Sjfv /* Reset FIFO pointers */ 1825205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFT, 1826205869Sjfv adapter->tx_head_addr); 1827205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFH, 1828205869Sjfv adapter->tx_head_addr); 1829205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFTS, 1830205869Sjfv adapter->tx_head_addr); 1831205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDFHS, 1832205869Sjfv adapter->tx_head_addr); 1833205869Sjfv 1834205869Sjfv /* Re-enable TX unit */ 1835205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); 1836205869Sjfv E1000_WRITE_FLUSH(&adapter->hw); 1837205869Sjfv 1838205869Sjfv adapter->tx_fifo_head = 0; 1839205869Sjfv adapter->tx_fifo_reset_cnt++; 1840205869Sjfv 1841205869Sjfv return (TRUE); 1842205869Sjfv } 1843205869Sjfv else { 1844205869Sjfv return (FALSE); 1845205869Sjfv } 1846205869Sjfv} 1847205869Sjfv 1848205869Sjfvstatic void 1849205869Sjfvlem_set_promisc(struct adapter *adapter) 1850205869Sjfv{ 1851205869Sjfv struct ifnet *ifp = adapter->ifp; 1852205869Sjfv u32 reg_rctl; 1853205869Sjfv 1854205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 1855205869Sjfv 1856205869Sjfv if (ifp->if_flags & IFF_PROMISC) { 1857205869Sjfv reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); 1858205869Sjfv /* Turn this on if you want to see bad packets */ 1859205869Sjfv if (lem_debug_sbp) 1860205869Sjfv reg_rctl |= E1000_RCTL_SBP; 1861205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1862205869Sjfv } else if (ifp->if_flags & IFF_ALLMULTI) { 1863205869Sjfv reg_rctl |= E1000_RCTL_MPE; 1864205869Sjfv reg_rctl &= ~E1000_RCTL_UPE; 1865205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1866205869Sjfv } 1867205869Sjfv} 1868205869Sjfv 1869205869Sjfvstatic void 1870205869Sjfvlem_disable_promisc(struct adapter *adapter) 1871205869Sjfv{ 1872249074Sjfv struct ifnet *ifp = adapter->ifp; 1873249074Sjfv u32 reg_rctl; 1874249074Sjfv int mcnt = 0; 1875205869Sjfv 1876205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 1877205869Sjfv reg_rctl &= (~E1000_RCTL_UPE); 1878249074Sjfv if (ifp->if_flags & IFF_ALLMULTI) 1879249074Sjfv mcnt = MAX_NUM_MULTICAST_ADDRESSES; 1880249074Sjfv else { 1881249074Sjfv struct ifmultiaddr *ifma; 1882249074Sjfv#if __FreeBSD_version < 800000 1883249074Sjfv IF_ADDR_LOCK(ifp); 1884249074Sjfv#else 1885249074Sjfv if_maddr_rlock(ifp); 1886249074Sjfv#endif 1887249074Sjfv TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1888249074Sjfv if (ifma->ifma_addr->sa_family != AF_LINK) 1889249074Sjfv continue; 1890249074Sjfv if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 1891249074Sjfv break; 1892249074Sjfv mcnt++; 1893249074Sjfv } 1894249074Sjfv#if __FreeBSD_version < 800000 1895249074Sjfv IF_ADDR_UNLOCK(ifp); 1896249074Sjfv#else 1897249074Sjfv if_maddr_runlock(ifp); 1898249074Sjfv#endif 1899249074Sjfv } 1900249074Sjfv /* Don't disable if in MAX groups */ 1901249074Sjfv if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) 1902249074Sjfv reg_rctl &= (~E1000_RCTL_MPE); 1903205869Sjfv reg_rctl &= (~E1000_RCTL_SBP); 1904205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1905205869Sjfv} 1906205869Sjfv 1907205869Sjfv 1908205869Sjfv/********************************************************************* 1909205869Sjfv * Multicast Update 1910205869Sjfv * 1911205869Sjfv * This routine is called whenever multicast address list is updated. 1912205869Sjfv * 1913205869Sjfv **********************************************************************/ 1914205869Sjfv 1915205869Sjfvstatic void 1916205869Sjfvlem_set_multi(struct adapter *adapter) 1917205869Sjfv{ 1918205869Sjfv struct ifnet *ifp = adapter->ifp; 1919205869Sjfv struct ifmultiaddr *ifma; 1920205869Sjfv u32 reg_rctl = 0; 1921205869Sjfv u8 *mta; /* Multicast array memory */ 1922205869Sjfv int mcnt = 0; 1923205869Sjfv 1924205869Sjfv IOCTL_DEBUGOUT("lem_set_multi: begin"); 1925205869Sjfv 1926211913Syongari mta = adapter->mta; 1927211913Syongari bzero(mta, sizeof(u8) * ETH_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES); 1928211913Syongari 1929205869Sjfv if (adapter->hw.mac.type == e1000_82542 && 1930205869Sjfv adapter->hw.revision_id == E1000_REVISION_2) { 1931205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 1932205869Sjfv if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) 1933205869Sjfv e1000_pci_clear_mwi(&adapter->hw); 1934205869Sjfv reg_rctl |= E1000_RCTL_RST; 1935205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1936205869Sjfv msec_delay(5); 1937205869Sjfv } 1938205869Sjfv 1939205869Sjfv#if __FreeBSD_version < 800000 1940205869Sjfv IF_ADDR_LOCK(ifp); 1941205869Sjfv#else 1942205869Sjfv if_maddr_rlock(ifp); 1943205869Sjfv#endif 1944205869Sjfv TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1945205869Sjfv if (ifma->ifma_addr->sa_family != AF_LINK) 1946205869Sjfv continue; 1947205869Sjfv 1948205869Sjfv if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) 1949205869Sjfv break; 1950205869Sjfv 1951205869Sjfv bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 1952205869Sjfv &mta[mcnt * ETH_ADDR_LEN], ETH_ADDR_LEN); 1953205869Sjfv mcnt++; 1954205869Sjfv } 1955205869Sjfv#if __FreeBSD_version < 800000 1956205869Sjfv IF_ADDR_UNLOCK(ifp); 1957205869Sjfv#else 1958205869Sjfv if_maddr_runlock(ifp); 1959205869Sjfv#endif 1960205869Sjfv if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) { 1961205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 1962205869Sjfv reg_rctl |= E1000_RCTL_MPE; 1963205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1964205869Sjfv } else 1965205869Sjfv e1000_update_mc_addr_list(&adapter->hw, mta, mcnt); 1966205869Sjfv 1967205869Sjfv if (adapter->hw.mac.type == e1000_82542 && 1968205869Sjfv adapter->hw.revision_id == E1000_REVISION_2) { 1969205869Sjfv reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 1970205869Sjfv reg_rctl &= ~E1000_RCTL_RST; 1971205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); 1972205869Sjfv msec_delay(5); 1973205869Sjfv if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) 1974205869Sjfv e1000_pci_set_mwi(&adapter->hw); 1975205869Sjfv } 1976205869Sjfv} 1977205869Sjfv 1978205869Sjfv 1979205869Sjfv/********************************************************************* 1980205869Sjfv * Timer routine 1981205869Sjfv * 1982205869Sjfv * This routine checks for link status and updates statistics. 1983205869Sjfv * 1984205869Sjfv **********************************************************************/ 1985205869Sjfv 1986205869Sjfvstatic void 1987205869Sjfvlem_local_timer(void *arg) 1988205869Sjfv{ 1989205869Sjfv struct adapter *adapter = arg; 1990205869Sjfv 1991205869Sjfv EM_CORE_LOCK_ASSERT(adapter); 1992205869Sjfv 1993205869Sjfv lem_update_link_status(adapter); 1994205869Sjfv lem_update_stats_counters(adapter); 1995205869Sjfv 1996205869Sjfv lem_smartspeed(adapter); 1997205869Sjfv 1998205869Sjfv /* 1999205869Sjfv * We check the watchdog: the time since 2000205869Sjfv * the last TX descriptor was cleaned. 2001205869Sjfv * This implies a functional TX engine. 2002205869Sjfv */ 2003205869Sjfv if ((adapter->watchdog_check == TRUE) && 2004205869Sjfv (ticks - adapter->watchdog_time > EM_WATCHDOG)) 2005205869Sjfv goto hung; 2006205869Sjfv 2007205869Sjfv callout_reset(&adapter->timer, hz, lem_local_timer, adapter); 2008205869Sjfv return; 2009205869Sjfvhung: 2010205869Sjfv device_printf(adapter->dev, "Watchdog timeout -- resetting\n"); 2011205869Sjfv adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 2012205869Sjfv adapter->watchdog_events++; 2013205869Sjfv lem_init_locked(adapter); 2014205869Sjfv} 2015205869Sjfv 2016205869Sjfvstatic void 2017205869Sjfvlem_update_link_status(struct adapter *adapter) 2018205869Sjfv{ 2019205869Sjfv struct e1000_hw *hw = &adapter->hw; 2020205869Sjfv struct ifnet *ifp = adapter->ifp; 2021205869Sjfv device_t dev = adapter->dev; 2022205869Sjfv u32 link_check = 0; 2023205869Sjfv 2024205869Sjfv /* Get the cached link value or read phy for real */ 2025205869Sjfv switch (hw->phy.media_type) { 2026205869Sjfv case e1000_media_type_copper: 2027205869Sjfv if (hw->mac.get_link_status) { 2028205869Sjfv /* Do the work to read phy */ 2029205869Sjfv e1000_check_for_link(hw); 2030205869Sjfv link_check = !hw->mac.get_link_status; 2031205869Sjfv if (link_check) /* ESB2 fix */ 2032205869Sjfv e1000_cfg_on_link_up(hw); 2033205869Sjfv } else 2034205869Sjfv link_check = TRUE; 2035205869Sjfv break; 2036205869Sjfv case e1000_media_type_fiber: 2037205869Sjfv e1000_check_for_link(hw); 2038205869Sjfv link_check = (E1000_READ_REG(hw, E1000_STATUS) & 2039205869Sjfv E1000_STATUS_LU); 2040205869Sjfv break; 2041205869Sjfv case e1000_media_type_internal_serdes: 2042205869Sjfv e1000_check_for_link(hw); 2043205869Sjfv link_check = adapter->hw.mac.serdes_has_link; 2044205869Sjfv break; 2045205869Sjfv default: 2046205869Sjfv case e1000_media_type_unknown: 2047205869Sjfv break; 2048205869Sjfv } 2049205869Sjfv 2050205869Sjfv /* Now check for a transition */ 2051205869Sjfv if (link_check && (adapter->link_active == 0)) { 2052205869Sjfv e1000_get_speed_and_duplex(hw, &adapter->link_speed, 2053205869Sjfv &adapter->link_duplex); 2054205869Sjfv if (bootverbose) 2055205869Sjfv device_printf(dev, "Link is up %d Mbps %s\n", 2056205869Sjfv adapter->link_speed, 2057205869Sjfv ((adapter->link_duplex == FULL_DUPLEX) ? 2058205869Sjfv "Full Duplex" : "Half Duplex")); 2059205869Sjfv adapter->link_active = 1; 2060205869Sjfv adapter->smartspeed = 0; 2061205869Sjfv ifp->if_baudrate = adapter->link_speed * 1000000; 2062205869Sjfv if_link_state_change(ifp, LINK_STATE_UP); 2063205869Sjfv } else if (!link_check && (adapter->link_active == 1)) { 2064205869Sjfv ifp->if_baudrate = adapter->link_speed = 0; 2065205869Sjfv adapter->link_duplex = 0; 2066205869Sjfv if (bootverbose) 2067205869Sjfv device_printf(dev, "Link is Down\n"); 2068205869Sjfv adapter->link_active = 0; 2069205869Sjfv /* Link down, disable watchdog */ 2070205869Sjfv adapter->watchdog_check = FALSE; 2071205869Sjfv if_link_state_change(ifp, LINK_STATE_DOWN); 2072205869Sjfv } 2073205869Sjfv} 2074205869Sjfv 2075205869Sjfv/********************************************************************* 2076205869Sjfv * 2077205869Sjfv * This routine disables all traffic on the adapter by issuing a 2078205869Sjfv * global reset on the MAC and deallocates TX/RX buffers. 2079205869Sjfv * 2080205869Sjfv * This routine should always be called with BOTH the CORE 2081205869Sjfv * and TX locks. 2082205869Sjfv **********************************************************************/ 2083205869Sjfv 2084205869Sjfvstatic void 2085205869Sjfvlem_stop(void *arg) 2086205869Sjfv{ 2087205869Sjfv struct adapter *adapter = arg; 2088205869Sjfv struct ifnet *ifp = adapter->ifp; 2089205869Sjfv 2090205869Sjfv EM_CORE_LOCK_ASSERT(adapter); 2091205869Sjfv EM_TX_LOCK_ASSERT(adapter); 2092205869Sjfv 2093205869Sjfv INIT_DEBUGOUT("lem_stop: begin"); 2094205869Sjfv 2095205869Sjfv lem_disable_intr(adapter); 2096205869Sjfv callout_stop(&adapter->timer); 2097205869Sjfv callout_stop(&adapter->tx_fifo_timer); 2098205869Sjfv 2099205869Sjfv /* Tell the stack that the interface is no longer active */ 2100205869Sjfv ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2101205869Sjfv 2102205869Sjfv e1000_reset_hw(&adapter->hw); 2103205869Sjfv if (adapter->hw.mac.type >= e1000_82544) 2104205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0); 2105206001Smarius 2106206001Smarius e1000_led_off(&adapter->hw); 2107206001Smarius e1000_cleanup_led(&adapter->hw); 2108205869Sjfv} 2109205869Sjfv 2110205869Sjfv 2111205869Sjfv/********************************************************************* 2112205869Sjfv * 2113205869Sjfv * Determine hardware revision. 2114205869Sjfv * 2115205869Sjfv **********************************************************************/ 2116205869Sjfvstatic void 2117205869Sjfvlem_identify_hardware(struct adapter *adapter) 2118205869Sjfv{ 2119205869Sjfv device_t dev = adapter->dev; 2120205869Sjfv 2121205869Sjfv /* Make sure our PCI config space has the necessary stuff set */ 2122254263Sscottl pci_enable_busmaster(dev); 2123205869Sjfv adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); 2124205869Sjfv 2125205869Sjfv /* Save off the information about this board */ 2126205869Sjfv adapter->hw.vendor_id = pci_get_vendor(dev); 2127205869Sjfv adapter->hw.device_id = pci_get_device(dev); 2128205869Sjfv adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1); 2129205869Sjfv adapter->hw.subsystem_vendor_id = 2130205869Sjfv pci_read_config(dev, PCIR_SUBVEND_0, 2); 2131205869Sjfv adapter->hw.subsystem_device_id = 2132205869Sjfv pci_read_config(dev, PCIR_SUBDEV_0, 2); 2133205869Sjfv 2134205869Sjfv /* Do Shared Code Init and Setup */ 2135205869Sjfv if (e1000_set_mac_type(&adapter->hw)) { 2136205869Sjfv device_printf(dev, "Setup init failure\n"); 2137205869Sjfv return; 2138205869Sjfv } 2139205869Sjfv} 2140205869Sjfv 2141205869Sjfvstatic int 2142205869Sjfvlem_allocate_pci_resources(struct adapter *adapter) 2143205869Sjfv{ 2144205869Sjfv device_t dev = adapter->dev; 2145205869Sjfv int val, rid, error = E1000_SUCCESS; 2146205869Sjfv 2147205869Sjfv rid = PCIR_BAR(0); 2148205869Sjfv adapter->memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 2149205869Sjfv &rid, RF_ACTIVE); 2150205869Sjfv if (adapter->memory == NULL) { 2151205869Sjfv device_printf(dev, "Unable to allocate bus resource: memory\n"); 2152205869Sjfv return (ENXIO); 2153205869Sjfv } 2154205869Sjfv adapter->osdep.mem_bus_space_tag = 2155205869Sjfv rman_get_bustag(adapter->memory); 2156205869Sjfv adapter->osdep.mem_bus_space_handle = 2157205869Sjfv rman_get_bushandle(adapter->memory); 2158205869Sjfv adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle; 2159205869Sjfv 2160205869Sjfv /* Only older adapters use IO mapping */ 2161205869Sjfv if (adapter->hw.mac.type > e1000_82543) { 2162205869Sjfv /* Figure our where our IO BAR is ? */ 2163205869Sjfv for (rid = PCIR_BAR(0); rid < PCIR_CIS;) { 2164205869Sjfv val = pci_read_config(dev, rid, 4); 2165205869Sjfv if (EM_BAR_TYPE(val) == EM_BAR_TYPE_IO) { 2166205869Sjfv adapter->io_rid = rid; 2167205869Sjfv break; 2168205869Sjfv } 2169205869Sjfv rid += 4; 2170205869Sjfv /* check for 64bit BAR */ 2171205869Sjfv if (EM_BAR_MEM_TYPE(val) == EM_BAR_MEM_TYPE_64BIT) 2172205869Sjfv rid += 4; 2173205869Sjfv } 2174205869Sjfv if (rid >= PCIR_CIS) { 2175205869Sjfv device_printf(dev, "Unable to locate IO BAR\n"); 2176205869Sjfv return (ENXIO); 2177205869Sjfv } 2178205869Sjfv adapter->ioport = bus_alloc_resource_any(dev, 2179205869Sjfv SYS_RES_IOPORT, &adapter->io_rid, RF_ACTIVE); 2180205869Sjfv if (adapter->ioport == NULL) { 2181205869Sjfv device_printf(dev, "Unable to allocate bus resource: " 2182205869Sjfv "ioport\n"); 2183205869Sjfv return (ENXIO); 2184205869Sjfv } 2185205869Sjfv adapter->hw.io_base = 0; 2186205869Sjfv adapter->osdep.io_bus_space_tag = 2187205869Sjfv rman_get_bustag(adapter->ioport); 2188205869Sjfv adapter->osdep.io_bus_space_handle = 2189205869Sjfv rman_get_bushandle(adapter->ioport); 2190205869Sjfv } 2191205869Sjfv 2192205869Sjfv adapter->hw.back = &adapter->osdep; 2193205869Sjfv 2194205869Sjfv return (error); 2195205869Sjfv} 2196205869Sjfv 2197205869Sjfv/********************************************************************* 2198205869Sjfv * 2199205869Sjfv * Setup the Legacy or MSI Interrupt handler 2200205869Sjfv * 2201205869Sjfv **********************************************************************/ 2202205869Sjfvint 2203205869Sjfvlem_allocate_irq(struct adapter *adapter) 2204205869Sjfv{ 2205205869Sjfv device_t dev = adapter->dev; 2206205869Sjfv int error, rid = 0; 2207205869Sjfv 2208205869Sjfv /* Manually turn off all interrupts */ 2209205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff); 2210205869Sjfv 2211205869Sjfv /* We allocate a single interrupt resource */ 2212205869Sjfv adapter->res[0] = bus_alloc_resource_any(dev, 2213205869Sjfv SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); 2214205869Sjfv if (adapter->res[0] == NULL) { 2215205869Sjfv device_printf(dev, "Unable to allocate bus resource: " 2216205869Sjfv "interrupt\n"); 2217205869Sjfv return (ENXIO); 2218205869Sjfv } 2219205869Sjfv 2220238953Sjfv /* Do Legacy setup? */ 2221238953Sjfv if (lem_use_legacy_irq) { 2222238953Sjfv if ((error = bus_setup_intr(dev, adapter->res[0], 2223238953Sjfv INTR_TYPE_NET | INTR_MPSAFE, NULL, lem_intr, adapter, 2224238953Sjfv &adapter->tag[0])) != 0) { 2225238953Sjfv device_printf(dev, 2226238953Sjfv "Failed to register interrupt handler"); 2227238953Sjfv return (error); 2228238953Sjfv } 2229238953Sjfv return (0); 2230205869Sjfv } 2231205869Sjfv 2232205869Sjfv /* 2233238953Sjfv * Use a Fast interrupt and the associated 2234238953Sjfv * deferred processing contexts. 2235205869Sjfv */ 2236205869Sjfv TASK_INIT(&adapter->rxtx_task, 0, lem_handle_rxtx, adapter); 2237205869Sjfv TASK_INIT(&adapter->link_task, 0, lem_handle_link, adapter); 2238205869Sjfv adapter->tq = taskqueue_create_fast("lem_taskq", M_NOWAIT, 2239205869Sjfv taskqueue_thread_enqueue, &adapter->tq); 2240205869Sjfv taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq", 2241205869Sjfv device_get_nameunit(adapter->dev)); 2242205869Sjfv if ((error = bus_setup_intr(dev, adapter->res[0], 2243205869Sjfv INTR_TYPE_NET, lem_irq_fast, NULL, adapter, 2244205869Sjfv &adapter->tag[0])) != 0) { 2245205869Sjfv device_printf(dev, "Failed to register fast interrupt " 2246205869Sjfv "handler: %d\n", error); 2247205869Sjfv taskqueue_free(adapter->tq); 2248205869Sjfv adapter->tq = NULL; 2249205869Sjfv return (error); 2250205869Sjfv } 2251205869Sjfv 2252205869Sjfv return (0); 2253205869Sjfv} 2254205869Sjfv 2255205869Sjfv 2256205869Sjfvstatic void 2257205869Sjfvlem_free_pci_resources(struct adapter *adapter) 2258205869Sjfv{ 2259205869Sjfv device_t dev = adapter->dev; 2260205869Sjfv 2261205869Sjfv 2262205869Sjfv if (adapter->tag[0] != NULL) { 2263205869Sjfv bus_teardown_intr(dev, adapter->res[0], 2264205869Sjfv adapter->tag[0]); 2265205869Sjfv adapter->tag[0] = NULL; 2266205869Sjfv } 2267205869Sjfv 2268205869Sjfv if (adapter->res[0] != NULL) { 2269205869Sjfv bus_release_resource(dev, SYS_RES_IRQ, 2270205869Sjfv 0, adapter->res[0]); 2271205869Sjfv } 2272205869Sjfv 2273205869Sjfv if (adapter->memory != NULL) 2274205869Sjfv bus_release_resource(dev, SYS_RES_MEMORY, 2275205869Sjfv PCIR_BAR(0), adapter->memory); 2276205869Sjfv 2277205869Sjfv if (adapter->ioport != NULL) 2278205869Sjfv bus_release_resource(dev, SYS_RES_IOPORT, 2279205869Sjfv adapter->io_rid, adapter->ioport); 2280205869Sjfv} 2281205869Sjfv 2282205869Sjfv 2283205869Sjfv/********************************************************************* 2284205869Sjfv * 2285205869Sjfv * Initialize the hardware to a configuration 2286205869Sjfv * as specified by the adapter structure. 2287205869Sjfv * 2288205869Sjfv **********************************************************************/ 2289205869Sjfvstatic int 2290205869Sjfvlem_hardware_init(struct adapter *adapter) 2291205869Sjfv{ 2292205869Sjfv device_t dev = adapter->dev; 2293205869Sjfv u16 rx_buffer_size; 2294205869Sjfv 2295205869Sjfv INIT_DEBUGOUT("lem_hardware_init: begin"); 2296205869Sjfv 2297205869Sjfv /* Issue a global reset */ 2298205869Sjfv e1000_reset_hw(&adapter->hw); 2299205869Sjfv 2300205869Sjfv /* When hardware is reset, fifo_head is also reset */ 2301205869Sjfv adapter->tx_fifo_head = 0; 2302205869Sjfv 2303205869Sjfv /* 2304205869Sjfv * These parameters control the automatic generation (Tx) and 2305205869Sjfv * response (Rx) to Ethernet PAUSE frames. 2306205869Sjfv * - High water mark should allow for at least two frames to be 2307205869Sjfv * received after sending an XOFF. 2308205869Sjfv * - Low water mark works best when it is very near the high water mark. 2309205869Sjfv * This allows the receiver to restart by sending XON when it has 2310205869Sjfv * drained a bit. Here we use an arbitary value of 1500 which will 2311205869Sjfv * restart after one full frame is pulled from the buffer. There 2312205869Sjfv * could be several smaller frames in the buffer and if so they will 2313205869Sjfv * not trigger the XON until their total number reduces the buffer 2314205869Sjfv * by 1500. 2315205869Sjfv * - The pause time is fairly large at 1000 x 512ns = 512 usec. 2316205869Sjfv */ 2317205869Sjfv rx_buffer_size = ((E1000_READ_REG(&adapter->hw, E1000_PBA) & 2318205869Sjfv 0xffff) << 10 ); 2319205869Sjfv 2320205869Sjfv adapter->hw.fc.high_water = rx_buffer_size - 2321205869Sjfv roundup2(adapter->max_frame_size, 1024); 2322205869Sjfv adapter->hw.fc.low_water = adapter->hw.fc.high_water - 1500; 2323205869Sjfv 2324205869Sjfv adapter->hw.fc.pause_time = EM_FC_PAUSE_TIME; 2325205869Sjfv adapter->hw.fc.send_xon = TRUE; 2326205869Sjfv 2327205869Sjfv /* Set Flow control, use the tunable location if sane */ 2328214646Sjfv if ((lem_fc_setting >= 0) && (lem_fc_setting < 4)) 2329205869Sjfv adapter->hw.fc.requested_mode = lem_fc_setting; 2330205869Sjfv else 2331205869Sjfv adapter->hw.fc.requested_mode = e1000_fc_none; 2332205869Sjfv 2333205869Sjfv if (e1000_init_hw(&adapter->hw) < 0) { 2334205869Sjfv device_printf(dev, "Hardware Initialization Failed\n"); 2335205869Sjfv return (EIO); 2336205869Sjfv } 2337205869Sjfv 2338205869Sjfv e1000_check_for_link(&adapter->hw); 2339205869Sjfv 2340205869Sjfv return (0); 2341205869Sjfv} 2342205869Sjfv 2343205869Sjfv/********************************************************************* 2344205869Sjfv * 2345205869Sjfv * Setup networking device structure and register an interface. 2346205869Sjfv * 2347205869Sjfv **********************************************************************/ 2348211907Syongaristatic int 2349205869Sjfvlem_setup_interface(device_t dev, struct adapter *adapter) 2350205869Sjfv{ 2351205869Sjfv struct ifnet *ifp; 2352205869Sjfv 2353205869Sjfv INIT_DEBUGOUT("lem_setup_interface: begin"); 2354205869Sjfv 2355205869Sjfv ifp = adapter->ifp = if_alloc(IFT_ETHER); 2356211907Syongari if (ifp == NULL) { 2357211907Syongari device_printf(dev, "can not allocate ifnet structure\n"); 2358211907Syongari return (-1); 2359211907Syongari } 2360205869Sjfv if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 2361205869Sjfv ifp->if_init = lem_init; 2362205869Sjfv ifp->if_softc = adapter; 2363205869Sjfv ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 2364205869Sjfv ifp->if_ioctl = lem_ioctl; 2365205869Sjfv ifp->if_start = lem_start; 2366205869Sjfv IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1); 2367205869Sjfv ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1; 2368205869Sjfv IFQ_SET_READY(&ifp->if_snd); 2369205869Sjfv 2370205869Sjfv ether_ifattach(ifp, adapter->hw.mac.addr); 2371205869Sjfv 2372205869Sjfv ifp->if_capabilities = ifp->if_capenable = 0; 2373205869Sjfv 2374205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 2375214646Sjfv ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; 2376214646Sjfv ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; 2377205869Sjfv } 2378205869Sjfv 2379205869Sjfv /* 2380205869Sjfv * Tell the upper layer(s) we support long frames. 2381205869Sjfv */ 2382205869Sjfv ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 2383205869Sjfv ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 2384205869Sjfv ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 2385205869Sjfv 2386214646Sjfv /* 2387214646Sjfv ** Dont turn this on by default, if vlans are 2388214646Sjfv ** created on another pseudo device (eg. lagg) 2389214646Sjfv ** then vlan events are not passed thru, breaking 2390214646Sjfv ** operation, but with HW FILTER off it works. If 2391214646Sjfv ** using vlans directly on the em driver you can 2392214646Sjfv ** enable this and get full hardware tag filtering. 2393214646Sjfv */ 2394214646Sjfv ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; 2395214646Sjfv 2396205869Sjfv#ifdef DEVICE_POLLING 2397205869Sjfv ifp->if_capabilities |= IFCAP_POLLING; 2398205869Sjfv#endif 2399205869Sjfv 2400208103Sjfv /* Enable only WOL MAGIC by default */ 2401205869Sjfv if (adapter->wol) { 2402205869Sjfv ifp->if_capabilities |= IFCAP_WOL; 2403208103Sjfv ifp->if_capenable |= IFCAP_WOL_MAGIC; 2404205869Sjfv } 2405205869Sjfv 2406205869Sjfv /* 2407205869Sjfv * Specify the media types supported by this adapter and register 2408205869Sjfv * callbacks to update media and link information 2409205869Sjfv */ 2410205869Sjfv ifmedia_init(&adapter->media, IFM_IMASK, 2411205869Sjfv lem_media_change, lem_media_status); 2412205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 2413205869Sjfv (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) { 2414205869Sjfv u_char fiber_type = IFM_1000_SX; /* default type */ 2415205869Sjfv 2416205869Sjfv if (adapter->hw.mac.type == e1000_82545) 2417205869Sjfv fiber_type = IFM_1000_LX; 2418205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | fiber_type | IFM_FDX, 2419205869Sjfv 0, NULL); 2420205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | fiber_type, 0, NULL); 2421205869Sjfv } else { 2422205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL); 2423205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX, 2424205869Sjfv 0, NULL); 2425205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, 2426205869Sjfv 0, NULL); 2427205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 2428205869Sjfv 0, NULL); 2429205869Sjfv if (adapter->hw.phy.type != e1000_phy_ife) { 2430205869Sjfv ifmedia_add(&adapter->media, 2431205869Sjfv IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); 2432205869Sjfv ifmedia_add(&adapter->media, 2433205869Sjfv IFM_ETHER | IFM_1000_T, 0, NULL); 2434205869Sjfv } 2435205869Sjfv } 2436205869Sjfv ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); 2437205869Sjfv ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); 2438211907Syongari return (0); 2439205869Sjfv} 2440205869Sjfv 2441205869Sjfv 2442205869Sjfv/********************************************************************* 2443205869Sjfv * 2444205869Sjfv * Workaround for SmartSpeed on 82541 and 82547 controllers 2445205869Sjfv * 2446205869Sjfv **********************************************************************/ 2447205869Sjfvstatic void 2448205869Sjfvlem_smartspeed(struct adapter *adapter) 2449205869Sjfv{ 2450205869Sjfv u16 phy_tmp; 2451205869Sjfv 2452205869Sjfv if (adapter->link_active || (adapter->hw.phy.type != e1000_phy_igp) || 2453205869Sjfv adapter->hw.mac.autoneg == 0 || 2454205869Sjfv (adapter->hw.phy.autoneg_advertised & ADVERTISE_1000_FULL) == 0) 2455205869Sjfv return; 2456205869Sjfv 2457205869Sjfv if (adapter->smartspeed == 0) { 2458205869Sjfv /* If Master/Slave config fault is asserted twice, 2459205869Sjfv * we assume back-to-back */ 2460205869Sjfv e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp); 2461205869Sjfv if (!(phy_tmp & SR_1000T_MS_CONFIG_FAULT)) 2462205869Sjfv return; 2463205869Sjfv e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp); 2464205869Sjfv if (phy_tmp & SR_1000T_MS_CONFIG_FAULT) { 2465205869Sjfv e1000_read_phy_reg(&adapter->hw, 2466205869Sjfv PHY_1000T_CTRL, &phy_tmp); 2467205869Sjfv if(phy_tmp & CR_1000T_MS_ENABLE) { 2468205869Sjfv phy_tmp &= ~CR_1000T_MS_ENABLE; 2469205869Sjfv e1000_write_phy_reg(&adapter->hw, 2470205869Sjfv PHY_1000T_CTRL, phy_tmp); 2471205869Sjfv adapter->smartspeed++; 2472205869Sjfv if(adapter->hw.mac.autoneg && 2473205869Sjfv !e1000_copper_link_autoneg(&adapter->hw) && 2474205869Sjfv !e1000_read_phy_reg(&adapter->hw, 2475205869Sjfv PHY_CONTROL, &phy_tmp)) { 2476205869Sjfv phy_tmp |= (MII_CR_AUTO_NEG_EN | 2477205869Sjfv MII_CR_RESTART_AUTO_NEG); 2478205869Sjfv e1000_write_phy_reg(&adapter->hw, 2479205869Sjfv PHY_CONTROL, phy_tmp); 2480205869Sjfv } 2481205869Sjfv } 2482205869Sjfv } 2483205869Sjfv return; 2484205869Sjfv } else if(adapter->smartspeed == EM_SMARTSPEED_DOWNSHIFT) { 2485205869Sjfv /* If still no link, perhaps using 2/3 pair cable */ 2486205869Sjfv e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_tmp); 2487205869Sjfv phy_tmp |= CR_1000T_MS_ENABLE; 2488205869Sjfv e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_tmp); 2489205869Sjfv if(adapter->hw.mac.autoneg && 2490205869Sjfv !e1000_copper_link_autoneg(&adapter->hw) && 2491205869Sjfv !e1000_read_phy_reg(&adapter->hw, PHY_CONTROL, &phy_tmp)) { 2492205869Sjfv phy_tmp |= (MII_CR_AUTO_NEG_EN | 2493205869Sjfv MII_CR_RESTART_AUTO_NEG); 2494205869Sjfv e1000_write_phy_reg(&adapter->hw, PHY_CONTROL, phy_tmp); 2495205869Sjfv } 2496205869Sjfv } 2497205869Sjfv /* Restart process after EM_SMARTSPEED_MAX iterations */ 2498205869Sjfv if(adapter->smartspeed++ == EM_SMARTSPEED_MAX) 2499205869Sjfv adapter->smartspeed = 0; 2500205869Sjfv} 2501205869Sjfv 2502205869Sjfv 2503205869Sjfv/* 2504205869Sjfv * Manage DMA'able memory. 2505205869Sjfv */ 2506205869Sjfvstatic void 2507205869Sjfvlem_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2508205869Sjfv{ 2509205869Sjfv if (error) 2510205869Sjfv return; 2511205869Sjfv *(bus_addr_t *) arg = segs[0].ds_addr; 2512205869Sjfv} 2513205869Sjfv 2514205869Sjfvstatic int 2515205869Sjfvlem_dma_malloc(struct adapter *adapter, bus_size_t size, 2516205869Sjfv struct em_dma_alloc *dma, int mapflags) 2517205869Sjfv{ 2518205869Sjfv int error; 2519205869Sjfv 2520205869Sjfv error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */ 2521205869Sjfv EM_DBA_ALIGN, 0, /* alignment, bounds */ 2522205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 2523205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 2524205869Sjfv NULL, NULL, /* filter, filterarg */ 2525205869Sjfv size, /* maxsize */ 2526205869Sjfv 1, /* nsegments */ 2527205869Sjfv size, /* maxsegsize */ 2528205869Sjfv 0, /* flags */ 2529205869Sjfv NULL, /* lockfunc */ 2530205869Sjfv NULL, /* lockarg */ 2531205869Sjfv &dma->dma_tag); 2532205869Sjfv if (error) { 2533205869Sjfv device_printf(adapter->dev, 2534205869Sjfv "%s: bus_dma_tag_create failed: %d\n", 2535205869Sjfv __func__, error); 2536205869Sjfv goto fail_0; 2537205869Sjfv } 2538205869Sjfv 2539205869Sjfv error = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr, 2540205869Sjfv BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map); 2541205869Sjfv if (error) { 2542205869Sjfv device_printf(adapter->dev, 2543205869Sjfv "%s: bus_dmamem_alloc(%ju) failed: %d\n", 2544205869Sjfv __func__, (uintmax_t)size, error); 2545205869Sjfv goto fail_2; 2546205869Sjfv } 2547205869Sjfv 2548205869Sjfv dma->dma_paddr = 0; 2549205869Sjfv error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, 2550205869Sjfv size, lem_dmamap_cb, &dma->dma_paddr, mapflags | BUS_DMA_NOWAIT); 2551205869Sjfv if (error || dma->dma_paddr == 0) { 2552205869Sjfv device_printf(adapter->dev, 2553205869Sjfv "%s: bus_dmamap_load failed: %d\n", 2554205869Sjfv __func__, error); 2555205869Sjfv goto fail_3; 2556205869Sjfv } 2557205869Sjfv 2558205869Sjfv return (0); 2559205869Sjfv 2560205869Sjfvfail_3: 2561205869Sjfv bus_dmamap_unload(dma->dma_tag, dma->dma_map); 2562205869Sjfvfail_2: 2563205869Sjfv bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 2564205869Sjfv bus_dma_tag_destroy(dma->dma_tag); 2565205869Sjfvfail_0: 2566205869Sjfv dma->dma_map = NULL; 2567205869Sjfv dma->dma_tag = NULL; 2568205869Sjfv 2569205869Sjfv return (error); 2570205869Sjfv} 2571205869Sjfv 2572205869Sjfvstatic void 2573205869Sjfvlem_dma_free(struct adapter *adapter, struct em_dma_alloc *dma) 2574205869Sjfv{ 2575205869Sjfv if (dma->dma_tag == NULL) 2576205869Sjfv return; 2577205869Sjfv if (dma->dma_map != NULL) { 2578205869Sjfv bus_dmamap_sync(dma->dma_tag, dma->dma_map, 2579205869Sjfv BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2580205869Sjfv bus_dmamap_unload(dma->dma_tag, dma->dma_map); 2581205869Sjfv bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 2582205869Sjfv dma->dma_map = NULL; 2583205869Sjfv } 2584205869Sjfv bus_dma_tag_destroy(dma->dma_tag); 2585205869Sjfv dma->dma_tag = NULL; 2586205869Sjfv} 2587205869Sjfv 2588205869Sjfv 2589205869Sjfv/********************************************************************* 2590205869Sjfv * 2591205869Sjfv * Allocate memory for tx_buffer structures. The tx_buffer stores all 2592205869Sjfv * the information needed to transmit a packet on the wire. 2593205869Sjfv * 2594205869Sjfv **********************************************************************/ 2595205869Sjfvstatic int 2596205869Sjfvlem_allocate_transmit_structures(struct adapter *adapter) 2597205869Sjfv{ 2598205869Sjfv device_t dev = adapter->dev; 2599205869Sjfv struct em_buffer *tx_buffer; 2600205869Sjfv int error; 2601205869Sjfv 2602205869Sjfv /* 2603205869Sjfv * Create DMA tags for tx descriptors 2604205869Sjfv */ 2605205869Sjfv if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 2606205869Sjfv 1, 0, /* alignment, bounds */ 2607205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 2608205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 2609205869Sjfv NULL, NULL, /* filter, filterarg */ 2610214646Sjfv MCLBYTES * EM_MAX_SCATTER, /* maxsize */ 2611205869Sjfv EM_MAX_SCATTER, /* nsegments */ 2612214646Sjfv MCLBYTES, /* maxsegsize */ 2613205869Sjfv 0, /* flags */ 2614214646Sjfv NULL, /* lockfunc */ 2615214646Sjfv NULL, /* lockarg */ 2616205869Sjfv &adapter->txtag)) != 0) { 2617205869Sjfv device_printf(dev, "Unable to allocate TX DMA tag\n"); 2618205869Sjfv goto fail; 2619205869Sjfv } 2620205869Sjfv 2621205869Sjfv adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) * 2622205869Sjfv adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); 2623205869Sjfv if (adapter->tx_buffer_area == NULL) { 2624205869Sjfv device_printf(dev, "Unable to allocate tx_buffer memory\n"); 2625205869Sjfv error = ENOMEM; 2626205869Sjfv goto fail; 2627205869Sjfv } 2628205869Sjfv 2629205869Sjfv /* Create the descriptor buffer dma maps */ 2630205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++) { 2631205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2632205869Sjfv error = bus_dmamap_create(adapter->txtag, 0, &tx_buffer->map); 2633205869Sjfv if (error != 0) { 2634205869Sjfv device_printf(dev, "Unable to create TX DMA map\n"); 2635205869Sjfv goto fail; 2636205869Sjfv } 2637205869Sjfv tx_buffer->next_eop = -1; 2638205869Sjfv } 2639205869Sjfv 2640205869Sjfv return (0); 2641205869Sjfvfail: 2642205869Sjfv lem_free_transmit_structures(adapter); 2643205869Sjfv return (error); 2644205869Sjfv} 2645205869Sjfv 2646205869Sjfv/********************************************************************* 2647205869Sjfv * 2648205869Sjfv * (Re)Initialize transmit structures. 2649205869Sjfv * 2650205869Sjfv **********************************************************************/ 2651205869Sjfvstatic void 2652205869Sjfvlem_setup_transmit_structures(struct adapter *adapter) 2653205869Sjfv{ 2654205869Sjfv struct em_buffer *tx_buffer; 2655228281Sluigi#ifdef DEV_NETMAP 2656228281Sluigi /* we are already locked */ 2657228281Sluigi struct netmap_adapter *na = NA(adapter->ifp); 2658228281Sluigi struct netmap_slot *slot = netmap_reset(na, NR_TX, 0, 0); 2659228281Sluigi#endif /* DEV_NETMAP */ 2660205869Sjfv 2661205869Sjfv /* Clear the old ring contents */ 2662205869Sjfv bzero(adapter->tx_desc_base, 2663205869Sjfv (sizeof(struct e1000_tx_desc)) * adapter->num_tx_desc); 2664205869Sjfv 2665205869Sjfv /* Free any existing TX buffers */ 2666205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) { 2667205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2668205869Sjfv bus_dmamap_sync(adapter->txtag, tx_buffer->map, 2669205869Sjfv BUS_DMASYNC_POSTWRITE); 2670205869Sjfv bus_dmamap_unload(adapter->txtag, tx_buffer->map); 2671205869Sjfv m_freem(tx_buffer->m_head); 2672205869Sjfv tx_buffer->m_head = NULL; 2673228281Sluigi#ifdef DEV_NETMAP 2674228281Sluigi if (slot) { 2675231796Sluigi /* the i-th NIC entry goes to slot si */ 2676232238Sluigi int si = netmap_idx_n2k(&na->tx_rings[0], i); 2677229939Sluigi uint64_t paddr; 2678228281Sluigi void *addr; 2679228281Sluigi 2680229939Sluigi addr = PNMB(slot + si, &paddr); 2681229939Sluigi adapter->tx_desc_base[si].buffer_addr = htole64(paddr); 2682228281Sluigi /* reload the map for netmap mode */ 2683229939Sluigi netmap_load_map(adapter->txtag, tx_buffer->map, addr); 2684228281Sluigi } 2685228281Sluigi#endif /* DEV_NETMAP */ 2686205869Sjfv tx_buffer->next_eop = -1; 2687205869Sjfv } 2688205869Sjfv 2689205869Sjfv /* Reset state */ 2690225640Srstone adapter->last_hw_offload = 0; 2691205869Sjfv adapter->next_avail_tx_desc = 0; 2692205869Sjfv adapter->next_tx_to_clean = 0; 2693205869Sjfv adapter->num_tx_desc_avail = adapter->num_tx_desc; 2694205869Sjfv 2695205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 2696205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2697205869Sjfv 2698205869Sjfv return; 2699205869Sjfv} 2700205869Sjfv 2701205869Sjfv/********************************************************************* 2702205869Sjfv * 2703205869Sjfv * Enable transmit unit. 2704205869Sjfv * 2705205869Sjfv **********************************************************************/ 2706205869Sjfvstatic void 2707205869Sjfvlem_initialize_transmit_unit(struct adapter *adapter) 2708205869Sjfv{ 2709205869Sjfv u32 tctl, tipg = 0; 2710205869Sjfv u64 bus_addr; 2711205869Sjfv 2712205869Sjfv INIT_DEBUGOUT("lem_initialize_transmit_unit: begin"); 2713205869Sjfv /* Setup the Base and Length of the Tx Descriptor Ring */ 2714205869Sjfv bus_addr = adapter->txdma.dma_paddr; 2715205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDLEN(0), 2716205869Sjfv adapter->num_tx_desc * sizeof(struct e1000_tx_desc)); 2717205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDBAH(0), 2718205869Sjfv (u32)(bus_addr >> 32)); 2719205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDBAL(0), 2720205869Sjfv (u32)bus_addr); 2721205869Sjfv /* Setup the HW Tx Head and Tail descriptor pointers */ 2722205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0); 2723205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TDH(0), 0); 2724205869Sjfv 2725205869Sjfv HW_DEBUGOUT2("Base = %x, Length = %x\n", 2726205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDBAL(0)), 2727205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TDLEN(0))); 2728205869Sjfv 2729205869Sjfv /* Set the default values for the Tx Inter Packet Gap timer */ 2730205869Sjfv switch (adapter->hw.mac.type) { 2731205869Sjfv case e1000_82542: 2732205869Sjfv tipg = DEFAULT_82542_TIPG_IPGT; 2733205869Sjfv tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 2734205869Sjfv tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 2735205869Sjfv break; 2736205869Sjfv default: 2737205869Sjfv if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || 2738205869Sjfv (adapter->hw.phy.media_type == 2739205869Sjfv e1000_media_type_internal_serdes)) 2740205869Sjfv tipg = DEFAULT_82543_TIPG_IPGT_FIBER; 2741205869Sjfv else 2742205869Sjfv tipg = DEFAULT_82543_TIPG_IPGT_COPPER; 2743205869Sjfv tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 2744205869Sjfv tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 2745205869Sjfv } 2746205869Sjfv 2747205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TIPG, tipg); 2748205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TIDV, adapter->tx_int_delay.value); 2749205869Sjfv if(adapter->hw.mac.type >= e1000_82540) 2750205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TADV, 2751205869Sjfv adapter->tx_abs_int_delay.value); 2752205869Sjfv 2753205869Sjfv /* Program the Transmit Control Register */ 2754205869Sjfv tctl = E1000_READ_REG(&adapter->hw, E1000_TCTL); 2755205869Sjfv tctl &= ~E1000_TCTL_CT; 2756205869Sjfv tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN | 2757205869Sjfv (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); 2758205869Sjfv 2759205869Sjfv /* This write will effectively turn on the transmit unit. */ 2760205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); 2761205869Sjfv 2762205869Sjfv /* Setup Transmit Descriptor Base Settings */ 2763205869Sjfv adapter->txd_cmd = E1000_TXD_CMD_IFCS; 2764205869Sjfv 2765205869Sjfv if (adapter->tx_int_delay.value > 0) 2766205869Sjfv adapter->txd_cmd |= E1000_TXD_CMD_IDE; 2767205869Sjfv} 2768205869Sjfv 2769205869Sjfv/********************************************************************* 2770205869Sjfv * 2771205869Sjfv * Free all transmit related data structures. 2772205869Sjfv * 2773205869Sjfv **********************************************************************/ 2774205869Sjfvstatic void 2775205869Sjfvlem_free_transmit_structures(struct adapter *adapter) 2776205869Sjfv{ 2777205869Sjfv struct em_buffer *tx_buffer; 2778205869Sjfv 2779205869Sjfv INIT_DEBUGOUT("free_transmit_structures: begin"); 2780205869Sjfv 2781205869Sjfv if (adapter->tx_buffer_area != NULL) { 2782205869Sjfv for (int i = 0; i < adapter->num_tx_desc; i++) { 2783205869Sjfv tx_buffer = &adapter->tx_buffer_area[i]; 2784205869Sjfv if (tx_buffer->m_head != NULL) { 2785205869Sjfv bus_dmamap_sync(adapter->txtag, tx_buffer->map, 2786205869Sjfv BUS_DMASYNC_POSTWRITE); 2787205869Sjfv bus_dmamap_unload(adapter->txtag, 2788205869Sjfv tx_buffer->map); 2789205869Sjfv m_freem(tx_buffer->m_head); 2790205869Sjfv tx_buffer->m_head = NULL; 2791205869Sjfv } else if (tx_buffer->map != NULL) 2792205869Sjfv bus_dmamap_unload(adapter->txtag, 2793205869Sjfv tx_buffer->map); 2794205869Sjfv if (tx_buffer->map != NULL) { 2795205869Sjfv bus_dmamap_destroy(adapter->txtag, 2796205869Sjfv tx_buffer->map); 2797205869Sjfv tx_buffer->map = NULL; 2798205869Sjfv } 2799205869Sjfv } 2800205869Sjfv } 2801205869Sjfv if (adapter->tx_buffer_area != NULL) { 2802205869Sjfv free(adapter->tx_buffer_area, M_DEVBUF); 2803205869Sjfv adapter->tx_buffer_area = NULL; 2804205869Sjfv } 2805205869Sjfv if (adapter->txtag != NULL) { 2806205869Sjfv bus_dma_tag_destroy(adapter->txtag); 2807205869Sjfv adapter->txtag = NULL; 2808205869Sjfv } 2809205869Sjfv#if __FreeBSD_version >= 800000 2810205869Sjfv if (adapter->br != NULL) 2811205869Sjfv buf_ring_free(adapter->br, M_DEVBUF); 2812205869Sjfv#endif 2813205869Sjfv} 2814205869Sjfv 2815205869Sjfv/********************************************************************* 2816205869Sjfv * 2817205869Sjfv * The offload context needs to be set when we transfer the first 2818205869Sjfv * packet of a particular protocol (TCP/UDP). This routine has been 2819205869Sjfv * enhanced to deal with inserted VLAN headers, and IPV6 (not complete) 2820205869Sjfv * 2821205869Sjfv * Added back the old method of keeping the current context type 2822205869Sjfv * and not setting if unnecessary, as this is reported to be a 2823205869Sjfv * big performance win. -jfv 2824205869Sjfv **********************************************************************/ 2825205869Sjfvstatic void 2826205869Sjfvlem_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp, 2827205869Sjfv u32 *txd_upper, u32 *txd_lower) 2828205869Sjfv{ 2829205869Sjfv struct e1000_context_desc *TXD = NULL; 2830205869Sjfv struct em_buffer *tx_buffer; 2831205869Sjfv struct ether_vlan_header *eh; 2832205869Sjfv struct ip *ip = NULL; 2833205869Sjfv struct ip6_hdr *ip6; 2834205869Sjfv int curr_txd, ehdrlen; 2835205869Sjfv u32 cmd, hdr_len, ip_hlen; 2836205869Sjfv u16 etype; 2837205869Sjfv u8 ipproto; 2838205869Sjfv 2839205869Sjfv 2840205869Sjfv cmd = hdr_len = ipproto = 0; 2841209959Sjfv *txd_upper = *txd_lower = 0; 2842205869Sjfv curr_txd = adapter->next_avail_tx_desc; 2843205869Sjfv 2844205869Sjfv /* 2845205869Sjfv * Determine where frame payload starts. 2846205869Sjfv * Jump over vlan headers if already present, 2847205869Sjfv * helpful for QinQ too. 2848205869Sjfv */ 2849205869Sjfv eh = mtod(mp, struct ether_vlan_header *); 2850205869Sjfv if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 2851205869Sjfv etype = ntohs(eh->evl_proto); 2852205869Sjfv ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 2853205869Sjfv } else { 2854205869Sjfv etype = ntohs(eh->evl_encap_proto); 2855205869Sjfv ehdrlen = ETHER_HDR_LEN; 2856205869Sjfv } 2857205869Sjfv 2858205869Sjfv /* 2859205869Sjfv * We only support TCP/UDP for IPv4 and IPv6 for the moment. 2860205869Sjfv * TODO: Support SCTP too when it hits the tree. 2861205869Sjfv */ 2862205869Sjfv switch (etype) { 2863205869Sjfv case ETHERTYPE_IP: 2864205869Sjfv ip = (struct ip *)(mp->m_data + ehdrlen); 2865205869Sjfv ip_hlen = ip->ip_hl << 2; 2866205869Sjfv 2867205869Sjfv /* Setup of IP header checksum. */ 2868205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_IP) { 2869205869Sjfv /* 2870205869Sjfv * Start offset for header checksum calculation. 2871205869Sjfv * End offset for header checksum calculation. 2872205869Sjfv * Offset of place to put the checksum. 2873205869Sjfv */ 2874205869Sjfv TXD = (struct e1000_context_desc *) 2875205869Sjfv &adapter->tx_desc_base[curr_txd]; 2876205869Sjfv TXD->lower_setup.ip_fields.ipcss = ehdrlen; 2877205869Sjfv TXD->lower_setup.ip_fields.ipcse = 2878205869Sjfv htole16(ehdrlen + ip_hlen); 2879205869Sjfv TXD->lower_setup.ip_fields.ipcso = 2880205869Sjfv ehdrlen + offsetof(struct ip, ip_sum); 2881205869Sjfv cmd |= E1000_TXD_CMD_IP; 2882205869Sjfv *txd_upper |= E1000_TXD_POPTS_IXSM << 8; 2883205869Sjfv } 2884205869Sjfv 2885205869Sjfv hdr_len = ehdrlen + ip_hlen; 2886205869Sjfv ipproto = ip->ip_p; 2887205869Sjfv 2888205869Sjfv break; 2889205869Sjfv case ETHERTYPE_IPV6: 2890205869Sjfv ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 2891205869Sjfv ip_hlen = sizeof(struct ip6_hdr); /* XXX: No header stacking. */ 2892205869Sjfv 2893205869Sjfv /* IPv6 doesn't have a header checksum. */ 2894205869Sjfv 2895205869Sjfv hdr_len = ehdrlen + ip_hlen; 2896205869Sjfv ipproto = ip6->ip6_nxt; 2897209959Sjfv break; 2898205869Sjfv 2899205869Sjfv default: 2900205869Sjfv return; 2901205869Sjfv } 2902205869Sjfv 2903205869Sjfv switch (ipproto) { 2904205869Sjfv case IPPROTO_TCP: 2905205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_TCP) { 2906205869Sjfv *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 2907205869Sjfv *txd_upper |= E1000_TXD_POPTS_TXSM << 8; 2908205869Sjfv /* no need for context if already set */ 2909205869Sjfv if (adapter->last_hw_offload == CSUM_TCP) 2910205869Sjfv return; 2911205869Sjfv adapter->last_hw_offload = CSUM_TCP; 2912205869Sjfv /* 2913205869Sjfv * Start offset for payload checksum calculation. 2914205869Sjfv * End offset for payload checksum calculation. 2915205869Sjfv * Offset of place to put the checksum. 2916205869Sjfv */ 2917205869Sjfv TXD = (struct e1000_context_desc *) 2918205869Sjfv &adapter->tx_desc_base[curr_txd]; 2919205869Sjfv TXD->upper_setup.tcp_fields.tucss = hdr_len; 2920205869Sjfv TXD->upper_setup.tcp_fields.tucse = htole16(0); 2921205869Sjfv TXD->upper_setup.tcp_fields.tucso = 2922205869Sjfv hdr_len + offsetof(struct tcphdr, th_sum); 2923205869Sjfv cmd |= E1000_TXD_CMD_TCP; 2924205869Sjfv } 2925205869Sjfv break; 2926205869Sjfv case IPPROTO_UDP: 2927205869Sjfv { 2928205869Sjfv if (mp->m_pkthdr.csum_flags & CSUM_UDP) { 2929205869Sjfv *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; 2930205869Sjfv *txd_upper |= E1000_TXD_POPTS_TXSM << 8; 2931205869Sjfv /* no need for context if already set */ 2932205869Sjfv if (adapter->last_hw_offload == CSUM_UDP) 2933205869Sjfv return; 2934205869Sjfv adapter->last_hw_offload = CSUM_UDP; 2935205869Sjfv /* 2936205869Sjfv * Start offset for header checksum calculation. 2937205869Sjfv * End offset for header checksum calculation. 2938205869Sjfv * Offset of place to put the checksum. 2939205869Sjfv */ 2940205869Sjfv TXD = (struct e1000_context_desc *) 2941205869Sjfv &adapter->tx_desc_base[curr_txd]; 2942205869Sjfv TXD->upper_setup.tcp_fields.tucss = hdr_len; 2943205869Sjfv TXD->upper_setup.tcp_fields.tucse = htole16(0); 2944205869Sjfv TXD->upper_setup.tcp_fields.tucso = 2945205869Sjfv hdr_len + offsetof(struct udphdr, uh_sum); 2946205869Sjfv } 2947205869Sjfv /* Fall Thru */ 2948205869Sjfv } 2949205869Sjfv default: 2950205869Sjfv break; 2951205869Sjfv } 2952205869Sjfv 2953209959Sjfv if (TXD == NULL) 2954209959Sjfv return; 2955205869Sjfv TXD->tcp_seg_setup.data = htole32(0); 2956205869Sjfv TXD->cmd_and_length = 2957205869Sjfv htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd); 2958205869Sjfv tx_buffer = &adapter->tx_buffer_area[curr_txd]; 2959205869Sjfv tx_buffer->m_head = NULL; 2960205869Sjfv tx_buffer->next_eop = -1; 2961205869Sjfv 2962205869Sjfv if (++curr_txd == adapter->num_tx_desc) 2963205869Sjfv curr_txd = 0; 2964205869Sjfv 2965205869Sjfv adapter->num_tx_desc_avail--; 2966205869Sjfv adapter->next_avail_tx_desc = curr_txd; 2967205869Sjfv} 2968205869Sjfv 2969205869Sjfv 2970205869Sjfv/********************************************************************** 2971205869Sjfv * 2972205869Sjfv * Examine each tx_buffer in the used queue. If the hardware is done 2973205869Sjfv * processing the packet then free associated resources. The 2974205869Sjfv * tx_buffer is put back on the free queue. 2975205869Sjfv * 2976205869Sjfv **********************************************************************/ 2977205869Sjfvstatic void 2978205869Sjfvlem_txeof(struct adapter *adapter) 2979205869Sjfv{ 2980205869Sjfv int first, last, done, num_avail; 2981205869Sjfv struct em_buffer *tx_buffer; 2982205869Sjfv struct e1000_tx_desc *tx_desc, *eop_desc; 2983205869Sjfv struct ifnet *ifp = adapter->ifp; 2984205869Sjfv 2985205869Sjfv EM_TX_LOCK_ASSERT(adapter); 2986205869Sjfv 2987228281Sluigi#ifdef DEV_NETMAP 2988250109Sluigi if (netmap_tx_irq(ifp, 0 | (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT))) 2989228281Sluigi return; 2990228281Sluigi#endif /* DEV_NETMAP */ 2991205869Sjfv if (adapter->num_tx_desc_avail == adapter->num_tx_desc) 2992205869Sjfv return; 2993205869Sjfv 2994205869Sjfv num_avail = adapter->num_tx_desc_avail; 2995205869Sjfv first = adapter->next_tx_to_clean; 2996205869Sjfv tx_desc = &adapter->tx_desc_base[first]; 2997205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 2998205869Sjfv last = tx_buffer->next_eop; 2999205869Sjfv eop_desc = &adapter->tx_desc_base[last]; 3000205869Sjfv 3001205869Sjfv /* 3002205869Sjfv * What this does is get the index of the 3003205869Sjfv * first descriptor AFTER the EOP of the 3004205869Sjfv * first packet, that way we can do the 3005205869Sjfv * simple comparison on the inner while loop. 3006205869Sjfv */ 3007205869Sjfv if (++last == adapter->num_tx_desc) 3008205869Sjfv last = 0; 3009205869Sjfv done = last; 3010205869Sjfv 3011205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 3012205869Sjfv BUS_DMASYNC_POSTREAD); 3013205869Sjfv 3014205869Sjfv while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) { 3015205869Sjfv /* We clean the range of the packet */ 3016205869Sjfv while (first != done) { 3017205869Sjfv tx_desc->upper.data = 0; 3018205869Sjfv tx_desc->lower.data = 0; 3019205869Sjfv tx_desc->buffer_addr = 0; 3020205869Sjfv ++num_avail; 3021205869Sjfv 3022205869Sjfv if (tx_buffer->m_head) { 3023205869Sjfv ifp->if_opackets++; 3024205869Sjfv bus_dmamap_sync(adapter->txtag, 3025205869Sjfv tx_buffer->map, 3026205869Sjfv BUS_DMASYNC_POSTWRITE); 3027205869Sjfv bus_dmamap_unload(adapter->txtag, 3028205869Sjfv tx_buffer->map); 3029205869Sjfv 3030205869Sjfv m_freem(tx_buffer->m_head); 3031205869Sjfv tx_buffer->m_head = NULL; 3032205869Sjfv } 3033205869Sjfv tx_buffer->next_eop = -1; 3034205869Sjfv adapter->watchdog_time = ticks; 3035205869Sjfv 3036205869Sjfv if (++first == adapter->num_tx_desc) 3037205869Sjfv first = 0; 3038205869Sjfv 3039205869Sjfv tx_buffer = &adapter->tx_buffer_area[first]; 3040205869Sjfv tx_desc = &adapter->tx_desc_base[first]; 3041205869Sjfv } 3042205869Sjfv /* See if we can continue to the next packet */ 3043205869Sjfv last = tx_buffer->next_eop; 3044205869Sjfv if (last != -1) { 3045205869Sjfv eop_desc = &adapter->tx_desc_base[last]; 3046205869Sjfv /* Get new done point */ 3047205869Sjfv if (++last == adapter->num_tx_desc) last = 0; 3048205869Sjfv done = last; 3049205869Sjfv } else 3050205869Sjfv break; 3051205869Sjfv } 3052205869Sjfv bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, 3053205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3054205869Sjfv 3055205869Sjfv adapter->next_tx_to_clean = first; 3056214646Sjfv adapter->num_tx_desc_avail = num_avail; 3057205869Sjfv 3058205869Sjfv /* 3059205869Sjfv * If we have enough room, clear IFF_DRV_OACTIVE to 3060205869Sjfv * tell the stack that it is OK to send packets. 3061205869Sjfv * If there are no pending descriptors, clear the watchdog. 3062205869Sjfv */ 3063214646Sjfv if (adapter->num_tx_desc_avail > EM_TX_CLEANUP_THRESHOLD) { 3064205869Sjfv ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 3065214646Sjfv if (adapter->num_tx_desc_avail == adapter->num_tx_desc) { 3066205869Sjfv adapter->watchdog_check = FALSE; 3067205869Sjfv return; 3068205869Sjfv } 3069205869Sjfv } 3070205869Sjfv} 3071205869Sjfv 3072205869Sjfv/********************************************************************* 3073205869Sjfv * 3074205869Sjfv * When Link is lost sometimes there is work still in the TX ring 3075205869Sjfv * which may result in a watchdog, rather than allow that we do an 3076205869Sjfv * attempted cleanup and then reinit here. Note that this has been 3077205869Sjfv * seens mostly with fiber adapters. 3078205869Sjfv * 3079205869Sjfv **********************************************************************/ 3080205869Sjfvstatic void 3081205869Sjfvlem_tx_purge(struct adapter *adapter) 3082205869Sjfv{ 3083205869Sjfv if ((!adapter->link_active) && (adapter->watchdog_check)) { 3084205869Sjfv EM_TX_LOCK(adapter); 3085205869Sjfv lem_txeof(adapter); 3086205869Sjfv EM_TX_UNLOCK(adapter); 3087205869Sjfv if (adapter->watchdog_check) /* Still outstanding? */ 3088205869Sjfv lem_init_locked(adapter); 3089205869Sjfv } 3090205869Sjfv} 3091205869Sjfv 3092205869Sjfv/********************************************************************* 3093205869Sjfv * 3094205869Sjfv * Get a buffer from system mbuf buffer pool. 3095205869Sjfv * 3096205869Sjfv **********************************************************************/ 3097205869Sjfvstatic int 3098205869Sjfvlem_get_buf(struct adapter *adapter, int i) 3099205869Sjfv{ 3100205869Sjfv struct mbuf *m; 3101205869Sjfv bus_dma_segment_t segs[1]; 3102205869Sjfv bus_dmamap_t map; 3103205869Sjfv struct em_buffer *rx_buffer; 3104205869Sjfv int error, nsegs; 3105205869Sjfv 3106243857Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 3107205869Sjfv if (m == NULL) { 3108205869Sjfv adapter->mbuf_cluster_failed++; 3109205869Sjfv return (ENOBUFS); 3110205869Sjfv } 3111205869Sjfv m->m_len = m->m_pkthdr.len = MCLBYTES; 3112205869Sjfv 3113205869Sjfv if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN)) 3114205869Sjfv m_adj(m, ETHER_ALIGN); 3115205869Sjfv 3116205869Sjfv /* 3117205869Sjfv * Using memory from the mbuf cluster pool, invoke the 3118205869Sjfv * bus_dma machinery to arrange the memory mapping. 3119205869Sjfv */ 3120205869Sjfv error = bus_dmamap_load_mbuf_sg(adapter->rxtag, 3121205869Sjfv adapter->rx_sparemap, m, segs, &nsegs, BUS_DMA_NOWAIT); 3122205869Sjfv if (error != 0) { 3123205869Sjfv m_free(m); 3124205869Sjfv return (error); 3125205869Sjfv } 3126205869Sjfv 3127205869Sjfv /* If nsegs is wrong then the stack is corrupt. */ 3128205869Sjfv KASSERT(nsegs == 1, ("Too many segments returned!")); 3129205869Sjfv 3130205869Sjfv rx_buffer = &adapter->rx_buffer_area[i]; 3131205869Sjfv if (rx_buffer->m_head != NULL) 3132205869Sjfv bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 3133205869Sjfv 3134205869Sjfv map = rx_buffer->map; 3135205869Sjfv rx_buffer->map = adapter->rx_sparemap; 3136205869Sjfv adapter->rx_sparemap = map; 3137205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD); 3138205869Sjfv rx_buffer->m_head = m; 3139205869Sjfv 3140205869Sjfv adapter->rx_desc_base[i].buffer_addr = htole64(segs[0].ds_addr); 3141205869Sjfv return (0); 3142205869Sjfv} 3143205869Sjfv 3144205869Sjfv/********************************************************************* 3145205869Sjfv * 3146205869Sjfv * Allocate memory for rx_buffer structures. Since we use one 3147205869Sjfv * rx_buffer per received packet, the maximum number of rx_buffer's 3148205869Sjfv * that we'll need is equal to the number of receive descriptors 3149205869Sjfv * that we've allocated. 3150205869Sjfv * 3151205869Sjfv **********************************************************************/ 3152205869Sjfvstatic int 3153205869Sjfvlem_allocate_receive_structures(struct adapter *adapter) 3154205869Sjfv{ 3155205869Sjfv device_t dev = adapter->dev; 3156205869Sjfv struct em_buffer *rx_buffer; 3157205869Sjfv int i, error; 3158205869Sjfv 3159205869Sjfv adapter->rx_buffer_area = malloc(sizeof(struct em_buffer) * 3160205869Sjfv adapter->num_rx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); 3161205869Sjfv if (adapter->rx_buffer_area == NULL) { 3162205869Sjfv device_printf(dev, "Unable to allocate rx_buffer memory\n"); 3163205869Sjfv return (ENOMEM); 3164205869Sjfv } 3165205869Sjfv 3166205869Sjfv error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 3167205869Sjfv 1, 0, /* alignment, bounds */ 3168205869Sjfv BUS_SPACE_MAXADDR, /* lowaddr */ 3169205869Sjfv BUS_SPACE_MAXADDR, /* highaddr */ 3170205869Sjfv NULL, NULL, /* filter, filterarg */ 3171205869Sjfv MCLBYTES, /* maxsize */ 3172205869Sjfv 1, /* nsegments */ 3173205869Sjfv MCLBYTES, /* maxsegsize */ 3174205869Sjfv 0, /* flags */ 3175205869Sjfv NULL, /* lockfunc */ 3176205869Sjfv NULL, /* lockarg */ 3177205869Sjfv &adapter->rxtag); 3178205869Sjfv if (error) { 3179205869Sjfv device_printf(dev, "%s: bus_dma_tag_create failed %d\n", 3180205869Sjfv __func__, error); 3181205869Sjfv goto fail; 3182205869Sjfv } 3183205869Sjfv 3184205869Sjfv /* Create the spare map (used by getbuf) */ 3185205869Sjfv error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT, 3186205869Sjfv &adapter->rx_sparemap); 3187205869Sjfv if (error) { 3188205869Sjfv device_printf(dev, "%s: bus_dmamap_create failed: %d\n", 3189205869Sjfv __func__, error); 3190205869Sjfv goto fail; 3191205869Sjfv } 3192205869Sjfv 3193205869Sjfv rx_buffer = adapter->rx_buffer_area; 3194205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3195205869Sjfv error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT, 3196205869Sjfv &rx_buffer->map); 3197205869Sjfv if (error) { 3198205869Sjfv device_printf(dev, "%s: bus_dmamap_create failed: %d\n", 3199205869Sjfv __func__, error); 3200205869Sjfv goto fail; 3201205869Sjfv } 3202205869Sjfv } 3203205869Sjfv 3204205869Sjfv return (0); 3205205869Sjfv 3206205869Sjfvfail: 3207205869Sjfv lem_free_receive_structures(adapter); 3208205869Sjfv return (error); 3209205869Sjfv} 3210205869Sjfv 3211205869Sjfv/********************************************************************* 3212205869Sjfv * 3213205869Sjfv * (Re)initialize receive structures. 3214205869Sjfv * 3215205869Sjfv **********************************************************************/ 3216205869Sjfvstatic int 3217205869Sjfvlem_setup_receive_structures(struct adapter *adapter) 3218205869Sjfv{ 3219205869Sjfv struct em_buffer *rx_buffer; 3220205869Sjfv int i, error; 3221228281Sluigi#ifdef DEV_NETMAP 3222228281Sluigi /* we are already under lock */ 3223228281Sluigi struct netmap_adapter *na = NA(adapter->ifp); 3224228281Sluigi struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0); 3225228281Sluigi#endif 3226205869Sjfv 3227205869Sjfv /* Reset descriptor ring */ 3228205869Sjfv bzero(adapter->rx_desc_base, 3229205869Sjfv (sizeof(struct e1000_rx_desc)) * adapter->num_rx_desc); 3230205869Sjfv 3231205869Sjfv /* Free current RX buffers. */ 3232205869Sjfv rx_buffer = adapter->rx_buffer_area; 3233205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3234205869Sjfv if (rx_buffer->m_head != NULL) { 3235205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, 3236205869Sjfv BUS_DMASYNC_POSTREAD); 3237205869Sjfv bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 3238205869Sjfv m_freem(rx_buffer->m_head); 3239205869Sjfv rx_buffer->m_head = NULL; 3240205869Sjfv } 3241205869Sjfv } 3242205869Sjfv 3243205869Sjfv /* Allocate new ones. */ 3244205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++) { 3245228281Sluigi#ifdef DEV_NETMAP 3246228281Sluigi if (slot) { 3247231796Sluigi /* the i-th NIC entry goes to slot si */ 3248232238Sluigi int si = netmap_idx_n2k(&na->rx_rings[0], i); 3249229939Sluigi uint64_t paddr; 3250228281Sluigi void *addr; 3251228281Sluigi 3252229939Sluigi addr = PNMB(slot + si, &paddr); 3253229939Sluigi netmap_load_map(adapter->rxtag, rx_buffer->map, addr); 3254228281Sluigi /* Update descriptor */ 3255229939Sluigi adapter->rx_desc_base[i].buffer_addr = htole64(paddr); 3256228281Sluigi continue; 3257228281Sluigi } 3258228281Sluigi#endif /* DEV_NETMAP */ 3259205869Sjfv error = lem_get_buf(adapter, i); 3260205869Sjfv if (error) 3261205869Sjfv return (error); 3262205869Sjfv } 3263205869Sjfv 3264205869Sjfv /* Setup our descriptor pointers */ 3265205869Sjfv adapter->next_rx_desc_to_check = 0; 3266205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3267205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3268205869Sjfv 3269205869Sjfv return (0); 3270205869Sjfv} 3271205869Sjfv 3272205869Sjfv/********************************************************************* 3273205869Sjfv * 3274205869Sjfv * Enable receive unit. 3275205869Sjfv * 3276205869Sjfv **********************************************************************/ 3277205869Sjfv 3278205869Sjfvstatic void 3279205869Sjfvlem_initialize_receive_unit(struct adapter *adapter) 3280205869Sjfv{ 3281205869Sjfv struct ifnet *ifp = adapter->ifp; 3282205869Sjfv u64 bus_addr; 3283205869Sjfv u32 rctl, rxcsum; 3284205869Sjfv 3285205869Sjfv INIT_DEBUGOUT("lem_initialize_receive_unit: begin"); 3286205869Sjfv 3287205869Sjfv /* 3288205869Sjfv * Make sure receives are disabled while setting 3289205869Sjfv * up the descriptor ring 3290205869Sjfv */ 3291205869Sjfv rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 3292205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); 3293205869Sjfv 3294205869Sjfv if (adapter->hw.mac.type >= e1000_82540) { 3295205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RADV, 3296205869Sjfv adapter->rx_abs_int_delay.value); 3297205869Sjfv /* 3298205869Sjfv * Set the interrupt throttling rate. Value is calculated 3299205869Sjfv * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) 3300205869Sjfv */ 3301205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_ITR, DEFAULT_ITR); 3302205869Sjfv } 3303205869Sjfv 3304205869Sjfv /* Setup the Base and Length of the Rx Descriptor Ring */ 3305205869Sjfv bus_addr = adapter->rxdma.dma_paddr; 3306205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0), 3307205869Sjfv adapter->num_rx_desc * sizeof(struct e1000_rx_desc)); 3308205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDBAH(0), 3309205869Sjfv (u32)(bus_addr >> 32)); 3310205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDBAL(0), 3311205869Sjfv (u32)bus_addr); 3312205869Sjfv 3313205869Sjfv /* Setup the Receive Control Register */ 3314205869Sjfv rctl &= ~(3 << E1000_RCTL_MO_SHIFT); 3315205869Sjfv rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | 3316205869Sjfv E1000_RCTL_RDMTS_HALF | 3317205869Sjfv (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); 3318205869Sjfv 3319205869Sjfv /* Make sure VLAN Filters are off */ 3320205869Sjfv rctl &= ~E1000_RCTL_VFE; 3321205869Sjfv 3322205869Sjfv if (e1000_tbi_sbp_enabled_82543(&adapter->hw)) 3323205869Sjfv rctl |= E1000_RCTL_SBP; 3324205869Sjfv else 3325205869Sjfv rctl &= ~E1000_RCTL_SBP; 3326205869Sjfv 3327205869Sjfv switch (adapter->rx_buffer_len) { 3328205869Sjfv default: 3329205869Sjfv case 2048: 3330205869Sjfv rctl |= E1000_RCTL_SZ_2048; 3331205869Sjfv break; 3332205869Sjfv case 4096: 3333205869Sjfv rctl |= E1000_RCTL_SZ_4096 | 3334205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3335205869Sjfv break; 3336205869Sjfv case 8192: 3337205869Sjfv rctl |= E1000_RCTL_SZ_8192 | 3338205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3339205869Sjfv break; 3340205869Sjfv case 16384: 3341205869Sjfv rctl |= E1000_RCTL_SZ_16384 | 3342205869Sjfv E1000_RCTL_BSEX | E1000_RCTL_LPE; 3343205869Sjfv break; 3344205869Sjfv } 3345205869Sjfv 3346205869Sjfv if (ifp->if_mtu > ETHERMTU) 3347205869Sjfv rctl |= E1000_RCTL_LPE; 3348205869Sjfv else 3349205869Sjfv rctl &= ~E1000_RCTL_LPE; 3350205869Sjfv 3351205869Sjfv /* Enable 82543 Receive Checksum Offload for TCP and UDP */ 3352205869Sjfv if ((adapter->hw.mac.type >= e1000_82543) && 3353205869Sjfv (ifp->if_capenable & IFCAP_RXCSUM)) { 3354205869Sjfv rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM); 3355205869Sjfv rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); 3356205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum); 3357205869Sjfv } 3358205869Sjfv 3359205869Sjfv /* Enable Receives */ 3360205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); 3361205869Sjfv 3362205869Sjfv /* 3363205869Sjfv * Setup the HW Rx Head and 3364205869Sjfv * Tail Descriptor Pointers 3365205869Sjfv */ 3366205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0); 3367250413Sluigi rctl = adapter->num_rx_desc - 1; /* default RDT value */ 3368228281Sluigi#ifdef DEV_NETMAP 3369228281Sluigi /* preserve buffers already made available to clients */ 3370250413Sluigi if (ifp->if_capenable & IFCAP_NETMAP) 3371250413Sluigi rctl -= NA(adapter->ifp)->rx_rings[0].nr_hwavail; 3372228281Sluigi#endif /* DEV_NETMAP */ 3373250413Sluigi E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), rctl); 3374205869Sjfv 3375205869Sjfv return; 3376205869Sjfv} 3377205869Sjfv 3378205869Sjfv/********************************************************************* 3379205869Sjfv * 3380205869Sjfv * Free receive related data structures. 3381205869Sjfv * 3382205869Sjfv **********************************************************************/ 3383205869Sjfvstatic void 3384205869Sjfvlem_free_receive_structures(struct adapter *adapter) 3385205869Sjfv{ 3386205869Sjfv struct em_buffer *rx_buffer; 3387205869Sjfv int i; 3388205869Sjfv 3389205869Sjfv INIT_DEBUGOUT("free_receive_structures: begin"); 3390205869Sjfv 3391205869Sjfv if (adapter->rx_sparemap) { 3392205869Sjfv bus_dmamap_destroy(adapter->rxtag, adapter->rx_sparemap); 3393205869Sjfv adapter->rx_sparemap = NULL; 3394205869Sjfv } 3395205869Sjfv 3396205869Sjfv /* Cleanup any existing buffers */ 3397205869Sjfv if (adapter->rx_buffer_area != NULL) { 3398205869Sjfv rx_buffer = adapter->rx_buffer_area; 3399205869Sjfv for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 3400205869Sjfv if (rx_buffer->m_head != NULL) { 3401205869Sjfv bus_dmamap_sync(adapter->rxtag, rx_buffer->map, 3402205869Sjfv BUS_DMASYNC_POSTREAD); 3403205869Sjfv bus_dmamap_unload(adapter->rxtag, 3404205869Sjfv rx_buffer->map); 3405205869Sjfv m_freem(rx_buffer->m_head); 3406205869Sjfv rx_buffer->m_head = NULL; 3407205869Sjfv } else if (rx_buffer->map != NULL) 3408205869Sjfv bus_dmamap_unload(adapter->rxtag, 3409205869Sjfv rx_buffer->map); 3410205869Sjfv if (rx_buffer->map != NULL) { 3411205869Sjfv bus_dmamap_destroy(adapter->rxtag, 3412205869Sjfv rx_buffer->map); 3413205869Sjfv rx_buffer->map = NULL; 3414205869Sjfv } 3415205869Sjfv } 3416205869Sjfv } 3417205869Sjfv 3418205869Sjfv if (adapter->rx_buffer_area != NULL) { 3419205869Sjfv free(adapter->rx_buffer_area, M_DEVBUF); 3420205869Sjfv adapter->rx_buffer_area = NULL; 3421205869Sjfv } 3422205869Sjfv 3423205869Sjfv if (adapter->rxtag != NULL) { 3424205869Sjfv bus_dma_tag_destroy(adapter->rxtag); 3425205869Sjfv adapter->rxtag = NULL; 3426205869Sjfv } 3427205869Sjfv} 3428205869Sjfv 3429205869Sjfv/********************************************************************* 3430205869Sjfv * 3431205869Sjfv * This routine executes in interrupt context. It replenishes 3432205869Sjfv * the mbufs in the descriptor and sends data which has been 3433205869Sjfv * dma'ed into host memory to upper layer. 3434205869Sjfv * 3435205869Sjfv * We loop at most count times if count is > 0, or until done if 3436205869Sjfv * count < 0. 3437205869Sjfv * 3438205869Sjfv * For polling we also now return the number of cleaned packets 3439205869Sjfv *********************************************************************/ 3440209238Sjfvstatic bool 3441209238Sjfvlem_rxeof(struct adapter *adapter, int count, int *done) 3442205869Sjfv{ 3443241844Seadler struct ifnet *ifp = adapter->ifp; 3444205869Sjfv struct mbuf *mp; 3445214646Sjfv u8 status = 0, accept_frame = 0, eop = 0; 3446205869Sjfv u16 len, desc_len, prev_len_adj; 3447205869Sjfv int i, rx_sent = 0; 3448205869Sjfv struct e1000_rx_desc *current_desc; 3449205869Sjfv 3450205869Sjfv EM_RX_LOCK(adapter); 3451205869Sjfv i = adapter->next_rx_desc_to_check; 3452205869Sjfv current_desc = &adapter->rx_desc_base[i]; 3453205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3454205869Sjfv BUS_DMASYNC_POSTREAD); 3455205869Sjfv 3456228281Sluigi#ifdef DEV_NETMAP 3457250109Sluigi if (netmap_rx_irq(ifp, 0 | NETMAP_LOCKED_ENTER, &rx_sent)) 3458250109Sluigi return (FALSE); 3459228281Sluigi#endif /* DEV_NETMAP */ 3460228281Sluigi 3461205869Sjfv if (!((current_desc->status) & E1000_RXD_STAT_DD)) { 3462209238Sjfv if (done != NULL) 3463209238Sjfv *done = rx_sent; 3464205869Sjfv EM_RX_UNLOCK(adapter); 3465209238Sjfv return (FALSE); 3466205869Sjfv } 3467205869Sjfv 3468214646Sjfv while (count != 0 && ifp->if_drv_flags & IFF_DRV_RUNNING) { 3469205869Sjfv struct mbuf *m = NULL; 3470205869Sjfv 3471214646Sjfv status = current_desc->status; 3472214646Sjfv if ((status & E1000_RXD_STAT_DD) == 0) 3473214646Sjfv break; 3474214646Sjfv 3475205869Sjfv mp = adapter->rx_buffer_area[i].m_head; 3476205869Sjfv /* 3477205869Sjfv * Can't defer bus_dmamap_sync(9) because TBI_ACCEPT 3478205869Sjfv * needs to access the last received byte in the mbuf. 3479205869Sjfv */ 3480205869Sjfv bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map, 3481205869Sjfv BUS_DMASYNC_POSTREAD); 3482205869Sjfv 3483205869Sjfv accept_frame = 1; 3484205869Sjfv prev_len_adj = 0; 3485205869Sjfv desc_len = le16toh(current_desc->length); 3486205869Sjfv if (status & E1000_RXD_STAT_EOP) { 3487205869Sjfv count--; 3488205869Sjfv eop = 1; 3489205869Sjfv if (desc_len < ETHER_CRC_LEN) { 3490205869Sjfv len = 0; 3491205869Sjfv prev_len_adj = ETHER_CRC_LEN - desc_len; 3492205869Sjfv } else 3493205869Sjfv len = desc_len - ETHER_CRC_LEN; 3494205869Sjfv } else { 3495205869Sjfv eop = 0; 3496205869Sjfv len = desc_len; 3497205869Sjfv } 3498205869Sjfv 3499205869Sjfv if (current_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) { 3500205869Sjfv u8 last_byte; 3501205869Sjfv u32 pkt_len = desc_len; 3502205869Sjfv 3503205869Sjfv if (adapter->fmp != NULL) 3504205869Sjfv pkt_len += adapter->fmp->m_pkthdr.len; 3505205869Sjfv 3506205869Sjfv last_byte = *(mtod(mp, caddr_t) + desc_len - 1); 3507205869Sjfv if (TBI_ACCEPT(&adapter->hw, status, 3508205869Sjfv current_desc->errors, pkt_len, last_byte, 3509205869Sjfv adapter->min_frame_size, adapter->max_frame_size)) { 3510205869Sjfv e1000_tbi_adjust_stats_82543(&adapter->hw, 3511205869Sjfv &adapter->stats, pkt_len, 3512205869Sjfv adapter->hw.mac.addr, 3513205869Sjfv adapter->max_frame_size); 3514205869Sjfv if (len > 0) 3515205869Sjfv len--; 3516205869Sjfv } else 3517205869Sjfv accept_frame = 0; 3518205869Sjfv } 3519205869Sjfv 3520205869Sjfv if (accept_frame) { 3521205869Sjfv if (lem_get_buf(adapter, i) != 0) { 3522205869Sjfv ifp->if_iqdrops++; 3523205869Sjfv goto discard; 3524205869Sjfv } 3525205869Sjfv 3526205869Sjfv /* Assign correct length to the current fragment */ 3527205869Sjfv mp->m_len = len; 3528205869Sjfv 3529205869Sjfv if (adapter->fmp == NULL) { 3530205869Sjfv mp->m_pkthdr.len = len; 3531205869Sjfv adapter->fmp = mp; /* Store the first mbuf */ 3532205869Sjfv adapter->lmp = mp; 3533205869Sjfv } else { 3534205869Sjfv /* Chain mbuf's together */ 3535205869Sjfv mp->m_flags &= ~M_PKTHDR; 3536205869Sjfv /* 3537205869Sjfv * Adjust length of previous mbuf in chain if 3538205869Sjfv * we received less than 4 bytes in the last 3539205869Sjfv * descriptor. 3540205869Sjfv */ 3541205869Sjfv if (prev_len_adj > 0) { 3542205869Sjfv adapter->lmp->m_len -= prev_len_adj; 3543205869Sjfv adapter->fmp->m_pkthdr.len -= 3544205869Sjfv prev_len_adj; 3545205869Sjfv } 3546205869Sjfv adapter->lmp->m_next = mp; 3547205869Sjfv adapter->lmp = adapter->lmp->m_next; 3548205869Sjfv adapter->fmp->m_pkthdr.len += len; 3549205869Sjfv } 3550205869Sjfv 3551205869Sjfv if (eop) { 3552205869Sjfv adapter->fmp->m_pkthdr.rcvif = ifp; 3553205869Sjfv ifp->if_ipackets++; 3554205869Sjfv lem_receive_checksum(adapter, current_desc, 3555205869Sjfv adapter->fmp); 3556205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3557205869Sjfv if (adapter->max_frame_size > 3558205869Sjfv (MCLBYTES - ETHER_ALIGN) && 3559205869Sjfv lem_fixup_rx(adapter) != 0) 3560205869Sjfv goto skip; 3561205869Sjfv#endif 3562205869Sjfv if (status & E1000_RXD_STAT_VP) { 3563205869Sjfv adapter->fmp->m_pkthdr.ether_vtag = 3564229606Srwatson le16toh(current_desc->special); 3565205869Sjfv adapter->fmp->m_flags |= M_VLANTAG; 3566205869Sjfv } 3567205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3568205869Sjfvskip: 3569205869Sjfv#endif 3570205869Sjfv m = adapter->fmp; 3571205869Sjfv adapter->fmp = NULL; 3572205869Sjfv adapter->lmp = NULL; 3573205869Sjfv } 3574205869Sjfv } else { 3575240879Ssbruno adapter->dropped_pkts++; 3576205869Sjfvdiscard: 3577205869Sjfv /* Reuse loaded DMA map and just update mbuf chain */ 3578205869Sjfv mp = adapter->rx_buffer_area[i].m_head; 3579205869Sjfv mp->m_len = mp->m_pkthdr.len = MCLBYTES; 3580205869Sjfv mp->m_data = mp->m_ext.ext_buf; 3581205869Sjfv mp->m_next = NULL; 3582205869Sjfv if (adapter->max_frame_size <= 3583205869Sjfv (MCLBYTES - ETHER_ALIGN)) 3584205869Sjfv m_adj(mp, ETHER_ALIGN); 3585205869Sjfv if (adapter->fmp != NULL) { 3586205869Sjfv m_freem(adapter->fmp); 3587205869Sjfv adapter->fmp = NULL; 3588205869Sjfv adapter->lmp = NULL; 3589205869Sjfv } 3590205869Sjfv m = NULL; 3591205869Sjfv } 3592205869Sjfv 3593205869Sjfv /* Zero out the receive descriptors status. */ 3594205869Sjfv current_desc->status = 0; 3595205869Sjfv bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, 3596205869Sjfv BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3597205869Sjfv 3598205869Sjfv /* Advance our pointers to the next descriptor. */ 3599205869Sjfv if (++i == adapter->num_rx_desc) 3600205869Sjfv i = 0; 3601205869Sjfv /* Call into the stack */ 3602205869Sjfv if (m != NULL) { 3603205869Sjfv adapter->next_rx_desc_to_check = i; 3604205869Sjfv EM_RX_UNLOCK(adapter); 3605205869Sjfv (*ifp->if_input)(ifp, m); 3606205869Sjfv EM_RX_LOCK(adapter); 3607205869Sjfv rx_sent++; 3608205869Sjfv i = adapter->next_rx_desc_to_check; 3609205869Sjfv } 3610205869Sjfv current_desc = &adapter->rx_desc_base[i]; 3611205869Sjfv } 3612205869Sjfv adapter->next_rx_desc_to_check = i; 3613205869Sjfv 3614205869Sjfv /* Advance the E1000's Receive Queue #0 "Tail Pointer". */ 3615205869Sjfv if (--i < 0) 3616205869Sjfv i = adapter->num_rx_desc - 1; 3617205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); 3618209238Sjfv if (done != NULL) 3619209238Sjfv *done = rx_sent; 3620205869Sjfv EM_RX_UNLOCK(adapter); 3621214646Sjfv return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE); 3622205869Sjfv} 3623205869Sjfv 3624205869Sjfv#ifndef __NO_STRICT_ALIGNMENT 3625205869Sjfv/* 3626205869Sjfv * When jumbo frames are enabled we should realign entire payload on 3627205869Sjfv * architecures with strict alignment. This is serious design mistake of 8254x 3628205869Sjfv * as it nullifies DMA operations. 8254x just allows RX buffer size to be 3629205869Sjfv * 2048/4096/8192/16384. What we really want is 2048 - ETHER_ALIGN to align its 3630205869Sjfv * payload. On architecures without strict alignment restrictions 8254x still 3631205869Sjfv * performs unaligned memory access which would reduce the performance too. 3632205869Sjfv * To avoid copying over an entire frame to align, we allocate a new mbuf and 3633205869Sjfv * copy ethernet header to the new mbuf. The new mbuf is prepended into the 3634205869Sjfv * existing mbuf chain. 3635205869Sjfv * 3636205869Sjfv * Be aware, best performance of the 8254x is achived only when jumbo frame is 3637205869Sjfv * not used at all on architectures with strict alignment. 3638205869Sjfv */ 3639205869Sjfvstatic int 3640205869Sjfvlem_fixup_rx(struct adapter *adapter) 3641205869Sjfv{ 3642205869Sjfv struct mbuf *m, *n; 3643205869Sjfv int error; 3644205869Sjfv 3645205869Sjfv error = 0; 3646205869Sjfv m = adapter->fmp; 3647205869Sjfv if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN)) { 3648205869Sjfv bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len); 3649205869Sjfv m->m_data += ETHER_HDR_LEN; 3650205869Sjfv } else { 3651243857Sglebius MGETHDR(n, M_NOWAIT, MT_DATA); 3652205869Sjfv if (n != NULL) { 3653205869Sjfv bcopy(m->m_data, n->m_data, ETHER_HDR_LEN); 3654205869Sjfv m->m_data += ETHER_HDR_LEN; 3655205869Sjfv m->m_len -= ETHER_HDR_LEN; 3656205869Sjfv n->m_len = ETHER_HDR_LEN; 3657205869Sjfv M_MOVE_PKTHDR(n, m); 3658205869Sjfv n->m_next = m; 3659205869Sjfv adapter->fmp = n; 3660205869Sjfv } else { 3661205869Sjfv adapter->dropped_pkts++; 3662205869Sjfv m_freem(adapter->fmp); 3663205869Sjfv adapter->fmp = NULL; 3664205869Sjfv error = ENOMEM; 3665205869Sjfv } 3666205869Sjfv } 3667205869Sjfv 3668205869Sjfv return (error); 3669205869Sjfv} 3670205869Sjfv#endif 3671205869Sjfv 3672205869Sjfv/********************************************************************* 3673205869Sjfv * 3674205869Sjfv * Verify that the hardware indicated that the checksum is valid. 3675205869Sjfv * Inform the stack about the status of checksum so that stack 3676205869Sjfv * doesn't spend time verifying the checksum. 3677205869Sjfv * 3678205869Sjfv *********************************************************************/ 3679205869Sjfvstatic void 3680205869Sjfvlem_receive_checksum(struct adapter *adapter, 3681205869Sjfv struct e1000_rx_desc *rx_desc, struct mbuf *mp) 3682205869Sjfv{ 3683205869Sjfv /* 82543 or newer only */ 3684205869Sjfv if ((adapter->hw.mac.type < e1000_82543) || 3685205869Sjfv /* Ignore Checksum bit is set */ 3686205869Sjfv (rx_desc->status & E1000_RXD_STAT_IXSM)) { 3687205869Sjfv mp->m_pkthdr.csum_flags = 0; 3688205869Sjfv return; 3689205869Sjfv } 3690205869Sjfv 3691205869Sjfv if (rx_desc->status & E1000_RXD_STAT_IPCS) { 3692205869Sjfv /* Did it pass? */ 3693205869Sjfv if (!(rx_desc->errors & E1000_RXD_ERR_IPE)) { 3694205869Sjfv /* IP Checksum Good */ 3695205869Sjfv mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; 3696205869Sjfv mp->m_pkthdr.csum_flags |= CSUM_IP_VALID; 3697205869Sjfv 3698205869Sjfv } else { 3699205869Sjfv mp->m_pkthdr.csum_flags = 0; 3700205869Sjfv } 3701205869Sjfv } 3702205869Sjfv 3703205869Sjfv if (rx_desc->status & E1000_RXD_STAT_TCPCS) { 3704205869Sjfv /* Did it pass? */ 3705205869Sjfv if (!(rx_desc->errors & E1000_RXD_ERR_TCPE)) { 3706205869Sjfv mp->m_pkthdr.csum_flags |= 3707205869Sjfv (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); 3708205869Sjfv mp->m_pkthdr.csum_data = htons(0xffff); 3709205869Sjfv } 3710205869Sjfv } 3711205869Sjfv} 3712205869Sjfv 3713205869Sjfv/* 3714205869Sjfv * This routine is run via an vlan 3715205869Sjfv * config EVENT 3716205869Sjfv */ 3717205869Sjfvstatic void 3718205869Sjfvlem_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3719205869Sjfv{ 3720205869Sjfv struct adapter *adapter = ifp->if_softc; 3721205869Sjfv u32 index, bit; 3722205869Sjfv 3723205869Sjfv if (ifp->if_softc != arg) /* Not our event */ 3724205869Sjfv return; 3725205869Sjfv 3726205869Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid ID */ 3727205869Sjfv return; 3728205869Sjfv 3729214646Sjfv EM_CORE_LOCK(adapter); 3730205869Sjfv index = (vtag >> 5) & 0x7F; 3731205869Sjfv bit = vtag & 0x1F; 3732214646Sjfv adapter->shadow_vfta[index] |= (1 << bit); 3733205869Sjfv ++adapter->num_vlans; 3734205869Sjfv /* Re-init to load the changes */ 3735214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 3736214646Sjfv lem_init_locked(adapter); 3737214646Sjfv EM_CORE_UNLOCK(adapter); 3738205869Sjfv} 3739205869Sjfv 3740205869Sjfv/* 3741205869Sjfv * This routine is run via an vlan 3742205869Sjfv * unconfig EVENT 3743205869Sjfv */ 3744205869Sjfvstatic void 3745205869Sjfvlem_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) 3746205869Sjfv{ 3747205869Sjfv struct adapter *adapter = ifp->if_softc; 3748205869Sjfv u32 index, bit; 3749205869Sjfv 3750205869Sjfv if (ifp->if_softc != arg) 3751205869Sjfv return; 3752205869Sjfv 3753205869Sjfv if ((vtag == 0) || (vtag > 4095)) /* Invalid */ 3754205869Sjfv return; 3755205869Sjfv 3756214646Sjfv EM_CORE_LOCK(adapter); 3757205869Sjfv index = (vtag >> 5) & 0x7F; 3758205869Sjfv bit = vtag & 0x1F; 3759214646Sjfv adapter->shadow_vfta[index] &= ~(1 << bit); 3760205869Sjfv --adapter->num_vlans; 3761205869Sjfv /* Re-init to load the changes */ 3762214646Sjfv if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) 3763214646Sjfv lem_init_locked(adapter); 3764214646Sjfv EM_CORE_UNLOCK(adapter); 3765205869Sjfv} 3766205869Sjfv 3767205869Sjfvstatic void 3768205869Sjfvlem_setup_vlan_hw_support(struct adapter *adapter) 3769205869Sjfv{ 3770205869Sjfv struct e1000_hw *hw = &adapter->hw; 3771205869Sjfv u32 reg; 3772205869Sjfv 3773205869Sjfv /* 3774205869Sjfv ** We get here thru init_locked, meaning 3775205869Sjfv ** a soft reset, this has already cleared 3776205869Sjfv ** the VFTA and other state, so if there 3777205869Sjfv ** have been no vlan's registered do nothing. 3778205869Sjfv */ 3779205869Sjfv if (adapter->num_vlans == 0) 3780205869Sjfv return; 3781205869Sjfv 3782205869Sjfv /* 3783205869Sjfv ** A soft reset zero's out the VFTA, so 3784205869Sjfv ** we need to repopulate it now. 3785205869Sjfv */ 3786205869Sjfv for (int i = 0; i < EM_VFTA_SIZE; i++) 3787214646Sjfv if (adapter->shadow_vfta[i] != 0) 3788205869Sjfv E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, 3789214646Sjfv i, adapter->shadow_vfta[i]); 3790205869Sjfv 3791205869Sjfv reg = E1000_READ_REG(hw, E1000_CTRL); 3792205869Sjfv reg |= E1000_CTRL_VME; 3793205869Sjfv E1000_WRITE_REG(hw, E1000_CTRL, reg); 3794205869Sjfv 3795205869Sjfv /* Enable the Filter Table */ 3796205869Sjfv reg = E1000_READ_REG(hw, E1000_RCTL); 3797205869Sjfv reg &= ~E1000_RCTL_CFIEN; 3798205869Sjfv reg |= E1000_RCTL_VFE; 3799205869Sjfv E1000_WRITE_REG(hw, E1000_RCTL, reg); 3800205869Sjfv} 3801205869Sjfv 3802205869Sjfvstatic void 3803205869Sjfvlem_enable_intr(struct adapter *adapter) 3804205869Sjfv{ 3805205869Sjfv struct e1000_hw *hw = &adapter->hw; 3806205869Sjfv u32 ims_mask = IMS_ENABLE_MASK; 3807205869Sjfv 3808205869Sjfv E1000_WRITE_REG(hw, E1000_IMS, ims_mask); 3809205869Sjfv} 3810205869Sjfv 3811205869Sjfvstatic void 3812205869Sjfvlem_disable_intr(struct adapter *adapter) 3813205869Sjfv{ 3814205869Sjfv struct e1000_hw *hw = &adapter->hw; 3815205869Sjfv 3816238953Sjfv E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 3817205869Sjfv} 3818205869Sjfv 3819205869Sjfv/* 3820205869Sjfv * Bit of a misnomer, what this really means is 3821205869Sjfv * to enable OS management of the system... aka 3822205869Sjfv * to disable special hardware management features 3823205869Sjfv */ 3824205869Sjfvstatic void 3825205869Sjfvlem_init_manageability(struct adapter *adapter) 3826205869Sjfv{ 3827205869Sjfv /* A shared code workaround */ 3828205869Sjfv if (adapter->has_manage) { 3829205869Sjfv int manc = E1000_READ_REG(&adapter->hw, E1000_MANC); 3830205869Sjfv /* disable hardware interception of ARP */ 3831205869Sjfv manc &= ~(E1000_MANC_ARP_EN); 3832205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); 3833205869Sjfv } 3834205869Sjfv} 3835205869Sjfv 3836205869Sjfv/* 3837205869Sjfv * Give control back to hardware management 3838205869Sjfv * controller if there is one. 3839205869Sjfv */ 3840205869Sjfvstatic void 3841205869Sjfvlem_release_manageability(struct adapter *adapter) 3842205869Sjfv{ 3843205869Sjfv if (adapter->has_manage) { 3844205869Sjfv int manc = E1000_READ_REG(&adapter->hw, E1000_MANC); 3845205869Sjfv 3846205869Sjfv /* re-enable hardware interception of ARP */ 3847205869Sjfv manc |= E1000_MANC_ARP_EN; 3848205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); 3849205869Sjfv } 3850205869Sjfv} 3851205869Sjfv 3852205869Sjfv/* 3853205869Sjfv * lem_get_hw_control sets the {CTRL_EXT|FWSM}:DRV_LOAD bit. 3854205869Sjfv * For ASF and Pass Through versions of f/w this means 3855205869Sjfv * that the driver is loaded. For AMT version type f/w 3856205869Sjfv * this means that the network i/f is open. 3857205869Sjfv */ 3858205869Sjfvstatic void 3859205869Sjfvlem_get_hw_control(struct adapter *adapter) 3860205869Sjfv{ 3861205869Sjfv u32 ctrl_ext; 3862205869Sjfv 3863205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 3864205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, 3865205869Sjfv ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); 3866205869Sjfv return; 3867205869Sjfv} 3868205869Sjfv 3869205869Sjfv/* 3870205869Sjfv * lem_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit. 3871205869Sjfv * For ASF and Pass Through versions of f/w this means that 3872205869Sjfv * the driver is no longer loaded. For AMT versions of the 3873205869Sjfv * f/w this means that the network i/f is closed. 3874205869Sjfv */ 3875205869Sjfvstatic void 3876205869Sjfvlem_release_hw_control(struct adapter *adapter) 3877205869Sjfv{ 3878205869Sjfv u32 ctrl_ext; 3879205869Sjfv 3880205869Sjfv if (!adapter->has_manage) 3881205869Sjfv return; 3882205869Sjfv 3883205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 3884205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, 3885205869Sjfv ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); 3886205869Sjfv return; 3887205869Sjfv} 3888205869Sjfv 3889205869Sjfvstatic int 3890205869Sjfvlem_is_valid_ether_addr(u8 *addr) 3891205869Sjfv{ 3892205869Sjfv char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; 3893205869Sjfv 3894205869Sjfv if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) { 3895205869Sjfv return (FALSE); 3896205869Sjfv } 3897205869Sjfv 3898205869Sjfv return (TRUE); 3899205869Sjfv} 3900205869Sjfv 3901205869Sjfv/* 3902205869Sjfv** Parse the interface capabilities with regard 3903205869Sjfv** to both system management and wake-on-lan for 3904205869Sjfv** later use. 3905205869Sjfv*/ 3906205869Sjfvstatic void 3907205869Sjfvlem_get_wakeup(device_t dev) 3908205869Sjfv{ 3909205869Sjfv struct adapter *adapter = device_get_softc(dev); 3910205869Sjfv u16 eeprom_data = 0, device_id, apme_mask; 3911205869Sjfv 3912205869Sjfv adapter->has_manage = e1000_enable_mng_pass_thru(&adapter->hw); 3913205869Sjfv apme_mask = EM_EEPROM_APME; 3914205869Sjfv 3915205869Sjfv switch (adapter->hw.mac.type) { 3916205869Sjfv case e1000_82542: 3917205869Sjfv case e1000_82543: 3918205869Sjfv break; 3919205869Sjfv case e1000_82544: 3920205869Sjfv e1000_read_nvm(&adapter->hw, 3921205869Sjfv NVM_INIT_CONTROL2_REG, 1, &eeprom_data); 3922205869Sjfv apme_mask = EM_82544_APME; 3923205869Sjfv break; 3924205869Sjfv case e1000_82546: 3925205869Sjfv case e1000_82546_rev_3: 3926205869Sjfv if (adapter->hw.bus.func == 1) { 3927205869Sjfv e1000_read_nvm(&adapter->hw, 3928205869Sjfv NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); 3929205869Sjfv break; 3930205869Sjfv } else 3931205869Sjfv e1000_read_nvm(&adapter->hw, 3932205869Sjfv NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); 3933205869Sjfv break; 3934205869Sjfv default: 3935205869Sjfv e1000_read_nvm(&adapter->hw, 3936205869Sjfv NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); 3937205869Sjfv break; 3938205869Sjfv } 3939205869Sjfv if (eeprom_data & apme_mask) 3940205869Sjfv adapter->wol = (E1000_WUFC_MAG | E1000_WUFC_MC); 3941205869Sjfv /* 3942205869Sjfv * We have the eeprom settings, now apply the special cases 3943205869Sjfv * where the eeprom may be wrong or the board won't support 3944205869Sjfv * wake on lan on a particular port 3945205869Sjfv */ 3946205869Sjfv device_id = pci_get_device(dev); 3947205869Sjfv switch (device_id) { 3948205869Sjfv case E1000_DEV_ID_82546GB_PCIE: 3949205869Sjfv adapter->wol = 0; 3950205869Sjfv break; 3951205869Sjfv case E1000_DEV_ID_82546EB_FIBER: 3952205869Sjfv case E1000_DEV_ID_82546GB_FIBER: 3953205869Sjfv /* Wake events only supported on port A for dual fiber 3954205869Sjfv * regardless of eeprom setting */ 3955205869Sjfv if (E1000_READ_REG(&adapter->hw, E1000_STATUS) & 3956205869Sjfv E1000_STATUS_FUNC_1) 3957205869Sjfv adapter->wol = 0; 3958205869Sjfv break; 3959205869Sjfv case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: 3960205869Sjfv /* if quad port adapter, disable WoL on all but port A */ 3961205869Sjfv if (global_quad_port_a != 0) 3962205869Sjfv adapter->wol = 0; 3963205869Sjfv /* Reset for multiple quad port adapters */ 3964205869Sjfv if (++global_quad_port_a == 4) 3965205869Sjfv global_quad_port_a = 0; 3966205869Sjfv break; 3967205869Sjfv } 3968205869Sjfv return; 3969205869Sjfv} 3970205869Sjfv 3971205869Sjfv 3972205869Sjfv/* 3973205869Sjfv * Enable PCI Wake On Lan capability 3974205869Sjfv */ 3975206001Smariusstatic void 3976205869Sjfvlem_enable_wakeup(device_t dev) 3977205869Sjfv{ 3978205869Sjfv struct adapter *adapter = device_get_softc(dev); 3979205869Sjfv struct ifnet *ifp = adapter->ifp; 3980205869Sjfv u32 pmc, ctrl, ctrl_ext, rctl; 3981205869Sjfv u16 status; 3982205869Sjfv 3983219902Sjhb if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0)) 3984205869Sjfv return; 3985205869Sjfv 3986205869Sjfv /* Advertise the wakeup capability */ 3987205869Sjfv ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); 3988205869Sjfv ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); 3989205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); 3990205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); 3991205869Sjfv 3992205869Sjfv /* Keep the laser running on Fiber adapters */ 3993205869Sjfv if (adapter->hw.phy.media_type == e1000_media_type_fiber || 3994205869Sjfv adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { 3995205869Sjfv ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); 3996205869Sjfv ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; 3997205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext); 3998205869Sjfv } 3999205869Sjfv 4000205869Sjfv /* 4001205869Sjfv ** Determine type of Wakeup: note that wol 4002205869Sjfv ** is set with all bits on by default. 4003205869Sjfv */ 4004205869Sjfv if ((ifp->if_capenable & IFCAP_WOL_MAGIC) == 0) 4005205869Sjfv adapter->wol &= ~E1000_WUFC_MAG; 4006205869Sjfv 4007205869Sjfv if ((ifp->if_capenable & IFCAP_WOL_MCAST) == 0) 4008205869Sjfv adapter->wol &= ~E1000_WUFC_MC; 4009205869Sjfv else { 4010205869Sjfv rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); 4011205869Sjfv rctl |= E1000_RCTL_MPE; 4012205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); 4013205869Sjfv } 4014205869Sjfv 4015205869Sjfv if (adapter->hw.mac.type == e1000_pchlan) { 4016205869Sjfv if (lem_enable_phy_wakeup(adapter)) 4017205869Sjfv return; 4018205869Sjfv } else { 4019205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); 4020205869Sjfv E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol); 4021205869Sjfv } 4022205869Sjfv 4023205869Sjfv 4024205869Sjfv /* Request PME */ 4025205869Sjfv status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2); 4026205869Sjfv status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); 4027205869Sjfv if (ifp->if_capenable & IFCAP_WOL) 4028205869Sjfv status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; 4029205869Sjfv pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2); 4030205869Sjfv 4031205869Sjfv return; 4032205869Sjfv} 4033205869Sjfv 4034205869Sjfv/* 4035205869Sjfv** WOL in the newer chipset interfaces (pchlan) 4036205869Sjfv** require thing to be copied into the phy 4037205869Sjfv*/ 4038205869Sjfvstatic int 4039205869Sjfvlem_enable_phy_wakeup(struct adapter *adapter) 4040205869Sjfv{ 4041205869Sjfv struct e1000_hw *hw = &adapter->hw; 4042205869Sjfv u32 mreg, ret = 0; 4043205869Sjfv u16 preg; 4044205869Sjfv 4045205869Sjfv /* copy MAC RARs to PHY RARs */ 4046205869Sjfv for (int i = 0; i < adapter->hw.mac.rar_entry_count; i++) { 4047205869Sjfv mreg = E1000_READ_REG(hw, E1000_RAL(i)); 4048205869Sjfv e1000_write_phy_reg(hw, BM_RAR_L(i), (u16)(mreg & 0xFFFF)); 4049205869Sjfv e1000_write_phy_reg(hw, BM_RAR_M(i), 4050205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4051205869Sjfv mreg = E1000_READ_REG(hw, E1000_RAH(i)); 4052205869Sjfv e1000_write_phy_reg(hw, BM_RAR_H(i), (u16)(mreg & 0xFFFF)); 4053205869Sjfv e1000_write_phy_reg(hw, BM_RAR_CTRL(i), 4054205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4055205869Sjfv } 4056205869Sjfv 4057205869Sjfv /* copy MAC MTA to PHY MTA */ 4058205869Sjfv for (int i = 0; i < adapter->hw.mac.mta_reg_count; i++) { 4059205869Sjfv mreg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); 4060205869Sjfv e1000_write_phy_reg(hw, BM_MTA(i), (u16)(mreg & 0xFFFF)); 4061205869Sjfv e1000_write_phy_reg(hw, BM_MTA(i) + 1, 4062205869Sjfv (u16)((mreg >> 16) & 0xFFFF)); 4063205869Sjfv } 4064205869Sjfv 4065205869Sjfv /* configure PHY Rx Control register */ 4066205869Sjfv e1000_read_phy_reg(&adapter->hw, BM_RCTL, &preg); 4067205869Sjfv mreg = E1000_READ_REG(hw, E1000_RCTL); 4068205869Sjfv if (mreg & E1000_RCTL_UPE) 4069205869Sjfv preg |= BM_RCTL_UPE; 4070205869Sjfv if (mreg & E1000_RCTL_MPE) 4071205869Sjfv preg |= BM_RCTL_MPE; 4072205869Sjfv preg &= ~(BM_RCTL_MO_MASK); 4073205869Sjfv if (mreg & E1000_RCTL_MO_3) 4074205869Sjfv preg |= (((mreg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) 4075205869Sjfv << BM_RCTL_MO_SHIFT); 4076205869Sjfv if (mreg & E1000_RCTL_BAM) 4077205869Sjfv preg |= BM_RCTL_BAM; 4078205869Sjfv if (mreg & E1000_RCTL_PMCF) 4079205869Sjfv preg |= BM_RCTL_PMCF; 4080205869Sjfv mreg = E1000_READ_REG(hw, E1000_CTRL); 4081205869Sjfv if (mreg & E1000_CTRL_RFCE) 4082205869Sjfv preg |= BM_RCTL_RFCE; 4083205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_RCTL, preg); 4084205869Sjfv 4085205869Sjfv /* enable PHY wakeup in MAC register */ 4086205869Sjfv E1000_WRITE_REG(hw, E1000_WUC, 4087205869Sjfv E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); 4088205869Sjfv E1000_WRITE_REG(hw, E1000_WUFC, adapter->wol); 4089205869Sjfv 4090205869Sjfv /* configure and enable PHY wakeup in PHY registers */ 4091205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_WUFC, adapter->wol); 4092205869Sjfv e1000_write_phy_reg(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); 4093205869Sjfv 4094205869Sjfv /* activate PHY wakeup */ 4095205869Sjfv ret = hw->phy.ops.acquire(hw); 4096205869Sjfv if (ret) { 4097205869Sjfv printf("Could not acquire PHY\n"); 4098205869Sjfv return ret; 4099205869Sjfv } 4100205869Sjfv e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 4101205869Sjfv (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); 4102205869Sjfv ret = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &preg); 4103205869Sjfv if (ret) { 4104205869Sjfv printf("Could not read PHY page 769\n"); 4105205869Sjfv goto out; 4106205869Sjfv } 4107205869Sjfv preg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; 4108205869Sjfv ret = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, preg); 4109205869Sjfv if (ret) 4110205869Sjfv printf("Could not set PHY Host Wakeup bit\n"); 4111205869Sjfvout: 4112205869Sjfv hw->phy.ops.release(hw); 4113205869Sjfv 4114205869Sjfv return ret; 4115205869Sjfv} 4116205869Sjfv 4117206001Smariusstatic void 4118206001Smariuslem_led_func(void *arg, int onoff) 4119206001Smarius{ 4120206001Smarius struct adapter *adapter = arg; 4121205869Sjfv 4122206001Smarius EM_CORE_LOCK(adapter); 4123206001Smarius if (onoff) { 4124206001Smarius e1000_setup_led(&adapter->hw); 4125206001Smarius e1000_led_on(&adapter->hw); 4126206001Smarius } else { 4127206001Smarius e1000_led_off(&adapter->hw); 4128206001Smarius e1000_cleanup_led(&adapter->hw); 4129206001Smarius } 4130206001Smarius EM_CORE_UNLOCK(adapter); 4131206001Smarius} 4132206001Smarius 4133205869Sjfv/********************************************************************* 4134205869Sjfv* 82544 Coexistence issue workaround. 4135205869Sjfv* There are 2 issues. 4136205869Sjfv* 1. Transmit Hang issue. 4137205869Sjfv* To detect this issue, following equation can be used... 4138205869Sjfv* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 4139205869Sjfv* If SUM[3:0] is in between 1 to 4, we will have this issue. 4140205869Sjfv* 4141205869Sjfv* 2. DAC issue. 4142205869Sjfv* To detect this issue, following equation can be used... 4143205869Sjfv* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. 4144205869Sjfv* If SUM[3:0] is in between 9 to c, we will have this issue. 4145205869Sjfv* 4146205869Sjfv* 4147205869Sjfv* WORKAROUND: 4148205869Sjfv* Make sure we do not have ending address 4149205869Sjfv* as 1,2,3,4(Hang) or 9,a,b,c (DAC) 4150205869Sjfv* 4151205869Sjfv*************************************************************************/ 4152205869Sjfvstatic u32 4153205869Sjfvlem_fill_descriptors (bus_addr_t address, u32 length, 4154205869Sjfv PDESC_ARRAY desc_array) 4155205869Sjfv{ 4156205869Sjfv u32 safe_terminator; 4157205869Sjfv 4158205869Sjfv /* Since issue is sensitive to length and address.*/ 4159205869Sjfv /* Let us first check the address...*/ 4160205869Sjfv if (length <= 4) { 4161205869Sjfv desc_array->descriptor[0].address = address; 4162205869Sjfv desc_array->descriptor[0].length = length; 4163205869Sjfv desc_array->elements = 1; 4164205869Sjfv return (desc_array->elements); 4165205869Sjfv } 4166205869Sjfv safe_terminator = (u32)((((u32)address & 0x7) + 4167205869Sjfv (length & 0xF)) & 0xF); 4168205869Sjfv /* if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then return */ 4169205869Sjfv if (safe_terminator == 0 || 4170205869Sjfv (safe_terminator > 4 && 4171205869Sjfv safe_terminator < 9) || 4172205869Sjfv (safe_terminator > 0xC && 4173205869Sjfv safe_terminator <= 0xF)) { 4174205869Sjfv desc_array->descriptor[0].address = address; 4175205869Sjfv desc_array->descriptor[0].length = length; 4176205869Sjfv desc_array->elements = 1; 4177205869Sjfv return (desc_array->elements); 4178205869Sjfv } 4179205869Sjfv 4180205869Sjfv desc_array->descriptor[0].address = address; 4181205869Sjfv desc_array->descriptor[0].length = length - 4; 4182205869Sjfv desc_array->descriptor[1].address = address + (length - 4); 4183205869Sjfv desc_array->descriptor[1].length = 4; 4184205869Sjfv desc_array->elements = 2; 4185205869Sjfv return (desc_array->elements); 4186205869Sjfv} 4187205869Sjfv 4188205869Sjfv/********************************************************************** 4189205869Sjfv * 4190205869Sjfv * Update the board statistics counters. 4191205869Sjfv * 4192205869Sjfv **********************************************************************/ 4193205869Sjfvstatic void 4194205869Sjfvlem_update_stats_counters(struct adapter *adapter) 4195205869Sjfv{ 4196205869Sjfv struct ifnet *ifp; 4197205869Sjfv 4198205869Sjfv if(adapter->hw.phy.media_type == e1000_media_type_copper || 4199205869Sjfv (E1000_READ_REG(&adapter->hw, E1000_STATUS) & E1000_STATUS_LU)) { 4200205869Sjfv adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, E1000_SYMERRS); 4201205869Sjfv adapter->stats.sec += E1000_READ_REG(&adapter->hw, E1000_SEC); 4202205869Sjfv } 4203205869Sjfv adapter->stats.crcerrs += E1000_READ_REG(&adapter->hw, E1000_CRCERRS); 4204205869Sjfv adapter->stats.mpc += E1000_READ_REG(&adapter->hw, E1000_MPC); 4205205869Sjfv adapter->stats.scc += E1000_READ_REG(&adapter->hw, E1000_SCC); 4206205869Sjfv adapter->stats.ecol += E1000_READ_REG(&adapter->hw, E1000_ECOL); 4207205869Sjfv 4208205869Sjfv adapter->stats.mcc += E1000_READ_REG(&adapter->hw, E1000_MCC); 4209205869Sjfv adapter->stats.latecol += E1000_READ_REG(&adapter->hw, E1000_LATECOL); 4210205869Sjfv adapter->stats.colc += E1000_READ_REG(&adapter->hw, E1000_COLC); 4211205869Sjfv adapter->stats.dc += E1000_READ_REG(&adapter->hw, E1000_DC); 4212205869Sjfv adapter->stats.rlec += E1000_READ_REG(&adapter->hw, E1000_RLEC); 4213205869Sjfv adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, E1000_XONRXC); 4214205869Sjfv adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, E1000_XONTXC); 4215205869Sjfv adapter->stats.xoffrxc += E1000_READ_REG(&adapter->hw, E1000_XOFFRXC); 4216205869Sjfv adapter->stats.xofftxc += E1000_READ_REG(&adapter->hw, E1000_XOFFTXC); 4217205869Sjfv adapter->stats.fcruc += E1000_READ_REG(&adapter->hw, E1000_FCRUC); 4218205869Sjfv adapter->stats.prc64 += E1000_READ_REG(&adapter->hw, E1000_PRC64); 4219205869Sjfv adapter->stats.prc127 += E1000_READ_REG(&adapter->hw, E1000_PRC127); 4220205869Sjfv adapter->stats.prc255 += E1000_READ_REG(&adapter->hw, E1000_PRC255); 4221205869Sjfv adapter->stats.prc511 += E1000_READ_REG(&adapter->hw, E1000_PRC511); 4222205869Sjfv adapter->stats.prc1023 += E1000_READ_REG(&adapter->hw, E1000_PRC1023); 4223205869Sjfv adapter->stats.prc1522 += E1000_READ_REG(&adapter->hw, E1000_PRC1522); 4224205869Sjfv adapter->stats.gprc += E1000_READ_REG(&adapter->hw, E1000_GPRC); 4225205869Sjfv adapter->stats.bprc += E1000_READ_REG(&adapter->hw, E1000_BPRC); 4226205869Sjfv adapter->stats.mprc += E1000_READ_REG(&adapter->hw, E1000_MPRC); 4227205869Sjfv adapter->stats.gptc += E1000_READ_REG(&adapter->hw, E1000_GPTC); 4228205869Sjfv 4229205869Sjfv /* For the 64-bit byte counters the low dword must be read first. */ 4230205869Sjfv /* Both registers clear on the read of the high dword */ 4231205869Sjfv 4232212902Sjhb adapter->stats.gorc += E1000_READ_REG(&adapter->hw, E1000_GORCL) + 4233212902Sjhb ((u64)E1000_READ_REG(&adapter->hw, E1000_GORCH) << 32); 4234212902Sjhb adapter->stats.gotc += E1000_READ_REG(&adapter->hw, E1000_GOTCL) + 4235212902Sjhb ((u64)E1000_READ_REG(&adapter->hw, E1000_GOTCH) << 32); 4236205869Sjfv 4237205869Sjfv adapter->stats.rnbc += E1000_READ_REG(&adapter->hw, E1000_RNBC); 4238205869Sjfv adapter->stats.ruc += E1000_READ_REG(&adapter->hw, E1000_RUC); 4239205869Sjfv adapter->stats.rfc += E1000_READ_REG(&adapter->hw, E1000_RFC); 4240205869Sjfv adapter->stats.roc += E1000_READ_REG(&adapter->hw, E1000_ROC); 4241205869Sjfv adapter->stats.rjc += E1000_READ_REG(&adapter->hw, E1000_RJC); 4242205869Sjfv 4243205869Sjfv adapter->stats.tor += E1000_READ_REG(&adapter->hw, E1000_TORH); 4244205869Sjfv adapter->stats.tot += E1000_READ_REG(&adapter->hw, E1000_TOTH); 4245205869Sjfv 4246205869Sjfv adapter->stats.tpr += E1000_READ_REG(&adapter->hw, E1000_TPR); 4247205869Sjfv adapter->stats.tpt += E1000_READ_REG(&adapter->hw, E1000_TPT); 4248205869Sjfv adapter->stats.ptc64 += E1000_READ_REG(&adapter->hw, E1000_PTC64); 4249205869Sjfv adapter->stats.ptc127 += E1000_READ_REG(&adapter->hw, E1000_PTC127); 4250205869Sjfv adapter->stats.ptc255 += E1000_READ_REG(&adapter->hw, E1000_PTC255); 4251205869Sjfv adapter->stats.ptc511 += E1000_READ_REG(&adapter->hw, E1000_PTC511); 4252205869Sjfv adapter->stats.ptc1023 += E1000_READ_REG(&adapter->hw, E1000_PTC1023); 4253205869Sjfv adapter->stats.ptc1522 += E1000_READ_REG(&adapter->hw, E1000_PTC1522); 4254205869Sjfv adapter->stats.mptc += E1000_READ_REG(&adapter->hw, E1000_MPTC); 4255205869Sjfv adapter->stats.bptc += E1000_READ_REG(&adapter->hw, E1000_BPTC); 4256205869Sjfv 4257205869Sjfv if (adapter->hw.mac.type >= e1000_82543) { 4258205869Sjfv adapter->stats.algnerrc += 4259205869Sjfv E1000_READ_REG(&adapter->hw, E1000_ALGNERRC); 4260205869Sjfv adapter->stats.rxerrc += 4261205869Sjfv E1000_READ_REG(&adapter->hw, E1000_RXERRC); 4262205869Sjfv adapter->stats.tncrs += 4263205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TNCRS); 4264205869Sjfv adapter->stats.cexterr += 4265205869Sjfv E1000_READ_REG(&adapter->hw, E1000_CEXTERR); 4266205869Sjfv adapter->stats.tsctc += 4267205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TSCTC); 4268205869Sjfv adapter->stats.tsctfc += 4269205869Sjfv E1000_READ_REG(&adapter->hw, E1000_TSCTFC); 4270205869Sjfv } 4271205869Sjfv ifp = adapter->ifp; 4272205869Sjfv 4273205869Sjfv ifp->if_collisions = adapter->stats.colc; 4274205869Sjfv 4275205869Sjfv /* Rx Errors */ 4276205869Sjfv ifp->if_ierrors = adapter->dropped_pkts + adapter->stats.rxerrc + 4277205869Sjfv adapter->stats.crcerrs + adapter->stats.algnerrc + 4278205869Sjfv adapter->stats.ruc + adapter->stats.roc + 4279205869Sjfv adapter->stats.mpc + adapter->stats.cexterr; 4280205869Sjfv 4281205869Sjfv /* Tx Errors */ 4282205869Sjfv ifp->if_oerrors = adapter->stats.ecol + 4283205869Sjfv adapter->stats.latecol + adapter->watchdog_events; 4284205869Sjfv} 4285205869Sjfv 4286212902Sjhb/* Export a single 32-bit register via a read-only sysctl. */ 4287212902Sjhbstatic int 4288212902Sjhblem_sysctl_reg_handler(SYSCTL_HANDLER_ARGS) 4289205869Sjfv{ 4290212902Sjhb struct adapter *adapter; 4291212902Sjhb u_int val; 4292205869Sjfv 4293212902Sjhb adapter = oidp->oid_arg1; 4294212902Sjhb val = E1000_READ_REG(&adapter->hw, oidp->oid_arg2); 4295212902Sjhb return (sysctl_handle_int(oidp, &val, 0, req)); 4296205869Sjfv} 4297205869Sjfv 4298212902Sjhb/* 4299212902Sjhb * Add sysctl variables, one per statistic, to the system. 4300212902Sjhb */ 4301205869Sjfvstatic void 4302212902Sjhblem_add_hw_stats(struct adapter *adapter) 4303205869Sjfv{ 4304205869Sjfv device_t dev = adapter->dev; 4305205869Sjfv 4306212902Sjhb struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 4307212902Sjhb struct sysctl_oid *tree = device_get_sysctl_tree(dev); 4308212902Sjhb struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 4309212902Sjhb struct e1000_hw_stats *stats = &adapter->stats; 4310212902Sjhb 4311212902Sjhb struct sysctl_oid *stat_node; 4312212902Sjhb struct sysctl_oid_list *stat_list; 4313212902Sjhb 4314212902Sjhb /* Driver Statistics */ 4315212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_alloc_fail", 4316212902Sjhb CTLFLAG_RD, &adapter->mbuf_alloc_failed, 4317212902Sjhb "Std mbuf failed"); 4318212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail", 4319212902Sjhb CTLFLAG_RD, &adapter->mbuf_cluster_failed, 4320212902Sjhb "Std mbuf cluster failed"); 4321212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped", 4322212902Sjhb CTLFLAG_RD, &adapter->dropped_pkts, 4323212902Sjhb "Driver dropped packets"); 4324212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail", 4325212902Sjhb CTLFLAG_RD, &adapter->no_tx_dma_setup, 4326212902Sjhb "Driver tx dma failure in xmit"); 4327212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_desc_fail1", 4328212902Sjhb CTLFLAG_RD, &adapter->no_tx_desc_avail1, 4329212902Sjhb "Not enough tx descriptors failure in xmit"); 4330212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_desc_fail2", 4331212902Sjhb CTLFLAG_RD, &adapter->no_tx_desc_avail2, 4332212902Sjhb "Not enough tx descriptors failure in xmit"); 4333212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns", 4334212902Sjhb CTLFLAG_RD, &adapter->rx_overruns, 4335212902Sjhb "RX overruns"); 4336212902Sjhb SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_timeouts", 4337212902Sjhb CTLFLAG_RD, &adapter->watchdog_events, 4338212902Sjhb "Watchdog timeouts"); 4339212902Sjhb 4340212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "device_control", 4341217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_CTRL, 4342212902Sjhb lem_sysctl_reg_handler, "IU", 4343212902Sjhb "Device Control Register"); 4344212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_control", 4345217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RCTL, 4346212902Sjhb lem_sysctl_reg_handler, "IU", 4347212902Sjhb "Receiver Control Register"); 4348212902Sjhb SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_high_water", 4349212902Sjhb CTLFLAG_RD, &adapter->hw.fc.high_water, 0, 4350212902Sjhb "Flow Control High Watermark"); 4351212902Sjhb SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_low_water", 4352212902Sjhb CTLFLAG_RD, &adapter->hw.fc.low_water, 0, 4353212902Sjhb "Flow Control Low Watermark"); 4354217318Smdf SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_workaround", 4355212902Sjhb CTLFLAG_RD, &adapter->tx_fifo_wrk_cnt, 4356212902Sjhb "TX FIFO workaround events"); 4357217318Smdf SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_reset", 4358212902Sjhb CTLFLAG_RD, &adapter->tx_fifo_reset_cnt, 4359212902Sjhb "TX FIFO resets"); 4360212902Sjhb 4361212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_head", 4362217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDH(0), 4363212902Sjhb lem_sysctl_reg_handler, "IU", 4364212902Sjhb "Transmit Descriptor Head"); 4365212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_tail", 4366217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDT(0), 4367212902Sjhb lem_sysctl_reg_handler, "IU", 4368212902Sjhb "Transmit Descriptor Tail"); 4369212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_head", 4370217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDH(0), 4371212902Sjhb lem_sysctl_reg_handler, "IU", 4372212902Sjhb "Receive Descriptor Head"); 4373212902Sjhb SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_tail", 4374217556Smdf CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDT(0), 4375212902Sjhb lem_sysctl_reg_handler, "IU", 4376212902Sjhb "Receive Descriptor Tail"); 4377212902Sjhb 4378212902Sjhb 4379212902Sjhb /* MAC stats get their own sub node */ 4380212902Sjhb 4381212902Sjhb stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats", 4382212902Sjhb CTLFLAG_RD, NULL, "Statistics"); 4383212902Sjhb stat_list = SYSCTL_CHILDREN(stat_node); 4384212902Sjhb 4385217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "excess_coll", 4386212902Sjhb CTLFLAG_RD, &stats->ecol, 4387212902Sjhb "Excessive collisions"); 4388217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "single_coll", 4389212902Sjhb CTLFLAG_RD, &stats->scc, 4390212902Sjhb "Single collisions"); 4391217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "multiple_coll", 4392212902Sjhb CTLFLAG_RD, &stats->mcc, 4393212902Sjhb "Multiple collisions"); 4394217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "late_coll", 4395212902Sjhb CTLFLAG_RD, &stats->latecol, 4396212902Sjhb "Late collisions"); 4397217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "collision_count", 4398212902Sjhb CTLFLAG_RD, &stats->colc, 4399212902Sjhb "Collision Count"); 4400217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "symbol_errors", 4401212902Sjhb CTLFLAG_RD, &adapter->stats.symerrs, 4402212902Sjhb "Symbol Errors"); 4403217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "sequence_errors", 4404212902Sjhb CTLFLAG_RD, &adapter->stats.sec, 4405212902Sjhb "Sequence Errors"); 4406217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "defer_count", 4407212902Sjhb CTLFLAG_RD, &adapter->stats.dc, 4408212902Sjhb "Defer Count"); 4409217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "missed_packets", 4410212902Sjhb CTLFLAG_RD, &adapter->stats.mpc, 4411212902Sjhb "Missed Packets"); 4412217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_no_buff", 4413212902Sjhb CTLFLAG_RD, &adapter->stats.rnbc, 4414212902Sjhb "Receive No Buffers"); 4415217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersize", 4416212902Sjhb CTLFLAG_RD, &adapter->stats.ruc, 4417212902Sjhb "Receive Undersize"); 4418217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented", 4419212902Sjhb CTLFLAG_RD, &adapter->stats.rfc, 4420212902Sjhb "Fragmented Packets Received "); 4421217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversize", 4422212902Sjhb CTLFLAG_RD, &adapter->stats.roc, 4423212902Sjhb "Oversized Packets Received"); 4424217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabber", 4425212902Sjhb CTLFLAG_RD, &adapter->stats.rjc, 4426212902Sjhb "Recevied Jabber"); 4427217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_errs", 4428212902Sjhb CTLFLAG_RD, &adapter->stats.rxerrc, 4429212902Sjhb "Receive Errors"); 4430217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs", 4431212902Sjhb CTLFLAG_RD, &adapter->stats.crcerrs, 4432212902Sjhb "CRC errors"); 4433217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "alignment_errs", 4434212902Sjhb CTLFLAG_RD, &adapter->stats.algnerrc, 4435212902Sjhb "Alignment Errors"); 4436217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs", 4437212902Sjhb CTLFLAG_RD, &adapter->stats.cexterr, 4438212902Sjhb "Collision/Carrier extension errors"); 4439217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd", 4440212902Sjhb CTLFLAG_RD, &adapter->stats.xonrxc, 4441212902Sjhb "XON Received"); 4442217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd", 4443212902Sjhb CTLFLAG_RD, &adapter->stats.xontxc, 4444212902Sjhb "XON Transmitted"); 4445217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd", 4446212902Sjhb CTLFLAG_RD, &adapter->stats.xoffrxc, 4447212902Sjhb "XOFF Received"); 4448217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd", 4449212902Sjhb CTLFLAG_RD, &adapter->stats.xofftxc, 4450212902Sjhb "XOFF Transmitted"); 4451212902Sjhb 4452212902Sjhb /* Packet Reception Stats */ 4453217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd", 4454212902Sjhb CTLFLAG_RD, &adapter->stats.tpr, 4455212902Sjhb "Total Packets Received "); 4456217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd", 4457212902Sjhb CTLFLAG_RD, &adapter->stats.gprc, 4458212902Sjhb "Good Packets Received"); 4459217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd", 4460212902Sjhb CTLFLAG_RD, &adapter->stats.bprc, 4461212902Sjhb "Broadcast Packets Received"); 4462217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd", 4463212902Sjhb CTLFLAG_RD, &adapter->stats.mprc, 4464212902Sjhb "Multicast Packets Received"); 4465217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64", 4466212902Sjhb CTLFLAG_RD, &adapter->stats.prc64, 4467212902Sjhb "64 byte frames received "); 4468217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127", 4469212902Sjhb CTLFLAG_RD, &adapter->stats.prc127, 4470212902Sjhb "65-127 byte frames received"); 4471217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255", 4472212902Sjhb CTLFLAG_RD, &adapter->stats.prc255, 4473212902Sjhb "128-255 byte frames received"); 4474217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511", 4475212902Sjhb CTLFLAG_RD, &adapter->stats.prc511, 4476212902Sjhb "256-511 byte frames received"); 4477217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023", 4478212902Sjhb CTLFLAG_RD, &adapter->stats.prc1023, 4479212902Sjhb "512-1023 byte frames received"); 4480217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522", 4481212902Sjhb CTLFLAG_RD, &adapter->stats.prc1522, 4482212902Sjhb "1023-1522 byte frames received"); 4483217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd", 4484212902Sjhb CTLFLAG_RD, &adapter->stats.gorc, 4485212902Sjhb "Good Octets Received"); 4486212902Sjhb 4487212902Sjhb /* Packet Transmission Stats */ 4488217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 4489212902Sjhb CTLFLAG_RD, &adapter->stats.gotc, 4490212902Sjhb "Good Octets Transmitted"); 4491217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd", 4492212902Sjhb CTLFLAG_RD, &adapter->stats.tpt, 4493212902Sjhb "Total Packets Transmitted"); 4494217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 4495212902Sjhb CTLFLAG_RD, &adapter->stats.gptc, 4496212902Sjhb "Good Packets Transmitted"); 4497217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 4498212902Sjhb CTLFLAG_RD, &adapter->stats.bptc, 4499212902Sjhb "Broadcast Packets Transmitted"); 4500217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 4501212902Sjhb CTLFLAG_RD, &adapter->stats.mptc, 4502212902Sjhb "Multicast Packets Transmitted"); 4503217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64", 4504212902Sjhb CTLFLAG_RD, &adapter->stats.ptc64, 4505212902Sjhb "64 byte frames transmitted "); 4506217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127", 4507212902Sjhb CTLFLAG_RD, &adapter->stats.ptc127, 4508212902Sjhb "65-127 byte frames transmitted"); 4509217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255", 4510212902Sjhb CTLFLAG_RD, &adapter->stats.ptc255, 4511212902Sjhb "128-255 byte frames transmitted"); 4512217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511", 4513212902Sjhb CTLFLAG_RD, &adapter->stats.ptc511, 4514212902Sjhb "256-511 byte frames transmitted"); 4515217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023", 4516212902Sjhb CTLFLAG_RD, &adapter->stats.ptc1023, 4517212902Sjhb "512-1023 byte frames transmitted"); 4518217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522", 4519212902Sjhb CTLFLAG_RD, &adapter->stats.ptc1522, 4520212902Sjhb "1024-1522 byte frames transmitted"); 4521217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_txd", 4522212902Sjhb CTLFLAG_RD, &adapter->stats.tsctc, 4523212902Sjhb "TSO Contexts Transmitted"); 4524217318Smdf SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail", 4525212902Sjhb CTLFLAG_RD, &adapter->stats.tsctfc, 4526212902Sjhb "TSO Contexts Failed"); 4527205869Sjfv} 4528205869Sjfv 4529205869Sjfv/********************************************************************** 4530205869Sjfv * 4531205869Sjfv * This routine provides a way to dump out the adapter eeprom, 4532205869Sjfv * often a useful debug/service tool. This only dumps the first 4533205869Sjfv * 32 words, stuff that matters is in that extent. 4534205869Sjfv * 4535205869Sjfv **********************************************************************/ 4536205869Sjfv 4537205869Sjfvstatic int 4538212902Sjhblem_sysctl_nvm_info(SYSCTL_HANDLER_ARGS) 4539205869Sjfv{ 4540205869Sjfv struct adapter *adapter; 4541205869Sjfv int error; 4542205869Sjfv int result; 4543205869Sjfv 4544205869Sjfv result = -1; 4545205869Sjfv error = sysctl_handle_int(oidp, &result, 0, req); 4546205869Sjfv 4547205869Sjfv if (error || !req->newptr) 4548205869Sjfv return (error); 4549205869Sjfv 4550205869Sjfv /* 4551205869Sjfv * This value will cause a hex dump of the 4552205869Sjfv * first 32 16-bit words of the EEPROM to 4553205869Sjfv * the screen. 4554205869Sjfv */ 4555212902Sjhb if (result == 1) { 4556205869Sjfv adapter = (struct adapter *)arg1; 4557205869Sjfv lem_print_nvm_info(adapter); 4558205869Sjfv } 4559205869Sjfv 4560205869Sjfv return (error); 4561205869Sjfv} 4562205869Sjfv 4563212902Sjhbstatic void 4564212902Sjhblem_print_nvm_info(struct adapter *adapter) 4565205869Sjfv{ 4566212902Sjhb u16 eeprom_data; 4567212902Sjhb int i, j, row = 0; 4568205869Sjfv 4569212902Sjhb /* Its a bit crude, but it gets the job done */ 4570212902Sjhb printf("\nInterface EEPROM Dump:\n"); 4571212902Sjhb printf("Offset\n0x0000 "); 4572212902Sjhb for (i = 0, j = 0; i < 32; i++, j++) { 4573212902Sjhb if (j == 8) { /* Make the offset block */ 4574212902Sjhb j = 0; ++row; 4575212902Sjhb printf("\n0x00%x0 ",row); 4576212902Sjhb } 4577212902Sjhb e1000_read_nvm(&adapter->hw, i, 1, &eeprom_data); 4578212902Sjhb printf("%04x ", eeprom_data); 4579205869Sjfv } 4580212902Sjhb printf("\n"); 4581205869Sjfv} 4582205869Sjfv 4583205869Sjfvstatic int 4584205869Sjfvlem_sysctl_int_delay(SYSCTL_HANDLER_ARGS) 4585205869Sjfv{ 4586205869Sjfv struct em_int_delay_info *info; 4587205869Sjfv struct adapter *adapter; 4588205869Sjfv u32 regval; 4589205869Sjfv int error; 4590205869Sjfv int usecs; 4591205869Sjfv int ticks; 4592205869Sjfv 4593205869Sjfv info = (struct em_int_delay_info *)arg1; 4594205869Sjfv usecs = info->value; 4595205869Sjfv error = sysctl_handle_int(oidp, &usecs, 0, req); 4596205869Sjfv if (error != 0 || req->newptr == NULL) 4597205869Sjfv return (error); 4598205869Sjfv if (usecs < 0 || usecs > EM_TICKS_TO_USECS(65535)) 4599205869Sjfv return (EINVAL); 4600205869Sjfv info->value = usecs; 4601205869Sjfv ticks = EM_USECS_TO_TICKS(usecs); 4602250414Sluigi if (info->offset == E1000_ITR) /* units are 256ns here */ 4603250414Sluigi ticks *= 4; 4604205869Sjfv 4605205869Sjfv adapter = info->adapter; 4606205869Sjfv 4607205869Sjfv EM_CORE_LOCK(adapter); 4608205869Sjfv regval = E1000_READ_OFFSET(&adapter->hw, info->offset); 4609205869Sjfv regval = (regval & ~0xffff) | (ticks & 0xffff); 4610205869Sjfv /* Handle a few special cases. */ 4611205869Sjfv switch (info->offset) { 4612205869Sjfv case E1000_RDTR: 4613205869Sjfv break; 4614205869Sjfv case E1000_TIDV: 4615205869Sjfv if (ticks == 0) { 4616205869Sjfv adapter->txd_cmd &= ~E1000_TXD_CMD_IDE; 4617205869Sjfv /* Don't write 0 into the TIDV register. */ 4618205869Sjfv regval++; 4619205869Sjfv } else 4620205869Sjfv adapter->txd_cmd |= E1000_TXD_CMD_IDE; 4621205869Sjfv break; 4622205869Sjfv } 4623205869Sjfv E1000_WRITE_OFFSET(&adapter->hw, info->offset, regval); 4624205869Sjfv EM_CORE_UNLOCK(adapter); 4625205869Sjfv return (0); 4626205869Sjfv} 4627205869Sjfv 4628205869Sjfvstatic void 4629205869Sjfvlem_add_int_delay_sysctl(struct adapter *adapter, const char *name, 4630205869Sjfv const char *description, struct em_int_delay_info *info, 4631205869Sjfv int offset, int value) 4632205869Sjfv{ 4633205869Sjfv info->adapter = adapter; 4634205869Sjfv info->offset = offset; 4635205869Sjfv info->value = value; 4636205869Sjfv SYSCTL_ADD_PROC(device_get_sysctl_ctx(adapter->dev), 4637205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4638205869Sjfv OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, 4639205869Sjfv info, 0, lem_sysctl_int_delay, "I", description); 4640205869Sjfv} 4641205869Sjfv 4642214646Sjfvstatic void 4643214646Sjfvlem_set_flow_cntrl(struct adapter *adapter, const char *name, 4644214646Sjfv const char *description, int *limit, int value) 4645214646Sjfv{ 4646214646Sjfv *limit = value; 4647214646Sjfv SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 4648214646Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4649214646Sjfv OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); 4650214646Sjfv} 4651214646Sjfv 4652205869Sjfvstatic void 4653205869Sjfvlem_add_rx_process_limit(struct adapter *adapter, const char *name, 4654205869Sjfv const char *description, int *limit, int value) 4655205869Sjfv{ 4656205869Sjfv *limit = value; 4657205869Sjfv SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev), 4658205869Sjfv SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), 4659205869Sjfv OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); 4660205869Sjfv} 4661