if_ixgb.c revision 246128
1139749Simp/******************************************************************************* 2129794Stackerman 3129794StackermanCopyright (c) 2001-2004, Intel Corporation 4129794StackermanAll rights reserved. 5129794Stackerman 6129794StackermanRedistribution and use in source and binary forms, with or without 7129794Stackermanmodification, are permitted provided that the following conditions are met: 8129794Stackerman 9129794Stackerman 1. Redistributions of source code must retain the above copyright notice, 10129794Stackerman this list of conditions and the following disclaimer. 11129794Stackerman 12129794Stackerman 2. Redistributions in binary form must reproduce the above copyright 13129794Stackerman notice, this list of conditions and the following disclaimer in the 14129794Stackerman documentation and/or other materials provided with the distribution. 15129794Stackerman 16129794Stackerman 3. Neither the name of the Intel Corporation nor the names of its 17129794Stackerman contributors may be used to endorse or promote products derived from 18129794Stackerman this software without specific prior written permission. 19129794Stackerman 20129794StackermanTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21129794StackermanAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22129794StackermanIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23129794StackermanARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24129794StackermanLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25129794StackermanCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26129794StackermanSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27129794StackermanINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28129794StackermanCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29129794StackermanARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30129794StackermanPOSSIBILITY OF SUCH DAMAGE. 31129794Stackerman 32129794Stackerman***************************************************************************/ 33129794Stackerman 34129794Stackerman/*$FreeBSD: head/sys/dev/ixgb/if_ixgb.c 246128 2013-01-30 18:01:20Z sbz $*/ 35129794Stackerman 36150968Sglebius#ifdef HAVE_KERNEL_OPTION_HEADERS 37150968Sglebius#include "opt_device_polling.h" 38150968Sglebius#endif 39150968Sglebius 40129794Stackerman#include <dev/ixgb/if_ixgb.h> 41129794Stackerman 42129794Stackerman/********************************************************************* 43129794Stackerman * Set this to one to display debug statistics 44129794Stackerman *********************************************************************/ 45129794Stackermanint ixgb_display_debug_stats = 0; 46129794Stackerman 47129794Stackerman/********************************************************************* 48129794Stackerman * Linked list of board private structures for all NICs found 49129794Stackerman *********************************************************************/ 50129794Stackerman 51129794Stackermanstruct adapter *ixgb_adapter_list = NULL; 52129794Stackerman 53129794Stackerman 54129794Stackerman 55129794Stackerman/********************************************************************* 56129794Stackerman * Driver version 57129794Stackerman *********************************************************************/ 58129794Stackerman 59129794Stackermanchar ixgb_driver_version[] = "1.0.6"; 60129794Stackermanchar ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation."; 61129794Stackerman 62129794Stackerman/********************************************************************* 63129794Stackerman * PCI Device ID Table 64129794Stackerman * 65129794Stackerman * Used by probe to select devices to load on 66129794Stackerman * Last field stores an index into ixgb_strings 67129794Stackerman * Last entry must be all 0s 68129794Stackerman * 69129794Stackerman * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 70129794Stackerman *********************************************************************/ 71129794Stackerman 72129794Stackermanstatic ixgb_vendor_info_t ixgb_vendor_info_array[] = 73129794Stackerman{ 74129794Stackerman /* Intel(R) PRO/10000 Network Connection */ 75129794Stackerman {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX, PCI_ANY_ID, PCI_ANY_ID, 0}, 76129794Stackerman {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR, PCI_ANY_ID, PCI_ANY_ID, 0}, 77129794Stackerman /* required last entry */ 78129794Stackerman {0, 0, 0, 0, 0} 79129794Stackerman}; 80129794Stackerman 81129794Stackerman/********************************************************************* 82129794Stackerman * Table of branding strings for all supported NICs. 83129794Stackerman *********************************************************************/ 84129794Stackerman 85129794Stackermanstatic char *ixgb_strings[] = { 86129794Stackerman "Intel(R) PRO/10GbE Network Driver" 87129794Stackerman}; 88129794Stackerman 89129794Stackerman/********************************************************************* 90129794Stackerman * Function prototypes 91129794Stackerman *********************************************************************/ 92129794Stackermanstatic int ixgb_probe(device_t); 93129794Stackermanstatic int ixgb_attach(device_t); 94129794Stackermanstatic int ixgb_detach(device_t); 95129794Stackermanstatic int ixgb_shutdown(device_t); 96129794Stackermanstatic void ixgb_intr(void *); 97129794Stackermanstatic void ixgb_start(struct ifnet *); 98144651Salcstatic void ixgb_start_locked(struct ifnet *); 99129794Stackermanstatic int ixgb_ioctl(struct ifnet *, IOCTL_CMD_TYPE, caddr_t); 100199539Sjhbstatic void ixgb_watchdog(struct adapter *); 101129794Stackermanstatic void ixgb_init(void *); 102144651Salcstatic void ixgb_init_locked(struct adapter *); 103129794Stackermanstatic void ixgb_stop(void *); 104129794Stackermanstatic void ixgb_media_status(struct ifnet *, struct ifmediareq *); 105129794Stackermanstatic int ixgb_media_change(struct ifnet *); 106129794Stackermanstatic void ixgb_identify_hardware(struct adapter *); 107129794Stackermanstatic int ixgb_allocate_pci_resources(struct adapter *); 108129794Stackermanstatic void ixgb_free_pci_resources(struct adapter *); 109129794Stackermanstatic void ixgb_local_timer(void *); 110129794Stackermanstatic int ixgb_hardware_init(struct adapter *); 111211907Syongaristatic int ixgb_setup_interface(device_t, struct adapter *); 112129794Stackermanstatic int ixgb_setup_transmit_structures(struct adapter *); 113129794Stackermanstatic void ixgb_initialize_transmit_unit(struct adapter *); 114129794Stackermanstatic int ixgb_setup_receive_structures(struct adapter *); 115129794Stackermanstatic void ixgb_initialize_receive_unit(struct adapter *); 116129794Stackermanstatic void ixgb_enable_intr(struct adapter *); 117129794Stackermanstatic void ixgb_disable_intr(struct adapter *); 118129794Stackermanstatic void ixgb_free_transmit_structures(struct adapter *); 119129794Stackermanstatic void ixgb_free_receive_structures(struct adapter *); 120129794Stackermanstatic void ixgb_update_stats_counters(struct adapter *); 121129794Stackermanstatic void ixgb_clean_transmit_interrupts(struct adapter *); 122129794Stackermanstatic int ixgb_allocate_receive_structures(struct adapter *); 123129794Stackermanstatic int ixgb_allocate_transmit_structures(struct adapter *); 124193096Sattiliostatic int ixgb_process_receive_interrupts(struct adapter *, int); 125129794Stackermanstatic void 126129794Stackermanixgb_receive_checksum(struct adapter *, 127129794Stackerman struct ixgb_rx_desc * rx_desc, 128129794Stackerman struct mbuf *); 129129794Stackermanstatic void 130129794Stackermanixgb_transmit_checksum_setup(struct adapter *, 131129794Stackerman struct mbuf *, 132129794Stackerman u_int8_t *); 133129794Stackermanstatic void ixgb_set_promisc(struct adapter *); 134129794Stackermanstatic void ixgb_disable_promisc(struct adapter *); 135129794Stackermanstatic void ixgb_set_multi(struct adapter *); 136129794Stackermanstatic void ixgb_print_hw_stats(struct adapter *); 137129794Stackermanstatic void ixgb_print_link_status(struct adapter *); 138129794Stackermanstatic int 139129794Stackermanixgb_get_buf(int i, struct adapter *, 140129794Stackerman struct mbuf *); 141129794Stackermanstatic void ixgb_enable_vlans(struct adapter * adapter); 142129794Stackermanstatic int ixgb_encap(struct adapter * adapter, struct mbuf * m_head); 143129794Stackermanstatic int ixgb_sysctl_stats(SYSCTL_HANDLER_ARGS); 144129794Stackermanstatic int 145129794Stackermanixgb_dma_malloc(struct adapter *, bus_size_t, 146129794Stackerman struct ixgb_dma_alloc *, int); 147129794Stackermanstatic void ixgb_dma_free(struct adapter *, struct ixgb_dma_alloc *); 148150789Sglebius#ifdef DEVICE_POLLING 149150789Sglebiusstatic poll_handler_t ixgb_poll; 150150789Sglebius#endif 151129794Stackerman 152129794Stackerman/********************************************************************* 153129794Stackerman * FreeBSD Device Interface Entry Points 154129794Stackerman *********************************************************************/ 155129794Stackerman 156129794Stackermanstatic device_method_t ixgb_methods[] = { 157129794Stackerman /* Device interface */ 158129794Stackerman DEVMETHOD(device_probe, ixgb_probe), 159129794Stackerman DEVMETHOD(device_attach, ixgb_attach), 160129794Stackerman DEVMETHOD(device_detach, ixgb_detach), 161129794Stackerman DEVMETHOD(device_shutdown, ixgb_shutdown), 162246128Ssbz 163246128Ssbz DEVMETHOD_END 164129794Stackerman}; 165129794Stackerman 166129794Stackermanstatic driver_t ixgb_driver = { 167129794Stackerman "ixgb", ixgb_methods, sizeof(struct adapter), 168129794Stackerman}; 169129794Stackerman 170129794Stackermanstatic devclass_t ixgb_devclass; 171192147SimpDRIVER_MODULE(ixgb, pci, ixgb_driver, ixgb_devclass, 0, 0); 172129794Stackerman 173192147SimpMODULE_DEPEND(ixgb, pci, 1, 1, 1); 174192147SimpMODULE_DEPEND(ixgb, ether, 1, 1, 1); 175144183Smux 176129794Stackerman/* some defines for controlling descriptor fetches in h/w */ 177129794Stackerman#define RXDCTL_PTHRESH_DEFAULT 128 /* chip considers prefech below this */ 178129794Stackerman#define RXDCTL_HTHRESH_DEFAULT 16 /* chip will only prefetch if tail is 179129794Stackerman * pushed this many descriptors from 180129794Stackerman * head */ 181129794Stackerman#define RXDCTL_WTHRESH_DEFAULT 0 /* chip writes back at this many or RXT0 */ 182129794Stackerman 183129794Stackerman 184129794Stackerman/********************************************************************* 185129794Stackerman * Device identification routine 186129794Stackerman * 187129794Stackerman * ixgb_probe determines if the driver should be loaded on 188129794Stackerman * adapter based on PCI vendor/device id of the adapter. 189129794Stackerman * 190129794Stackerman * return 0 on success, positive on failure 191129794Stackerman *********************************************************************/ 192129794Stackerman 193129794Stackermanstatic int 194129794Stackermanixgb_probe(device_t dev) 195129794Stackerman{ 196129794Stackerman ixgb_vendor_info_t *ent; 197129794Stackerman 198129794Stackerman u_int16_t pci_vendor_id = 0; 199129794Stackerman u_int16_t pci_device_id = 0; 200129794Stackerman u_int16_t pci_subvendor_id = 0; 201129794Stackerman u_int16_t pci_subdevice_id = 0; 202129794Stackerman char adapter_name[60]; 203129794Stackerman 204129794Stackerman INIT_DEBUGOUT("ixgb_probe: begin"); 205129794Stackerman 206129794Stackerman pci_vendor_id = pci_get_vendor(dev); 207129794Stackerman if (pci_vendor_id != IXGB_VENDOR_ID) 208129794Stackerman return (ENXIO); 209129794Stackerman 210129794Stackerman pci_device_id = pci_get_device(dev); 211129794Stackerman pci_subvendor_id = pci_get_subvendor(dev); 212129794Stackerman pci_subdevice_id = pci_get_subdevice(dev); 213129794Stackerman 214129794Stackerman ent = ixgb_vendor_info_array; 215129794Stackerman while (ent->vendor_id != 0) { 216129794Stackerman if ((pci_vendor_id == ent->vendor_id) && 217129794Stackerman (pci_device_id == ent->device_id) && 218129794Stackerman 219129794Stackerman ((pci_subvendor_id == ent->subvendor_id) || 220129794Stackerman (ent->subvendor_id == PCI_ANY_ID)) && 221129794Stackerman 222129794Stackerman ((pci_subdevice_id == ent->subdevice_id) || 223129794Stackerman (ent->subdevice_id == PCI_ANY_ID))) { 224129794Stackerman sprintf(adapter_name, "%s, Version - %s", 225129794Stackerman ixgb_strings[ent->index], 226129794Stackerman ixgb_driver_version); 227129794Stackerman device_set_desc_copy(dev, adapter_name); 228143160Simp return (BUS_PROBE_DEFAULT); 229129794Stackerman } 230129794Stackerman ent++; 231129794Stackerman } 232129794Stackerman 233129794Stackerman return (ENXIO); 234129794Stackerman} 235129794Stackerman 236129794Stackerman/********************************************************************* 237129794Stackerman * Device initialization routine 238129794Stackerman * 239129794Stackerman * The attach entry point is called when the driver is being loaded. 240129794Stackerman * This routine identifies the type of hardware, allocates all resources 241129794Stackerman * and initializes the hardware. 242129794Stackerman * 243129794Stackerman * return 0 on success, positive on failure 244129794Stackerman *********************************************************************/ 245129794Stackerman 246129794Stackermanstatic int 247129794Stackermanixgb_attach(device_t dev) 248129794Stackerman{ 249129794Stackerman struct adapter *adapter; 250129794Stackerman int tsize, rsize; 251129794Stackerman int error = 0; 252129794Stackerman 253198987Sjhb device_printf(dev, "%s\n", ixgb_copyright); 254129794Stackerman INIT_DEBUGOUT("ixgb_attach: begin"); 255129794Stackerman 256129794Stackerman /* Allocate, clear, and link in our adapter structure */ 257129794Stackerman if (!(adapter = device_get_softc(dev))) { 258198987Sjhb device_printf(dev, "adapter structure allocation failed\n"); 259129794Stackerman return (ENOMEM); 260129794Stackerman } 261129794Stackerman bzero(adapter, sizeof(struct adapter)); 262129794Stackerman adapter->dev = dev; 263129794Stackerman adapter->osdep.dev = dev; 264144651Salc IXGB_LOCK_INIT(adapter, device_get_nameunit(dev)); 265129794Stackerman 266129794Stackerman if (ixgb_adapter_list != NULL) 267129794Stackerman ixgb_adapter_list->prev = adapter; 268129794Stackerman adapter->next = ixgb_adapter_list; 269129794Stackerman ixgb_adapter_list = adapter; 270129794Stackerman 271129794Stackerman /* SYSCTL APIs */ 272144183Smux SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 273144183Smux SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 274129794Stackerman OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW, 275129794Stackerman (void *)adapter, 0, 276129794Stackerman ixgb_sysctl_stats, "I", "Statistics"); 277129794Stackerman 278199539Sjhb callout_init_mtx(&adapter->timer, &adapter->mtx, 0); 279129794Stackerman 280129794Stackerman /* Determine hardware revision */ 281129794Stackerman ixgb_identify_hardware(adapter); 282129794Stackerman 283129794Stackerman /* Parameters (to be read from user) */ 284129794Stackerman adapter->num_tx_desc = IXGB_MAX_TXD; 285129794Stackerman adapter->num_rx_desc = IXGB_MAX_RXD; 286129794Stackerman adapter->tx_int_delay = TIDV; 287129794Stackerman adapter->rx_int_delay = RDTR; 288129794Stackerman adapter->rx_buffer_len = IXGB_RXBUFFER_2048; 289129794Stackerman 290129794Stackerman adapter->hw.fc.high_water = FCRTH; 291129794Stackerman adapter->hw.fc.low_water = FCRTL; 292129794Stackerman adapter->hw.fc.pause_time = FCPAUSE; 293129794Stackerman adapter->hw.fc.send_xon = TRUE; 294129794Stackerman adapter->hw.fc.type = FLOW_CONTROL; 295129794Stackerman 296129794Stackerman 297129794Stackerman /* Set the max frame size assuming standard ethernet sized frames */ 298129794Stackerman adapter->hw.max_frame_size = 299129794Stackerman ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN; 300129794Stackerman 301129794Stackerman if (ixgb_allocate_pci_resources(adapter)) { 302198987Sjhb device_printf(dev, "Allocation of PCI resources failed\n"); 303129794Stackerman error = ENXIO; 304129794Stackerman goto err_pci; 305129794Stackerman } 306129794Stackerman tsize = IXGB_ROUNDUP(adapter->num_tx_desc * 307129794Stackerman sizeof(struct ixgb_tx_desc), 4096); 308129794Stackerman 309129794Stackerman /* Allocate Transmit Descriptor ring */ 310129794Stackerman if (ixgb_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) { 311198987Sjhb device_printf(dev, "Unable to allocate TxDescriptor memory\n"); 312129794Stackerman error = ENOMEM; 313129794Stackerman goto err_tx_desc; 314129794Stackerman } 315129794Stackerman adapter->tx_desc_base = (struct ixgb_tx_desc *) adapter->txdma.dma_vaddr; 316129794Stackerman 317129794Stackerman rsize = IXGB_ROUNDUP(adapter->num_rx_desc * 318129794Stackerman sizeof(struct ixgb_rx_desc), 4096); 319129794Stackerman 320129794Stackerman /* Allocate Receive Descriptor ring */ 321129794Stackerman if (ixgb_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) { 322198987Sjhb device_printf(dev, "Unable to allocate rx_desc memory\n"); 323129794Stackerman error = ENOMEM; 324129794Stackerman goto err_rx_desc; 325129794Stackerman } 326129794Stackerman adapter->rx_desc_base = (struct ixgb_rx_desc *) adapter->rxdma.dma_vaddr; 327129794Stackerman 328211913Syongari /* Allocate multicast array memory. */ 329211913Syongari adapter->mta = malloc(sizeof(u_int8_t) * IXGB_ETH_LENGTH_OF_ADDRESS * 330211913Syongari MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT); 331211913Syongari if (adapter->mta == NULL) { 332211913Syongari device_printf(dev, "Can not allocate multicast setup array\n"); 333211913Syongari error = ENOMEM; 334211913Syongari goto err_hw_init; 335211913Syongari } 336211913Syongari 337129794Stackerman /* Initialize the hardware */ 338129794Stackerman if (ixgb_hardware_init(adapter)) { 339198987Sjhb device_printf(dev, "Unable to initialize the hardware\n"); 340129794Stackerman error = EIO; 341129794Stackerman goto err_hw_init; 342129794Stackerman } 343129794Stackerman /* Setup OS specific network interface */ 344211907Syongari if (ixgb_setup_interface(dev, adapter) != 0) 345211907Syongari goto err_hw_init; 346129794Stackerman 347129794Stackerman /* Initialize statistics */ 348129794Stackerman ixgb_clear_hw_cntrs(&adapter->hw); 349129794Stackerman ixgb_update_stats_counters(adapter); 350129794Stackerman 351129794Stackerman INIT_DEBUGOUT("ixgb_attach: end"); 352129794Stackerman return (0); 353129794Stackerman 354129794Stackermanerr_hw_init: 355129794Stackerman ixgb_dma_free(adapter, &adapter->rxdma); 356129794Stackermanerr_rx_desc: 357129794Stackerman ixgb_dma_free(adapter, &adapter->txdma); 358129794Stackermanerr_tx_desc: 359129794Stackermanerr_pci: 360211907Syongari if (adapter->ifp != NULL) 361211907Syongari if_free(adapter->ifp); 362129794Stackerman ixgb_free_pci_resources(adapter); 363129794Stackerman sysctl_ctx_free(&adapter->sysctl_ctx); 364211913Syongari free(adapter->mta, M_DEVBUF); 365129794Stackerman return (error); 366129794Stackerman 367129794Stackerman} 368129794Stackerman 369129794Stackerman/********************************************************************* 370129794Stackerman * Device removal routine 371129794Stackerman * 372129794Stackerman * The detach entry point is called when the driver is being removed. 373129794Stackerman * This routine stops the adapter and deallocates all the resources 374129794Stackerman * that were allocated for driver operation. 375129794Stackerman * 376129794Stackerman * return 0 on success, positive on failure 377129794Stackerman *********************************************************************/ 378129794Stackerman 379129794Stackermanstatic int 380129794Stackermanixgb_detach(device_t dev) 381129794Stackerman{ 382129794Stackerman struct adapter *adapter = device_get_softc(dev); 383147256Sbrooks struct ifnet *ifp = adapter->ifp; 384129794Stackerman 385129794Stackerman INIT_DEBUGOUT("ixgb_detach: begin"); 386129794Stackerman 387150789Sglebius#ifdef DEVICE_POLLING 388150789Sglebius if (ifp->if_capenable & IFCAP_POLLING) 389150789Sglebius ether_poll_deregister(ifp); 390150789Sglebius#endif 391150789Sglebius 392144651Salc IXGB_LOCK(adapter); 393129794Stackerman adapter->in_detach = 1; 394129794Stackerman 395129794Stackerman ixgb_stop(adapter); 396144651Salc IXGB_UNLOCK(adapter); 397129794Stackerman 398129794Stackerman#if __FreeBSD_version < 500000 399199539Sjhb ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); 400129794Stackerman#else 401199539Sjhb ether_ifdetach(ifp); 402150306Simp#endif 403199539Sjhb callout_drain(&adapter->timer); 404150306Simp ixgb_free_pci_resources(adapter); 405150306Simp#if __FreeBSD_version >= 500000 406199539Sjhb if_free(ifp); 407129794Stackerman#endif 408129794Stackerman 409129794Stackerman /* Free Transmit Descriptor ring */ 410129794Stackerman if (adapter->tx_desc_base) { 411129794Stackerman ixgb_dma_free(adapter, &adapter->txdma); 412129794Stackerman adapter->tx_desc_base = NULL; 413129794Stackerman } 414129794Stackerman /* Free Receive Descriptor ring */ 415129794Stackerman if (adapter->rx_desc_base) { 416129794Stackerman ixgb_dma_free(adapter, &adapter->rxdma); 417129794Stackerman adapter->rx_desc_base = NULL; 418129794Stackerman } 419129794Stackerman /* Remove from the adapter list */ 420129794Stackerman if (ixgb_adapter_list == adapter) 421129794Stackerman ixgb_adapter_list = adapter->next; 422129794Stackerman if (adapter->next != NULL) 423129794Stackerman adapter->next->prev = adapter->prev; 424129794Stackerman if (adapter->prev != NULL) 425129794Stackerman adapter->prev->next = adapter->next; 426211913Syongari free(adapter->mta, M_DEVBUF); 427129794Stackerman 428144651Salc IXGB_LOCK_DESTROY(adapter); 429129794Stackerman return (0); 430129794Stackerman} 431129794Stackerman 432129794Stackerman/********************************************************************* 433129794Stackerman * 434129794Stackerman * Shutdown entry point 435129794Stackerman * 436129794Stackerman **********************************************************************/ 437129794Stackerman 438129794Stackermanstatic int 439129794Stackermanixgb_shutdown(device_t dev) 440129794Stackerman{ 441129794Stackerman struct adapter *adapter = device_get_softc(dev); 442144651Salc IXGB_LOCK(adapter); 443129794Stackerman ixgb_stop(adapter); 444144651Salc IXGB_UNLOCK(adapter); 445129794Stackerman return (0); 446129794Stackerman} 447129794Stackerman 448129794Stackerman 449129794Stackerman/********************************************************************* 450129794Stackerman * Transmit entry point 451129794Stackerman * 452129794Stackerman * ixgb_start is called by the stack to initiate a transmit. 453129794Stackerman * The driver will remain in this routine as long as there are 454129794Stackerman * packets to transmit and transmit resources are available. 455129794Stackerman * In case resources are not available stack is notified and 456129794Stackerman * the packet is requeued. 457129794Stackerman **********************************************************************/ 458129794Stackerman 459129794Stackermanstatic void 460144651Salcixgb_start_locked(struct ifnet * ifp) 461129794Stackerman{ 462129794Stackerman struct mbuf *m_head; 463129794Stackerman struct adapter *adapter = ifp->if_softc; 464129794Stackerman 465144651Salc IXGB_LOCK_ASSERT(adapter); 466129794Stackerman 467129794Stackerman if (!adapter->link_active) 468129794Stackerman return; 469129794Stackerman 470129794Stackerman while (ifp->if_snd.ifq_head != NULL) { 471129794Stackerman IF_DEQUEUE(&ifp->if_snd, m_head); 472129794Stackerman 473129794Stackerman if (m_head == NULL) 474129794Stackerman break; 475129794Stackerman 476129794Stackerman if (ixgb_encap(adapter, m_head)) { 477148887Srwatson ifp->if_drv_flags |= IFF_DRV_OACTIVE; 478129794Stackerman IF_PREPEND(&ifp->if_snd, m_head); 479129794Stackerman break; 480129794Stackerman } 481129794Stackerman /* Send a copy of the frame to the BPF listener */ 482129794Stackerman#if __FreeBSD_version < 500000 483129794Stackerman if (ifp->if_bpf) 484129794Stackerman bpf_mtap(ifp, m_head); 485129794Stackerman#else 486167190Scsjp ETHER_BPF_MTAP(ifp, m_head); 487129794Stackerman#endif 488129794Stackerman /* Set timeout in case hardware has problems transmitting */ 489199539Sjhb adapter->tx_timer = IXGB_TX_TIMEOUT; 490129794Stackerman 491129794Stackerman } 492129794Stackerman return; 493129794Stackerman} 494129794Stackerman 495144651Salcstatic void 496144651Salcixgb_start(struct ifnet *ifp) 497144651Salc{ 498144651Salc struct adapter *adapter = ifp->if_softc; 499144651Salc 500144651Salc IXGB_LOCK(adapter); 501144651Salc ixgb_start_locked(ifp); 502144651Salc IXGB_UNLOCK(adapter); 503144651Salc return; 504144651Salc} 505144651Salc 506129794Stackerman/********************************************************************* 507129794Stackerman * Ioctl entry point 508129794Stackerman * 509129794Stackerman * ixgb_ioctl is called when the user wants to configure the 510129794Stackerman * interface. 511129794Stackerman * 512129794Stackerman * return 0 on success, positive on failure 513129794Stackerman **********************************************************************/ 514129794Stackerman 515129794Stackermanstatic int 516129794Stackermanixgb_ioctl(struct ifnet * ifp, IOCTL_CMD_TYPE command, caddr_t data) 517129794Stackerman{ 518144651Salc int mask, error = 0; 519129794Stackerman struct ifreq *ifr = (struct ifreq *) data; 520129794Stackerman struct adapter *adapter = ifp->if_softc; 521129794Stackerman 522129794Stackerman if (adapter->in_detach) 523129794Stackerman goto out; 524129794Stackerman 525129794Stackerman switch (command) { 526129794Stackerman case SIOCSIFADDR: 527129794Stackerman case SIOCGIFADDR: 528129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFADDR (Get/Set Interface Addr)"); 529129794Stackerman ether_ioctl(ifp, command, data); 530129794Stackerman break; 531129794Stackerman case SIOCSIFMTU: 532129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); 533129794Stackerman if (ifr->ifr_mtu > IXGB_MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN) { 534129794Stackerman error = EINVAL; 535129794Stackerman } else { 536144651Salc IXGB_LOCK(adapter); 537129794Stackerman ifp->if_mtu = ifr->ifr_mtu; 538129794Stackerman adapter->hw.max_frame_size = 539129794Stackerman ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 540129794Stackerman 541144651Salc ixgb_init_locked(adapter); 542144651Salc IXGB_UNLOCK(adapter); 543129794Stackerman } 544129794Stackerman break; 545129794Stackerman case SIOCSIFFLAGS: 546129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)"); 547144651Salc IXGB_LOCK(adapter); 548129794Stackerman if (ifp->if_flags & IFF_UP) { 549148887Srwatson if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 550144651Salc ixgb_init_locked(adapter); 551129794Stackerman } 552129794Stackerman ixgb_disable_promisc(adapter); 553129794Stackerman ixgb_set_promisc(adapter); 554129794Stackerman } else { 555148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 556129794Stackerman ixgb_stop(adapter); 557129794Stackerman } 558129794Stackerman } 559144651Salc IXGB_UNLOCK(adapter); 560129794Stackerman break; 561129794Stackerman case SIOCADDMULTI: 562129794Stackerman case SIOCDELMULTI: 563129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI"); 564148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 565144651Salc IXGB_LOCK(adapter); 566129794Stackerman ixgb_disable_intr(adapter); 567129794Stackerman ixgb_set_multi(adapter); 568129794Stackerman ixgb_enable_intr(adapter); 569144651Salc IXGB_UNLOCK(adapter); 570129794Stackerman } 571129794Stackerman break; 572129794Stackerman case SIOCSIFMEDIA: 573129794Stackerman case SIOCGIFMEDIA: 574129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA (Get/Set Interface Media)"); 575129794Stackerman error = ifmedia_ioctl(ifp, ifr, &adapter->media, command); 576129794Stackerman break; 577129794Stackerman case SIOCSIFCAP: 578129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)"); 579129794Stackerman mask = ifr->ifr_reqcap ^ ifp->if_capenable; 580150789Sglebius#ifdef DEVICE_POLLING 581150789Sglebius if (mask & IFCAP_POLLING) { 582150789Sglebius if (ifr->ifr_reqcap & IFCAP_POLLING) { 583150789Sglebius error = ether_poll_register(ixgb_poll, ifp); 584150789Sglebius if (error) 585150789Sglebius return(error); 586150789Sglebius IXGB_LOCK(adapter); 587150789Sglebius ixgb_disable_intr(adapter); 588150789Sglebius ifp->if_capenable |= IFCAP_POLLING; 589150789Sglebius IXGB_UNLOCK(adapter); 590150789Sglebius } else { 591150789Sglebius error = ether_poll_deregister(ifp); 592150789Sglebius /* Enable interrupt even in error case */ 593150789Sglebius IXGB_LOCK(adapter); 594150789Sglebius ixgb_enable_intr(adapter); 595150789Sglebius ifp->if_capenable &= ~IFCAP_POLLING; 596150789Sglebius IXGB_UNLOCK(adapter); 597150789Sglebius } 598150789Sglebius } 599150789Sglebius#endif /* DEVICE_POLLING */ 600129794Stackerman if (mask & IFCAP_HWCSUM) { 601129794Stackerman if (IFCAP_HWCSUM & ifp->if_capenable) 602129794Stackerman ifp->if_capenable &= ~IFCAP_HWCSUM; 603129794Stackerman else 604129794Stackerman ifp->if_capenable |= IFCAP_HWCSUM; 605148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) 606129794Stackerman ixgb_init(adapter); 607129794Stackerman } 608129794Stackerman break; 609129794Stackerman default: 610129794Stackerman IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%X)\n", (int)command); 611129794Stackerman error = EINVAL; 612129794Stackerman } 613129794Stackerman 614129794Stackermanout: 615129794Stackerman return (error); 616129794Stackerman} 617129794Stackerman 618129794Stackerman/********************************************************************* 619129794Stackerman * Watchdog entry point 620129794Stackerman * 621129794Stackerman * This routine is called whenever hardware quits transmitting. 622129794Stackerman * 623129794Stackerman **********************************************************************/ 624129794Stackerman 625129794Stackermanstatic void 626199539Sjhbixgb_watchdog(struct adapter *adapter) 627129794Stackerman{ 628199539Sjhb struct ifnet *ifp; 629129794Stackerman 630199539Sjhb ifp = adapter->ifp; 631199539Sjhb 632129794Stackerman /* 633129794Stackerman * If we are in this routine because of pause frames, then don't 634129794Stackerman * reset the hardware. 635129794Stackerman */ 636129794Stackerman if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF) { 637199539Sjhb adapter->tx_timer = IXGB_TX_TIMEOUT; 638129794Stackerman return; 639129794Stackerman } 640198987Sjhb if_printf(ifp, "watchdog timeout -- resetting\n"); 641129794Stackerman 642129794Stackerman ixgb_stop(adapter); 643199539Sjhb ixgb_init_locked(adapter); 644129794Stackerman 645129794Stackerman 646129794Stackerman ifp->if_oerrors++; 647129794Stackerman 648129794Stackerman return; 649129794Stackerman} 650129794Stackerman 651129794Stackerman/********************************************************************* 652129794Stackerman * Init entry point 653129794Stackerman * 654129794Stackerman * This routine is used in two ways. It is used by the stack as 655129794Stackerman * init entry point in network interface structure. It is also used 656129794Stackerman * by the driver as a hw/sw initialization routine to get to a 657129794Stackerman * consistent state. 658129794Stackerman * 659129794Stackerman * return 0 on success, positive on failure 660129794Stackerman **********************************************************************/ 661129794Stackerman 662129794Stackermanstatic void 663144651Salcixgb_init_locked(struct adapter *adapter) 664129794Stackerman{ 665129794Stackerman struct ifnet *ifp; 666129794Stackerman 667129794Stackerman INIT_DEBUGOUT("ixgb_init: begin"); 668129794Stackerman 669144651Salc IXGB_LOCK_ASSERT(adapter); 670129794Stackerman 671129794Stackerman ixgb_stop(adapter); 672198987Sjhb ifp = adapter->ifp; 673129794Stackerman 674129794Stackerman /* Get the latest mac address, User can use a LAA */ 675198987Sjhb bcopy(IF_LLADDR(ifp), adapter->hw.curr_mac_addr, 676198987Sjhb IXGB_ETH_LENGTH_OF_ADDRESS); 677129794Stackerman 678129794Stackerman /* Initialize the hardware */ 679129794Stackerman if (ixgb_hardware_init(adapter)) { 680198987Sjhb if_printf(ifp, "Unable to initialize the hardware\n"); 681129794Stackerman return; 682129794Stackerman } 683129794Stackerman ixgb_enable_vlans(adapter); 684129794Stackerman 685129794Stackerman /* Prepare transmit descriptors and buffers */ 686129794Stackerman if (ixgb_setup_transmit_structures(adapter)) { 687198987Sjhb if_printf(ifp, "Could not setup transmit structures\n"); 688129794Stackerman ixgb_stop(adapter); 689129794Stackerman return; 690129794Stackerman } 691129794Stackerman ixgb_initialize_transmit_unit(adapter); 692129794Stackerman 693129794Stackerman /* Setup Multicast table */ 694129794Stackerman ixgb_set_multi(adapter); 695129794Stackerman 696129794Stackerman /* Prepare receive descriptors and buffers */ 697129794Stackerman if (ixgb_setup_receive_structures(adapter)) { 698198987Sjhb if_printf(ifp, "Could not setup receive structures\n"); 699129794Stackerman ixgb_stop(adapter); 700129794Stackerman return; 701129794Stackerman } 702129794Stackerman ixgb_initialize_receive_unit(adapter); 703129794Stackerman 704160964Syar /* Don't lose promiscuous settings */ 705129794Stackerman ixgb_set_promisc(adapter); 706129794Stackerman 707147256Sbrooks ifp = adapter->ifp; 708148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 709148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 710129794Stackerman 711129794Stackerman 712129794Stackerman if (ifp->if_capenable & IFCAP_TXCSUM) 713129794Stackerman ifp->if_hwassist = IXGB_CHECKSUM_FEATURES; 714129794Stackerman else 715129794Stackerman ifp->if_hwassist = 0; 716129794Stackerman 717129794Stackerman 718129794Stackerman /* Enable jumbo frames */ 719129794Stackerman if (ifp->if_mtu > ETHERMTU) { 720129794Stackerman uint32_t temp_reg; 721129794Stackerman IXGB_WRITE_REG(&adapter->hw, MFS, 722129794Stackerman adapter->hw.max_frame_size << IXGB_MFS_SHIFT); 723129794Stackerman temp_reg = IXGB_READ_REG(&adapter->hw, CTRL0); 724129794Stackerman temp_reg |= IXGB_CTRL0_JFE; 725129794Stackerman IXGB_WRITE_REG(&adapter->hw, CTRL0, temp_reg); 726129794Stackerman } 727199539Sjhb callout_reset(&adapter->timer, hz, ixgb_local_timer, adapter); 728129794Stackerman ixgb_clear_hw_cntrs(&adapter->hw); 729129794Stackerman#ifdef DEVICE_POLLING 730129794Stackerman /* 731129794Stackerman * Only disable interrupts if we are polling, make sure they are on 732129794Stackerman * otherwise. 733129794Stackerman */ 734150789Sglebius if (ifp->if_capenable & IFCAP_POLLING) 735129794Stackerman ixgb_disable_intr(adapter); 736129794Stackerman else 737150789Sglebius#endif 738129794Stackerman ixgb_enable_intr(adapter); 739129794Stackerman 740129794Stackerman return; 741129794Stackerman} 742129794Stackerman 743144651Salcstatic void 744144651Salcixgb_init(void *arg) 745144651Salc{ 746144651Salc struct adapter *adapter = arg; 747129794Stackerman 748144651Salc IXGB_LOCK(adapter); 749144651Salc ixgb_init_locked(adapter); 750144651Salc IXGB_UNLOCK(adapter); 751144651Salc return; 752144651Salc} 753144651Salc 754129794Stackerman#ifdef DEVICE_POLLING 755193096Sattiliostatic int 756144651Salcixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count) 757129794Stackerman{ 758129794Stackerman struct adapter *adapter = ifp->if_softc; 759129794Stackerman u_int32_t reg_icr; 760193096Sattilio int rx_npkts; 761129794Stackerman 762144651Salc IXGB_LOCK_ASSERT(adapter); 763144651Salc 764129794Stackerman if (cmd == POLL_AND_CHECK_STATUS) { 765129794Stackerman reg_icr = IXGB_READ_REG(&adapter->hw, ICR); 766129794Stackerman if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) { 767129794Stackerman ixgb_check_for_link(&adapter->hw); 768129794Stackerman ixgb_print_link_status(adapter); 769129794Stackerman } 770129794Stackerman } 771193096Sattilio rx_npkts = ixgb_process_receive_interrupts(adapter, count); 772150789Sglebius ixgb_clean_transmit_interrupts(adapter); 773150789Sglebius 774150789Sglebius if (ifp->if_snd.ifq_head != NULL) 775144651Salc ixgb_start_locked(ifp); 776193096Sattilio return (rx_npkts); 777129794Stackerman} 778144651Salc 779193096Sattiliostatic int 780144651Salcixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count) 781144651Salc{ 782144651Salc struct adapter *adapter = ifp->if_softc; 783193096Sattilio int rx_npkts = 0; 784144651Salc 785144651Salc IXGB_LOCK(adapter); 786150789Sglebius if (ifp->if_drv_flags & IFF_DRV_RUNNING) 787193096Sattilio rx_npkts = ixgb_poll_locked(ifp, cmd, count); 788144651Salc IXGB_UNLOCK(adapter); 789193096Sattilio return (rx_npkts); 790144651Salc} 791150789Sglebius#endif /* DEVICE_POLLING */ 792129794Stackerman 793129794Stackerman/********************************************************************* 794129794Stackerman * 795129794Stackerman * Interrupt Service routine 796129794Stackerman * 797129794Stackerman **********************************************************************/ 798129794Stackerman 799129794Stackermanstatic void 800129794Stackermanixgb_intr(void *arg) 801129794Stackerman{ 802129794Stackerman u_int32_t loop_cnt = IXGB_MAX_INTR; 803129794Stackerman u_int32_t reg_icr; 804129794Stackerman struct ifnet *ifp; 805129794Stackerman struct adapter *adapter = arg; 806129794Stackerman boolean_t rxdmt0 = FALSE; 807129794Stackerman 808144651Salc IXGB_LOCK(adapter); 809144651Salc 810147256Sbrooks ifp = adapter->ifp; 811129794Stackerman 812129794Stackerman#ifdef DEVICE_POLLING 813150789Sglebius if (ifp->if_capenable & IFCAP_POLLING) { 814144651Salc IXGB_UNLOCK(adapter); 815129794Stackerman return; 816144651Salc } 817150789Sglebius#endif 818129794Stackerman 819144651Salc reg_icr = IXGB_READ_REG(&adapter->hw, ICR); 820144651Salc if (reg_icr == 0) { 821144651Salc IXGB_UNLOCK(adapter); 822129794Stackerman return; 823144651Salc } 824129794Stackerman 825129794Stackerman if (reg_icr & IXGB_INT_RXDMT0) 826129794Stackerman rxdmt0 = TRUE; 827129794Stackerman 828129794Stackerman#ifdef _SV_ 829129794Stackerman if (reg_icr & IXGB_INT_RXDMT0) 830129794Stackerman adapter->sv_stats.icr_rxdmt0++; 831129794Stackerman if (reg_icr & IXGB_INT_RXO) 832129794Stackerman adapter->sv_stats.icr_rxo++; 833129794Stackerman if (reg_icr & IXGB_INT_RXT0) 834129794Stackerman adapter->sv_stats.icr_rxt0++; 835129794Stackerman if (reg_icr & IXGB_INT_TXDW) 836129794Stackerman adapter->sv_stats.icr_TXDW++; 837129794Stackerman#endif /* _SV_ */ 838129794Stackerman 839129794Stackerman /* Link status change */ 840129794Stackerman if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) { 841129794Stackerman ixgb_check_for_link(&adapter->hw); 842129794Stackerman ixgb_print_link_status(adapter); 843129794Stackerman } 844129794Stackerman while (loop_cnt > 0) { 845148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 846129794Stackerman ixgb_process_receive_interrupts(adapter, -1); 847129794Stackerman ixgb_clean_transmit_interrupts(adapter); 848129794Stackerman } 849129794Stackerman loop_cnt--; 850129794Stackerman } 851129794Stackerman 852129794Stackerman if (rxdmt0 && adapter->raidc) { 853129794Stackerman IXGB_WRITE_REG(&adapter->hw, IMC, IXGB_INT_RXDMT0); 854129794Stackerman IXGB_WRITE_REG(&adapter->hw, IMS, IXGB_INT_RXDMT0); 855129794Stackerman } 856148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING && ifp->if_snd.ifq_head != NULL) 857144651Salc ixgb_start_locked(ifp); 858129794Stackerman 859144651Salc IXGB_UNLOCK(adapter); 860129794Stackerman return; 861129794Stackerman} 862129794Stackerman 863129794Stackerman 864129794Stackerman/********************************************************************* 865129794Stackerman * 866129794Stackerman * Media Ioctl callback 867129794Stackerman * 868129794Stackerman * This routine is called whenever the user queries the status of 869129794Stackerman * the interface using ifconfig. 870129794Stackerman * 871129794Stackerman **********************************************************************/ 872129794Stackermanstatic void 873129794Stackermanixgb_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) 874129794Stackerman{ 875129794Stackerman struct adapter *adapter = ifp->if_softc; 876129794Stackerman 877129794Stackerman INIT_DEBUGOUT("ixgb_media_status: begin"); 878129794Stackerman 879129794Stackerman ixgb_check_for_link(&adapter->hw); 880129794Stackerman ixgb_print_link_status(adapter); 881129794Stackerman 882129794Stackerman ifmr->ifm_status = IFM_AVALID; 883129794Stackerman ifmr->ifm_active = IFM_ETHER; 884129794Stackerman 885129794Stackerman if (!adapter->hw.link_up) 886129794Stackerman return; 887129794Stackerman 888129794Stackerman ifmr->ifm_status |= IFM_ACTIVE; 889129794Stackerman ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; 890129794Stackerman 891129794Stackerman return; 892129794Stackerman} 893129794Stackerman 894129794Stackerman/********************************************************************* 895129794Stackerman * 896129794Stackerman * Media Ioctl callback 897129794Stackerman * 898129794Stackerman * This routine is called when the user changes speed/duplex using 899129794Stackerman * media/mediopt option with ifconfig. 900129794Stackerman * 901129794Stackerman **********************************************************************/ 902129794Stackermanstatic int 903129794Stackermanixgb_media_change(struct ifnet * ifp) 904129794Stackerman{ 905129794Stackerman struct adapter *adapter = ifp->if_softc; 906129794Stackerman struct ifmedia *ifm = &adapter->media; 907129794Stackerman 908129794Stackerman INIT_DEBUGOUT("ixgb_media_change: begin"); 909129794Stackerman 910129794Stackerman if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 911129794Stackerman return (EINVAL); 912129794Stackerman 913129794Stackerman return (0); 914129794Stackerman} 915129794Stackerman 916129794Stackerman/********************************************************************* 917129794Stackerman * 918129794Stackerman * This routine maps the mbufs to tx descriptors. 919129794Stackerman * 920129794Stackerman * return 0 on success, positive on failure 921129794Stackerman **********************************************************************/ 922129794Stackerman 923129794Stackermanstatic int 924129794Stackermanixgb_encap(struct adapter * adapter, struct mbuf * m_head) 925129794Stackerman{ 926129794Stackerman u_int8_t txd_popts; 927146339Salc int i, j, error, nsegs; 928129794Stackerman 929129794Stackerman#if __FreeBSD_version < 500000 930129794Stackerman struct ifvlan *ifv = NULL; 931129794Stackerman#endif 932146339Salc bus_dma_segment_t segs[IXGB_MAX_SCATTER]; 933146339Salc bus_dmamap_t map; 934129794Stackerman struct ixgb_buffer *tx_buffer = NULL; 935129794Stackerman struct ixgb_tx_desc *current_tx_desc = NULL; 936147256Sbrooks struct ifnet *ifp = adapter->ifp; 937129794Stackerman 938129794Stackerman /* 939129794Stackerman * Force a cleanup if number of TX descriptors available hits the 940129794Stackerman * threshold 941129794Stackerman */ 942129794Stackerman if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) { 943129794Stackerman ixgb_clean_transmit_interrupts(adapter); 944129794Stackerman } 945129794Stackerman if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) { 946129794Stackerman adapter->no_tx_desc_avail1++; 947129794Stackerman return (ENOBUFS); 948129794Stackerman } 949129794Stackerman /* 950129794Stackerman * Map the packet for DMA. 951129794Stackerman */ 952146339Salc if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &map)) { 953129794Stackerman adapter->no_tx_map_avail++; 954129794Stackerman return (ENOMEM); 955129794Stackerman } 956146339Salc error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs, 957146339Salc &nsegs, BUS_DMA_NOWAIT); 958129794Stackerman if (error != 0) { 959129794Stackerman adapter->no_tx_dma_setup++; 960198987Sjhb if_printf(ifp, "ixgb_encap: bus_dmamap_load_mbuf failed; " 961198987Sjhb "error %u\n", error); 962146339Salc bus_dmamap_destroy(adapter->txtag, map); 963129794Stackerman return (error); 964129794Stackerman } 965146339Salc KASSERT(nsegs != 0, ("ixgb_encap: empty packet")); 966129794Stackerman 967146339Salc if (nsegs > adapter->num_tx_desc_avail) { 968129794Stackerman adapter->no_tx_desc_avail2++; 969146339Salc bus_dmamap_destroy(adapter->txtag, map); 970129794Stackerman return (ENOBUFS); 971129794Stackerman } 972129794Stackerman if (ifp->if_hwassist > 0) { 973129794Stackerman ixgb_transmit_checksum_setup(adapter, m_head, 974129794Stackerman &txd_popts); 975129794Stackerman } else 976129794Stackerman txd_popts = 0; 977129794Stackerman 978129794Stackerman /* Find out if we are in vlan mode */ 979129794Stackerman#if __FreeBSD_version < 500000 980129794Stackerman if ((m_head->m_flags & (M_PROTO1 | M_PKTHDR)) == (M_PROTO1 | M_PKTHDR) && 981129794Stackerman m_head->m_pkthdr.rcvif != NULL && 982129794Stackerman m_head->m_pkthdr.rcvif->if_type == IFT_L2VLAN) 983129794Stackerman ifv = m_head->m_pkthdr.rcvif->if_softc; 984162375Sandre#elseif __FreeBSD_version < 700000 985129794Stackerman mtag = VLAN_OUTPUT_TAG(ifp, m_head); 986129794Stackerman#endif 987129794Stackerman i = adapter->next_avail_tx_desc; 988146339Salc for (j = 0; j < nsegs; j++) { 989129794Stackerman tx_buffer = &adapter->tx_buffer_area[i]; 990129794Stackerman current_tx_desc = &adapter->tx_desc_base[i]; 991129794Stackerman 992146339Salc current_tx_desc->buff_addr = htole64(segs[j].ds_addr); 993146339Salc current_tx_desc->cmd_type_len = (adapter->txd_cmd | segs[j].ds_len); 994129794Stackerman current_tx_desc->popts = txd_popts; 995129794Stackerman if (++i == adapter->num_tx_desc) 996129794Stackerman i = 0; 997129794Stackerman 998129794Stackerman tx_buffer->m_head = NULL; 999129794Stackerman } 1000129794Stackerman 1001146339Salc adapter->num_tx_desc_avail -= nsegs; 1002129794Stackerman adapter->next_avail_tx_desc = i; 1003129794Stackerman 1004129794Stackerman#if __FreeBSD_version < 500000 1005129794Stackerman if (ifv != NULL) { 1006129794Stackerman /* Set the vlan id */ 1007129794Stackerman current_tx_desc->vlan = ifv->ifv_tag; 1008162375Sandre#elseif __FreeBSD_version < 700000 1009129794Stackerman if (mtag != NULL) { 1010129794Stackerman /* Set the vlan id */ 1011129794Stackerman current_tx_desc->vlan = VLAN_TAG_VALUE(mtag); 1012162375Sandre#else 1013162375Sandre if (m_head->m_flags & M_VLANTAG) { 1014162375Sandre current_tx_desc->vlan = m_head->m_pkthdr.ether_vtag; 1015129794Stackerman#endif 1016129794Stackerman 1017129794Stackerman /* Tell hardware to add tag */ 1018129794Stackerman current_tx_desc->cmd_type_len |= IXGB_TX_DESC_CMD_VLE; 1019129794Stackerman } 1020129794Stackerman tx_buffer->m_head = m_head; 1021146339Salc tx_buffer->map = map; 1022146339Salc bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE); 1023129794Stackerman 1024129794Stackerman /* 1025129794Stackerman * Last Descriptor of Packet needs End Of Packet (EOP) 1026129794Stackerman */ 1027129794Stackerman current_tx_desc->cmd_type_len |= (IXGB_TX_DESC_CMD_EOP); 1028129794Stackerman 1029129794Stackerman /* 1030129794Stackerman * Advance the Transmit Descriptor Tail (Tdt), this tells the E1000 1031129794Stackerman * that this frame is available to transmit. 1032129794Stackerman */ 1033129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDT, i); 1034129794Stackerman 1035129794Stackerman return (0); 1036129794Stackerman} 1037129794Stackerman 1038129794Stackermanstatic void 1039129794Stackermanixgb_set_promisc(struct adapter * adapter) 1040129794Stackerman{ 1041129794Stackerman 1042129794Stackerman u_int32_t reg_rctl; 1043147256Sbrooks struct ifnet *ifp = adapter->ifp; 1044129794Stackerman 1045129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1046129794Stackerman 1047129794Stackerman if (ifp->if_flags & IFF_PROMISC) { 1048129794Stackerman reg_rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE); 1049129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 1050129794Stackerman } else if (ifp->if_flags & IFF_ALLMULTI) { 1051129794Stackerman reg_rctl |= IXGB_RCTL_MPE; 1052129794Stackerman reg_rctl &= ~IXGB_RCTL_UPE; 1053129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 1054129794Stackerman } 1055129794Stackerman return; 1056129794Stackerman} 1057129794Stackerman 1058129794Stackermanstatic void 1059129794Stackermanixgb_disable_promisc(struct adapter * adapter) 1060129794Stackerman{ 1061129794Stackerman u_int32_t reg_rctl; 1062129794Stackerman 1063129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1064129794Stackerman 1065129794Stackerman reg_rctl &= (~IXGB_RCTL_UPE); 1066129794Stackerman reg_rctl &= (~IXGB_RCTL_MPE); 1067129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 1068129794Stackerman 1069129794Stackerman return; 1070129794Stackerman} 1071129794Stackerman 1072129794Stackerman 1073129794Stackerman/********************************************************************* 1074129794Stackerman * Multicast Update 1075129794Stackerman * 1076129794Stackerman * This routine is called whenever multicast address list is updated. 1077129794Stackerman * 1078129794Stackerman **********************************************************************/ 1079129794Stackerman 1080129794Stackermanstatic void 1081129794Stackermanixgb_set_multi(struct adapter * adapter) 1082129794Stackerman{ 1083129794Stackerman u_int32_t reg_rctl = 0; 1084211913Syongari u_int8_t *mta; 1085129794Stackerman struct ifmultiaddr *ifma; 1086129794Stackerman int mcnt = 0; 1087147256Sbrooks struct ifnet *ifp = adapter->ifp; 1088129794Stackerman 1089129794Stackerman IOCTL_DEBUGOUT("ixgb_set_multi: begin"); 1090129794Stackerman 1091211913Syongari mta = adapter->mta; 1092211913Syongari bzero(mta, sizeof(u_int8_t) * IXGB_ETH_LENGTH_OF_ADDRESS * 1093211913Syongari MAX_NUM_MULTICAST_ADDRESSES); 1094211913Syongari 1095195049Srwatson if_maddr_rlock(ifp); 1096129794Stackerman#if __FreeBSD_version < 500000 1097129794Stackerman LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1098129794Stackerman#else 1099129794Stackerman TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1100129794Stackerman#endif 1101129794Stackerman if (ifma->ifma_addr->sa_family != AF_LINK) 1102129794Stackerman continue; 1103129794Stackerman 1104129794Stackerman bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr), 1105129794Stackerman &mta[mcnt * IXGB_ETH_LENGTH_OF_ADDRESS], IXGB_ETH_LENGTH_OF_ADDRESS); 1106129794Stackerman mcnt++; 1107129794Stackerman } 1108195049Srwatson if_maddr_runlock(ifp); 1109129794Stackerman 1110129794Stackerman if (mcnt > MAX_NUM_MULTICAST_ADDRESSES) { 1111129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1112129794Stackerman reg_rctl |= IXGB_RCTL_MPE; 1113129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 1114129794Stackerman } else 1115129794Stackerman ixgb_mc_addr_list_update(&adapter->hw, mta, mcnt, 0); 1116129794Stackerman 1117129794Stackerman return; 1118129794Stackerman} 1119129794Stackerman 1120129794Stackerman 1121129794Stackerman/********************************************************************* 1122129794Stackerman * Timer routine 1123129794Stackerman * 1124129794Stackerman * This routine checks for link status and updates statistics. 1125129794Stackerman * 1126129794Stackerman **********************************************************************/ 1127129794Stackerman 1128129794Stackermanstatic void 1129129794Stackermanixgb_local_timer(void *arg) 1130129794Stackerman{ 1131129794Stackerman struct ifnet *ifp; 1132129794Stackerman struct adapter *adapter = arg; 1133147256Sbrooks ifp = adapter->ifp; 1134129794Stackerman 1135199539Sjhb IXGB_LOCK_ASSERT(adapter); 1136129794Stackerman 1137129794Stackerman ixgb_check_for_link(&adapter->hw); 1138129794Stackerman ixgb_print_link_status(adapter); 1139129794Stackerman ixgb_update_stats_counters(adapter); 1140148887Srwatson if (ixgb_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) { 1141129794Stackerman ixgb_print_hw_stats(adapter); 1142129794Stackerman } 1143199539Sjhb if (adapter->tx_timer != 0 && --adapter->tx_timer == 0) 1144199539Sjhb ixgb_watchdog(adapter); 1145199539Sjhb callout_reset(&adapter->timer, hz, ixgb_local_timer, adapter); 1146129794Stackerman} 1147129794Stackerman 1148129794Stackermanstatic void 1149129794Stackermanixgb_print_link_status(struct adapter * adapter) 1150129794Stackerman{ 1151129794Stackerman if (adapter->hw.link_up) { 1152129794Stackerman if (!adapter->link_active) { 1153198987Sjhb if_printf(adapter->ifp, "Link is up %d Mbps %s \n", 1154129794Stackerman 10000, 1155129794Stackerman "Full Duplex"); 1156129794Stackerman adapter->link_active = 1; 1157129794Stackerman } 1158129794Stackerman } else { 1159129794Stackerman if (adapter->link_active) { 1160198987Sjhb if_printf(adapter->ifp, "Link is Down \n"); 1161129794Stackerman adapter->link_active = 0; 1162129794Stackerman } 1163129794Stackerman } 1164129794Stackerman 1165129794Stackerman return; 1166129794Stackerman} 1167129794Stackerman 1168129794Stackerman 1169129794Stackerman 1170129794Stackerman/********************************************************************* 1171129794Stackerman * 1172129794Stackerman * This routine disables all traffic on the adapter by issuing a 1173129794Stackerman * global reset on the MAC and deallocates TX/RX buffers. 1174129794Stackerman * 1175129794Stackerman **********************************************************************/ 1176129794Stackerman 1177129794Stackermanstatic void 1178129794Stackermanixgb_stop(void *arg) 1179129794Stackerman{ 1180129794Stackerman struct ifnet *ifp; 1181129794Stackerman struct adapter *adapter = arg; 1182147256Sbrooks ifp = adapter->ifp; 1183129794Stackerman 1184144651Salc IXGB_LOCK_ASSERT(adapter); 1185144651Salc 1186129794Stackerman INIT_DEBUGOUT("ixgb_stop: begin\n"); 1187129794Stackerman ixgb_disable_intr(adapter); 1188129794Stackerman adapter->hw.adapter_stopped = FALSE; 1189129794Stackerman ixgb_adapter_stop(&adapter->hw); 1190144651Salc callout_stop(&adapter->timer); 1191129794Stackerman ixgb_free_transmit_structures(adapter); 1192129794Stackerman ixgb_free_receive_structures(adapter); 1193129794Stackerman 1194129794Stackerman /* Tell the stack that the interface is no longer active */ 1195148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1196199539Sjhb adapter->tx_timer = 0; 1197129794Stackerman 1198129794Stackerman return; 1199129794Stackerman} 1200129794Stackerman 1201129794Stackerman 1202129794Stackerman/********************************************************************* 1203129794Stackerman * 1204129794Stackerman * Determine hardware revision. 1205129794Stackerman * 1206129794Stackerman **********************************************************************/ 1207129794Stackermanstatic void 1208129794Stackermanixgb_identify_hardware(struct adapter * adapter) 1209129794Stackerman{ 1210129794Stackerman device_t dev = adapter->dev; 1211129794Stackerman 1212129794Stackerman /* Make sure our PCI config space has the necessary stuff set */ 1213129794Stackerman adapter->hw.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); 1214129794Stackerman if (!((adapter->hw.pci_cmd_word & PCIM_CMD_BUSMASTEREN) && 1215129794Stackerman (adapter->hw.pci_cmd_word & PCIM_CMD_MEMEN))) { 1216198987Sjhb device_printf(dev, 1217198987Sjhb "Memory Access and/or Bus Master bits were not set!\n"); 1218129794Stackerman adapter->hw.pci_cmd_word |= 1219129794Stackerman (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); 1220129794Stackerman pci_write_config(dev, PCIR_COMMAND, adapter->hw.pci_cmd_word, 2); 1221129794Stackerman } 1222129794Stackerman /* Save off the information about this board */ 1223129794Stackerman adapter->hw.vendor_id = pci_get_vendor(dev); 1224129794Stackerman adapter->hw.device_id = pci_get_device(dev); 1225129794Stackerman adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1); 1226129794Stackerman adapter->hw.subsystem_vendor_id = pci_read_config(dev, PCIR_SUBVEND_0, 2); 1227129794Stackerman adapter->hw.subsystem_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 1228129794Stackerman 1229129794Stackerman /* Set MacType, etc. based on this PCI info */ 1230129794Stackerman switch (adapter->hw.device_id) { 1231129794Stackerman case IXGB_DEVICE_ID_82597EX: 1232129794Stackerman case IXGB_DEVICE_ID_82597EX_SR: 1233129794Stackerman adapter->hw.mac_type = ixgb_82597; 1234129794Stackerman break; 1235129794Stackerman default: 1236129794Stackerman INIT_DEBUGOUT1("Unknown device if 0x%x", adapter->hw.device_id); 1237198987Sjhb device_printf(dev, "unsupported device id 0x%x\n", 1238198987Sjhb adapter->hw.device_id); 1239129794Stackerman } 1240129794Stackerman 1241129794Stackerman return; 1242129794Stackerman} 1243129794Stackerman 1244129794Stackermanstatic int 1245129794Stackermanixgb_allocate_pci_resources(struct adapter * adapter) 1246129794Stackerman{ 1247129794Stackerman int rid; 1248129794Stackerman device_t dev = adapter->dev; 1249129794Stackerman 1250129794Stackerman rid = IXGB_MMBA; 1251129794Stackerman adapter->res_memory = bus_alloc_resource(dev, SYS_RES_MEMORY, 1252129794Stackerman &rid, 0, ~0, 1, 1253129794Stackerman RF_ACTIVE); 1254129794Stackerman if (!(adapter->res_memory)) { 1255198987Sjhb device_printf(dev, "Unable to allocate bus resource: memory\n"); 1256129794Stackerman return (ENXIO); 1257129794Stackerman } 1258129794Stackerman adapter->osdep.mem_bus_space_tag = 1259129794Stackerman rman_get_bustag(adapter->res_memory); 1260129794Stackerman adapter->osdep.mem_bus_space_handle = 1261129794Stackerman rman_get_bushandle(adapter->res_memory); 1262129794Stackerman adapter->hw.hw_addr = (uint8_t *) & adapter->osdep.mem_bus_space_handle; 1263129794Stackerman 1264129794Stackerman rid = 0x0; 1265129794Stackerman adapter->res_interrupt = bus_alloc_resource(dev, SYS_RES_IRQ, 1266129794Stackerman &rid, 0, ~0, 1, 1267129794Stackerman RF_SHAREABLE | RF_ACTIVE); 1268129794Stackerman if (!(adapter->res_interrupt)) { 1269198987Sjhb device_printf(dev, 1270198987Sjhb "Unable to allocate bus resource: interrupt\n"); 1271129794Stackerman return (ENXIO); 1272129794Stackerman } 1273144651Salc if (bus_setup_intr(dev, adapter->res_interrupt, 1274144651Salc INTR_TYPE_NET | INTR_MPSAFE, 1275166901Spiso NULL, (void (*) (void *))ixgb_intr, adapter, 1276129794Stackerman &adapter->int_handler_tag)) { 1277198987Sjhb device_printf(dev, "Error registering interrupt handler!\n"); 1278129794Stackerman return (ENXIO); 1279129794Stackerman } 1280129794Stackerman adapter->hw.back = &adapter->osdep; 1281129794Stackerman 1282129794Stackerman return (0); 1283129794Stackerman} 1284129794Stackerman 1285129794Stackermanstatic void 1286129794Stackermanixgb_free_pci_resources(struct adapter * adapter) 1287129794Stackerman{ 1288129794Stackerman device_t dev = adapter->dev; 1289129794Stackerman 1290129794Stackerman if (adapter->res_interrupt != NULL) { 1291129794Stackerman bus_teardown_intr(dev, adapter->res_interrupt, 1292129794Stackerman adapter->int_handler_tag); 1293129794Stackerman bus_release_resource(dev, SYS_RES_IRQ, 0, 1294129794Stackerman adapter->res_interrupt); 1295129794Stackerman } 1296129794Stackerman if (adapter->res_memory != NULL) { 1297129794Stackerman bus_release_resource(dev, SYS_RES_MEMORY, IXGB_MMBA, 1298129794Stackerman adapter->res_memory); 1299129794Stackerman } 1300129794Stackerman if (adapter->res_ioport != NULL) { 1301129794Stackerman bus_release_resource(dev, SYS_RES_IOPORT, adapter->io_rid, 1302129794Stackerman adapter->res_ioport); 1303129794Stackerman } 1304129794Stackerman return; 1305129794Stackerman} 1306129794Stackerman 1307129794Stackerman/********************************************************************* 1308129794Stackerman * 1309129794Stackerman * Initialize the hardware to a configuration as specified by the 1310129794Stackerman * adapter structure. The controller is reset, the EEPROM is 1311129794Stackerman * verified, the MAC address is set, then the shared initialization 1312129794Stackerman * routines are called. 1313129794Stackerman * 1314129794Stackerman **********************************************************************/ 1315129794Stackermanstatic int 1316129794Stackermanixgb_hardware_init(struct adapter * adapter) 1317129794Stackerman{ 1318129794Stackerman /* Issue a global reset */ 1319129794Stackerman adapter->hw.adapter_stopped = FALSE; 1320129794Stackerman ixgb_adapter_stop(&adapter->hw); 1321129794Stackerman 1322129794Stackerman /* Make sure we have a good EEPROM before we read from it */ 1323129794Stackerman if (!ixgb_validate_eeprom_checksum(&adapter->hw)) { 1324198987Sjhb device_printf(adapter->dev, 1325198987Sjhb "The EEPROM Checksum Is Not Valid\n"); 1326129794Stackerman return (EIO); 1327129794Stackerman } 1328129794Stackerman if (!ixgb_init_hw(&adapter->hw)) { 1329198987Sjhb device_printf(adapter->dev, "Hardware Initialization Failed"); 1330129794Stackerman return (EIO); 1331129794Stackerman } 1332129794Stackerman 1333129794Stackerman return (0); 1334129794Stackerman} 1335129794Stackerman 1336129794Stackerman/********************************************************************* 1337129794Stackerman * 1338129794Stackerman * Setup networking device structure and register an interface. 1339129794Stackerman * 1340129794Stackerman **********************************************************************/ 1341211907Syongaristatic int 1342129794Stackermanixgb_setup_interface(device_t dev, struct adapter * adapter) 1343129794Stackerman{ 1344129794Stackerman struct ifnet *ifp; 1345129794Stackerman INIT_DEBUGOUT("ixgb_setup_interface: begin"); 1346129794Stackerman 1347147256Sbrooks ifp = adapter->ifp = if_alloc(IFT_ETHER); 1348211907Syongari if (ifp == NULL) { 1349211907Syongari device_printf(dev, "can not allocate ifnet structure\n"); 1350211907Syongari return (-1); 1351211907Syongari } 1352129794Stackerman#if __FreeBSD_version >= 502000 1353129794Stackerman if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 1354129794Stackerman#else 1355198987Sjhb ifp->if_unit = device_get_unit(dev); 1356129794Stackerman ifp->if_name = "ixgb"; 1357129794Stackerman#endif 1358129794Stackerman ifp->if_baudrate = 1000000000; 1359129794Stackerman ifp->if_init = ixgb_init; 1360129794Stackerman ifp->if_softc = adapter; 1361144651Salc ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1362129794Stackerman ifp->if_ioctl = ixgb_ioctl; 1363129794Stackerman ifp->if_start = ixgb_start; 1364129794Stackerman ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 1; 1365129794Stackerman 1366129794Stackerman#if __FreeBSD_version < 500000 1367129794Stackerman ether_ifattach(ifp, ETHER_BPF_SUPPORTED); 1368129794Stackerman#else 1369147256Sbrooks ether_ifattach(ifp, adapter->hw.curr_mac_addr); 1370129794Stackerman#endif 1371129794Stackerman 1372129794Stackerman ifp->if_capabilities = IFCAP_HWCSUM; 1373129794Stackerman 1374129794Stackerman /* 1375129794Stackerman * Tell the upper layer(s) we support long frames. 1376129794Stackerman */ 1377129794Stackerman ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 1378129794Stackerman 1379129794Stackerman#if __FreeBSD_version >= 500000 1380129794Stackerman ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 1381129794Stackerman#endif 1382148637Sbrueffer 1383148637Sbrueffer ifp->if_capenable = ifp->if_capabilities; 1384148637Sbrueffer 1385150789Sglebius#ifdef DEVICE_POLLING 1386150789Sglebius ifp->if_capabilities |= IFCAP_POLLING; 1387150789Sglebius#endif 1388150789Sglebius 1389129794Stackerman /* 1390129794Stackerman * Specify the media types supported by this adapter and register 1391129794Stackerman * callbacks to update media and link information 1392129794Stackerman */ 1393129794Stackerman ifmedia_init(&adapter->media, IFM_IMASK, ixgb_media_change, 1394129794Stackerman ixgb_media_status); 1395129794Stackerman ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX | IFM_FDX, 1396129794Stackerman 0, NULL); 1397129794Stackerman ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 1398129794Stackerman 0, NULL); 1399129794Stackerman ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); 1400129794Stackerman ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); 1401129794Stackerman 1402211907Syongari return (0); 1403129794Stackerman} 1404129794Stackerman 1405129794Stackerman/******************************************************************** 1406129794Stackerman * Manage DMA'able memory. 1407129794Stackerman *******************************************************************/ 1408129794Stackermanstatic void 1409129794Stackermanixgb_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg, int error) 1410129794Stackerman{ 1411129794Stackerman if (error) 1412129794Stackerman return; 1413129794Stackerman *(bus_addr_t *) arg = segs->ds_addr; 1414129794Stackerman return; 1415129794Stackerman} 1416129794Stackerman 1417129794Stackermanstatic int 1418129794Stackermanixgb_dma_malloc(struct adapter * adapter, bus_size_t size, 1419129794Stackerman struct ixgb_dma_alloc * dma, int mapflags) 1420129794Stackerman{ 1421198987Sjhb device_t dev; 1422129794Stackerman int r; 1423129794Stackerman 1424198987Sjhb dev = adapter->dev; 1425232874Sscottl r = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 1426129794Stackerman PAGE_SIZE, 0, /* alignment, bounds */ 1427129794Stackerman BUS_SPACE_MAXADDR, /* lowaddr */ 1428129794Stackerman BUS_SPACE_MAXADDR, /* highaddr */ 1429129794Stackerman NULL, NULL, /* filter, filterarg */ 1430129794Stackerman size, /* maxsize */ 1431129794Stackerman 1, /* nsegments */ 1432129794Stackerman size, /* maxsegsize */ 1433129794Stackerman BUS_DMA_ALLOCNOW, /* flags */ 1434129794Stackerman#if __FreeBSD_version >= 502000 1435129794Stackerman NULL, /* lockfunc */ 1436129794Stackerman NULL, /* lockfuncarg */ 1437129794Stackerman#endif 1438129794Stackerman &dma->dma_tag); 1439129794Stackerman if (r != 0) { 1440198987Sjhb device_printf(dev, "ixgb_dma_malloc: bus_dma_tag_create failed; " 1441198987Sjhb "error %u\n", r); 1442129794Stackerman goto fail_0; 1443129794Stackerman } 1444129794Stackerman r = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1445129794Stackerman BUS_DMA_NOWAIT, &dma->dma_map); 1446129794Stackerman if (r != 0) { 1447198987Sjhb device_printf(dev, "ixgb_dma_malloc: bus_dmamem_alloc failed; " 1448198987Sjhb "error %u\n", r); 1449144183Smux goto fail_1; 1450129794Stackerman } 1451129794Stackerman r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, 1452129794Stackerman size, 1453129794Stackerman ixgb_dmamap_cb, 1454129794Stackerman &dma->dma_paddr, 1455129794Stackerman mapflags | BUS_DMA_NOWAIT); 1456129794Stackerman if (r != 0) { 1457198987Sjhb device_printf(dev, "ixgb_dma_malloc: bus_dmamap_load failed; " 1458198987Sjhb "error %u\n", r); 1459144183Smux goto fail_2; 1460129794Stackerman } 1461129794Stackerman dma->dma_size = size; 1462129794Stackerman return (0); 1463129794Stackermanfail_2: 1464129794Stackerman bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1465129794Stackermanfail_1: 1466129794Stackerman bus_dma_tag_destroy(dma->dma_tag); 1467129794Stackermanfail_0: 1468129794Stackerman dma->dma_map = NULL; 1469129794Stackerman dma->dma_tag = NULL; 1470129794Stackerman return (r); 1471129794Stackerman} 1472129794Stackerman 1473129794Stackerman 1474129794Stackerman 1475129794Stackermanstatic void 1476129794Stackermanixgb_dma_free(struct adapter * adapter, struct ixgb_dma_alloc * dma) 1477129794Stackerman{ 1478129794Stackerman bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1479129794Stackerman bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1480129794Stackerman bus_dma_tag_destroy(dma->dma_tag); 1481129794Stackerman} 1482129794Stackerman 1483129794Stackerman/********************************************************************* 1484129794Stackerman * 1485129794Stackerman * Allocate memory for tx_buffer structures. The tx_buffer stores all 1486129794Stackerman * the information needed to transmit a packet on the wire. 1487129794Stackerman * 1488129794Stackerman **********************************************************************/ 1489129794Stackermanstatic int 1490129794Stackermanixgb_allocate_transmit_structures(struct adapter * adapter) 1491129794Stackerman{ 1492129794Stackerman if (!(adapter->tx_buffer_area = 1493129794Stackerman (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) * 1494129794Stackerman adapter->num_tx_desc, M_DEVBUF, 1495129794Stackerman M_NOWAIT | M_ZERO))) { 1496198987Sjhb device_printf(adapter->dev, 1497198987Sjhb "Unable to allocate tx_buffer memory\n"); 1498129794Stackerman return ENOMEM; 1499129794Stackerman } 1500129794Stackerman bzero(adapter->tx_buffer_area, 1501129794Stackerman sizeof(struct ixgb_buffer) * adapter->num_tx_desc); 1502129794Stackerman 1503129794Stackerman return 0; 1504129794Stackerman} 1505129794Stackerman 1506129794Stackerman/********************************************************************* 1507129794Stackerman * 1508129794Stackerman * Allocate and initialize transmit structures. 1509129794Stackerman * 1510129794Stackerman **********************************************************************/ 1511129794Stackermanstatic int 1512129794Stackermanixgb_setup_transmit_structures(struct adapter * adapter) 1513129794Stackerman{ 1514129794Stackerman /* 1515129794Stackerman * Setup DMA descriptor areas. 1516129794Stackerman */ 1517232874Sscottl if (bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */ 1518129794Stackerman PAGE_SIZE, 0, /* alignment, bounds */ 1519129794Stackerman BUS_SPACE_MAXADDR, /* lowaddr */ 1520129794Stackerman BUS_SPACE_MAXADDR, /* highaddr */ 1521129794Stackerman NULL, NULL, /* filter, filterarg */ 1522129794Stackerman MCLBYTES * IXGB_MAX_SCATTER, /* maxsize */ 1523129794Stackerman IXGB_MAX_SCATTER, /* nsegments */ 1524129794Stackerman MCLBYTES, /* maxsegsize */ 1525129794Stackerman BUS_DMA_ALLOCNOW, /* flags */ 1526129794Stackerman#if __FreeBSD_version >= 502000 1527129794Stackerman NULL, /* lockfunc */ 1528129794Stackerman NULL, /* lockfuncarg */ 1529129794Stackerman#endif 1530129794Stackerman &adapter->txtag)) { 1531198987Sjhb device_printf(adapter->dev, "Unable to allocate TX DMA tag\n"); 1532129794Stackerman return (ENOMEM); 1533129794Stackerman } 1534129794Stackerman if (ixgb_allocate_transmit_structures(adapter)) 1535129794Stackerman return ENOMEM; 1536129794Stackerman 1537129794Stackerman bzero((void *)adapter->tx_desc_base, 1538129794Stackerman (sizeof(struct ixgb_tx_desc)) * adapter->num_tx_desc); 1539129794Stackerman 1540129794Stackerman adapter->next_avail_tx_desc = 0; 1541129794Stackerman adapter->oldest_used_tx_desc = 0; 1542129794Stackerman 1543129794Stackerman /* Set number of descriptors available */ 1544129794Stackerman adapter->num_tx_desc_avail = adapter->num_tx_desc; 1545129794Stackerman 1546129794Stackerman /* Set checksum context */ 1547129794Stackerman adapter->active_checksum_context = OFFLOAD_NONE; 1548129794Stackerman 1549129794Stackerman return 0; 1550129794Stackerman} 1551129794Stackerman 1552129794Stackerman/********************************************************************* 1553129794Stackerman * 1554129794Stackerman * Enable transmit unit. 1555129794Stackerman * 1556129794Stackerman **********************************************************************/ 1557129794Stackermanstatic void 1558129794Stackermanixgb_initialize_transmit_unit(struct adapter * adapter) 1559129794Stackerman{ 1560129794Stackerman u_int32_t reg_tctl; 1561144183Smux u_int64_t tdba = adapter->txdma.dma_paddr; 1562129794Stackerman 1563129794Stackerman /* Setup the Base and Length of the Tx Descriptor Ring */ 1564129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDBAL, 1565129794Stackerman (tdba & 0x00000000ffffffffULL)); 1566129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32)); 1567129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDLEN, 1568129794Stackerman adapter->num_tx_desc * 1569129794Stackerman sizeof(struct ixgb_tx_desc)); 1570129794Stackerman 1571129794Stackerman /* Setup the HW Tx Head and Tail descriptor pointers */ 1572129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDH, 0); 1573129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDT, 0); 1574129794Stackerman 1575129794Stackerman 1576129794Stackerman HW_DEBUGOUT2("Base = %x, Length = %x\n", 1577129794Stackerman IXGB_READ_REG(&adapter->hw, TDBAL), 1578129794Stackerman IXGB_READ_REG(&adapter->hw, TDLEN)); 1579129794Stackerman 1580129794Stackerman IXGB_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay); 1581129794Stackerman 1582129794Stackerman 1583129794Stackerman /* Program the Transmit Control Register */ 1584129794Stackerman reg_tctl = IXGB_READ_REG(&adapter->hw, TCTL); 1585129794Stackerman reg_tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE; 1586129794Stackerman IXGB_WRITE_REG(&adapter->hw, TCTL, reg_tctl); 1587129794Stackerman 1588129794Stackerman /* Setup Transmit Descriptor Settings for this adapter */ 1589129794Stackerman adapter->txd_cmd = IXGB_TX_DESC_TYPE | IXGB_TX_DESC_CMD_RS; 1590129794Stackerman 1591129794Stackerman if (adapter->tx_int_delay > 0) 1592129794Stackerman adapter->txd_cmd |= IXGB_TX_DESC_CMD_IDE; 1593129794Stackerman return; 1594129794Stackerman} 1595129794Stackerman 1596129794Stackerman/********************************************************************* 1597129794Stackerman * 1598129794Stackerman * Free all transmit related data structures. 1599129794Stackerman * 1600129794Stackerman **********************************************************************/ 1601129794Stackermanstatic void 1602129794Stackermanixgb_free_transmit_structures(struct adapter * adapter) 1603129794Stackerman{ 1604129794Stackerman struct ixgb_buffer *tx_buffer; 1605129794Stackerman int i; 1606129794Stackerman 1607129794Stackerman INIT_DEBUGOUT("free_transmit_structures: begin"); 1608129794Stackerman 1609129794Stackerman if (adapter->tx_buffer_area != NULL) { 1610129794Stackerman tx_buffer = adapter->tx_buffer_area; 1611129794Stackerman for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) { 1612129794Stackerman if (tx_buffer->m_head != NULL) { 1613129794Stackerman bus_dmamap_unload(adapter->txtag, tx_buffer->map); 1614129794Stackerman bus_dmamap_destroy(adapter->txtag, tx_buffer->map); 1615129794Stackerman m_freem(tx_buffer->m_head); 1616129794Stackerman } 1617129794Stackerman tx_buffer->m_head = NULL; 1618129794Stackerman } 1619129794Stackerman } 1620129794Stackerman if (adapter->tx_buffer_area != NULL) { 1621129794Stackerman free(adapter->tx_buffer_area, M_DEVBUF); 1622129794Stackerman adapter->tx_buffer_area = NULL; 1623129794Stackerman } 1624129794Stackerman if (adapter->txtag != NULL) { 1625129794Stackerman bus_dma_tag_destroy(adapter->txtag); 1626129794Stackerman adapter->txtag = NULL; 1627129794Stackerman } 1628129794Stackerman return; 1629129794Stackerman} 1630129794Stackerman 1631129794Stackerman/********************************************************************* 1632129794Stackerman * 1633129794Stackerman * The offload context needs to be set when we transfer the first 1634129794Stackerman * packet of a particular protocol (TCP/UDP). We change the 1635129794Stackerman * context only if the protocol type changes. 1636129794Stackerman * 1637129794Stackerman **********************************************************************/ 1638129794Stackermanstatic void 1639129794Stackermanixgb_transmit_checksum_setup(struct adapter * adapter, 1640129794Stackerman struct mbuf * mp, 1641129794Stackerman u_int8_t * txd_popts) 1642129794Stackerman{ 1643129794Stackerman struct ixgb_context_desc *TXD; 1644129794Stackerman struct ixgb_buffer *tx_buffer; 1645129794Stackerman int curr_txd; 1646129794Stackerman 1647129794Stackerman if (mp->m_pkthdr.csum_flags) { 1648129794Stackerman 1649129794Stackerman if (mp->m_pkthdr.csum_flags & CSUM_TCP) { 1650129794Stackerman *txd_popts = IXGB_TX_DESC_POPTS_TXSM; 1651129794Stackerman if (adapter->active_checksum_context == OFFLOAD_TCP_IP) 1652129794Stackerman return; 1653129794Stackerman else 1654129794Stackerman adapter->active_checksum_context = OFFLOAD_TCP_IP; 1655129794Stackerman } else if (mp->m_pkthdr.csum_flags & CSUM_UDP) { 1656129794Stackerman *txd_popts = IXGB_TX_DESC_POPTS_TXSM; 1657129794Stackerman if (adapter->active_checksum_context == OFFLOAD_UDP_IP) 1658129794Stackerman return; 1659129794Stackerman else 1660129794Stackerman adapter->active_checksum_context = OFFLOAD_UDP_IP; 1661129794Stackerman } else { 1662129794Stackerman *txd_popts = 0; 1663129794Stackerman return; 1664129794Stackerman } 1665129794Stackerman } else { 1666129794Stackerman *txd_popts = 0; 1667129794Stackerman return; 1668129794Stackerman } 1669129794Stackerman 1670129794Stackerman /* 1671129794Stackerman * If we reach this point, the checksum offload context needs to be 1672129794Stackerman * reset. 1673129794Stackerman */ 1674129794Stackerman curr_txd = adapter->next_avail_tx_desc; 1675129794Stackerman tx_buffer = &adapter->tx_buffer_area[curr_txd]; 1676129794Stackerman TXD = (struct ixgb_context_desc *) & adapter->tx_desc_base[curr_txd]; 1677129794Stackerman 1678129794Stackerman 1679129794Stackerman TXD->tucss = ENET_HEADER_SIZE + sizeof(struct ip); 1680129794Stackerman TXD->tucse = 0; 1681129794Stackerman 1682129794Stackerman TXD->mss = 0; 1683129794Stackerman 1684129794Stackerman if (adapter->active_checksum_context == OFFLOAD_TCP_IP) { 1685129794Stackerman TXD->tucso = 1686129794Stackerman ENET_HEADER_SIZE + sizeof(struct ip) + 1687129794Stackerman offsetof(struct tcphdr, th_sum); 1688129794Stackerman } else if (adapter->active_checksum_context == OFFLOAD_UDP_IP) { 1689129794Stackerman TXD->tucso = 1690129794Stackerman ENET_HEADER_SIZE + sizeof(struct ip) + 1691129794Stackerman offsetof(struct udphdr, uh_sum); 1692129794Stackerman } 1693129794Stackerman TXD->cmd_type_len = IXGB_CONTEXT_DESC_CMD_TCP | IXGB_TX_DESC_CMD_RS | IXGB_CONTEXT_DESC_CMD_IDE; 1694129794Stackerman 1695129794Stackerman tx_buffer->m_head = NULL; 1696129794Stackerman 1697129794Stackerman if (++curr_txd == adapter->num_tx_desc) 1698129794Stackerman curr_txd = 0; 1699129794Stackerman 1700129794Stackerman adapter->num_tx_desc_avail--; 1701129794Stackerman adapter->next_avail_tx_desc = curr_txd; 1702129794Stackerman return; 1703129794Stackerman} 1704129794Stackerman 1705129794Stackerman/********************************************************************** 1706129794Stackerman * 1707129794Stackerman * Examine each tx_buffer in the used queue. If the hardware is done 1708129794Stackerman * processing the packet then free associated resources. The 1709129794Stackerman * tx_buffer is put back on the free queue. 1710129794Stackerman * 1711129794Stackerman **********************************************************************/ 1712129794Stackermanstatic void 1713129794Stackermanixgb_clean_transmit_interrupts(struct adapter * adapter) 1714129794Stackerman{ 1715129794Stackerman int i, num_avail; 1716129794Stackerman struct ixgb_buffer *tx_buffer; 1717129794Stackerman struct ixgb_tx_desc *tx_desc; 1718129794Stackerman 1719144651Salc IXGB_LOCK_ASSERT(adapter); 1720129794Stackerman 1721129794Stackerman if (adapter->num_tx_desc_avail == adapter->num_tx_desc) 1722129794Stackerman return; 1723129794Stackerman 1724129794Stackerman#ifdef _SV_ 1725129794Stackerman adapter->clean_tx_interrupts++; 1726129794Stackerman#endif 1727129794Stackerman num_avail = adapter->num_tx_desc_avail; 1728129794Stackerman i = adapter->oldest_used_tx_desc; 1729129794Stackerman 1730129794Stackerman tx_buffer = &adapter->tx_buffer_area[i]; 1731129794Stackerman tx_desc = &adapter->tx_desc_base[i]; 1732129794Stackerman 1733129794Stackerman while (tx_desc->status & IXGB_TX_DESC_STATUS_DD) { 1734129794Stackerman 1735129794Stackerman tx_desc->status = 0; 1736129794Stackerman num_avail++; 1737129794Stackerman 1738129794Stackerman if (tx_buffer->m_head) { 1739129794Stackerman bus_dmamap_sync(adapter->txtag, tx_buffer->map, 1740129794Stackerman BUS_DMASYNC_POSTWRITE); 1741129794Stackerman bus_dmamap_unload(adapter->txtag, tx_buffer->map); 1742129794Stackerman bus_dmamap_destroy(adapter->txtag, tx_buffer->map); 1743129794Stackerman m_freem(tx_buffer->m_head); 1744129794Stackerman tx_buffer->m_head = NULL; 1745129794Stackerman } 1746129794Stackerman if (++i == adapter->num_tx_desc) 1747129794Stackerman i = 0; 1748129794Stackerman 1749129794Stackerman tx_buffer = &adapter->tx_buffer_area[i]; 1750129794Stackerman tx_desc = &adapter->tx_desc_base[i]; 1751129794Stackerman } 1752129794Stackerman 1753129794Stackerman adapter->oldest_used_tx_desc = i; 1754129794Stackerman 1755129794Stackerman /* 1756148887Srwatson * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that 1757129794Stackerman * it is OK to send packets. If there are no pending descriptors, 1758129794Stackerman * clear the timeout. Otherwise, if some descriptors have been freed, 1759129794Stackerman * restart the timeout. 1760129794Stackerman */ 1761129794Stackerman if (num_avail > IXGB_TX_CLEANUP_THRESHOLD) { 1762147256Sbrooks struct ifnet *ifp = adapter->ifp; 1763129794Stackerman 1764148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1765129794Stackerman if (num_avail == adapter->num_tx_desc) 1766199539Sjhb adapter->tx_timer = 0; 1767129794Stackerman else if (num_avail == adapter->num_tx_desc_avail) 1768199539Sjhb adapter->tx_timer = IXGB_TX_TIMEOUT; 1769129794Stackerman } 1770129794Stackerman adapter->num_tx_desc_avail = num_avail; 1771129794Stackerman return; 1772129794Stackerman} 1773129794Stackerman 1774129794Stackerman 1775129794Stackerman/********************************************************************* 1776129794Stackerman * 1777129794Stackerman * Get a buffer from system mbuf buffer pool. 1778129794Stackerman * 1779129794Stackerman **********************************************************************/ 1780129794Stackermanstatic int 1781129794Stackermanixgb_get_buf(int i, struct adapter * adapter, 1782129794Stackerman struct mbuf * nmp) 1783129794Stackerman{ 1784129794Stackerman register struct mbuf *mp = nmp; 1785129794Stackerman struct ixgb_buffer *rx_buffer; 1786129794Stackerman struct ifnet *ifp; 1787129794Stackerman bus_addr_t paddr; 1788129794Stackerman int error; 1789129794Stackerman 1790147256Sbrooks ifp = adapter->ifp; 1791129794Stackerman 1792129794Stackerman if (mp == NULL) { 1793129794Stackerman 1794243857Sglebius mp = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 1795129794Stackerman 1796129794Stackerman if (mp == NULL) { 1797129794Stackerman adapter->mbuf_alloc_failed++; 1798129794Stackerman return (ENOBUFS); 1799129794Stackerman } 1800129794Stackerman mp->m_len = mp->m_pkthdr.len = MCLBYTES; 1801129794Stackerman } else { 1802129794Stackerman mp->m_len = mp->m_pkthdr.len = MCLBYTES; 1803129794Stackerman mp->m_data = mp->m_ext.ext_buf; 1804129794Stackerman mp->m_next = NULL; 1805129794Stackerman } 1806129794Stackerman 1807129794Stackerman if (ifp->if_mtu <= ETHERMTU) { 1808129794Stackerman m_adj(mp, ETHER_ALIGN); 1809129794Stackerman } 1810129794Stackerman rx_buffer = &adapter->rx_buffer_area[i]; 1811129794Stackerman 1812129794Stackerman /* 1813129794Stackerman * Using memory from the mbuf cluster pool, invoke the bus_dma 1814129794Stackerman * machinery to arrange the memory mapping. 1815129794Stackerman */ 1816129794Stackerman error = bus_dmamap_load(adapter->rxtag, rx_buffer->map, 1817129794Stackerman mtod(mp, void *), mp->m_len, 1818129794Stackerman ixgb_dmamap_cb, &paddr, 0); 1819129794Stackerman if (error) { 1820129794Stackerman m_free(mp); 1821129794Stackerman return (error); 1822129794Stackerman } 1823129794Stackerman rx_buffer->m_head = mp; 1824129794Stackerman adapter->rx_desc_base[i].buff_addr = htole64(paddr); 1825129794Stackerman bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD); 1826129794Stackerman 1827129794Stackerman return (0); 1828129794Stackerman} 1829129794Stackerman 1830129794Stackerman/********************************************************************* 1831129794Stackerman * 1832129794Stackerman * Allocate memory for rx_buffer structures. Since we use one 1833129794Stackerman * rx_buffer per received packet, the maximum number of rx_buffer's 1834129794Stackerman * that we'll need is equal to the number of receive descriptors 1835129794Stackerman * that we've allocated. 1836129794Stackerman * 1837129794Stackerman **********************************************************************/ 1838129794Stackermanstatic int 1839129794Stackermanixgb_allocate_receive_structures(struct adapter * adapter) 1840129794Stackerman{ 1841129794Stackerman int i, error; 1842129794Stackerman struct ixgb_buffer *rx_buffer; 1843129794Stackerman 1844129794Stackerman if (!(adapter->rx_buffer_area = 1845129794Stackerman (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) * 1846129794Stackerman adapter->num_rx_desc, M_DEVBUF, 1847129794Stackerman M_NOWAIT | M_ZERO))) { 1848198987Sjhb device_printf(adapter->dev, 1849198987Sjhb "Unable to allocate rx_buffer memory\n"); 1850129794Stackerman return (ENOMEM); 1851129794Stackerman } 1852129794Stackerman bzero(adapter->rx_buffer_area, 1853129794Stackerman sizeof(struct ixgb_buffer) * adapter->num_rx_desc); 1854129794Stackerman 1855232874Sscottl error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev),/* parent */ 1856129794Stackerman PAGE_SIZE, 0, /* alignment, bounds */ 1857129794Stackerman BUS_SPACE_MAXADDR, /* lowaddr */ 1858129794Stackerman BUS_SPACE_MAXADDR, /* highaddr */ 1859129794Stackerman NULL, NULL, /* filter, filterarg */ 1860129794Stackerman MCLBYTES, /* maxsize */ 1861129794Stackerman 1, /* nsegments */ 1862129794Stackerman MCLBYTES, /* maxsegsize */ 1863129794Stackerman BUS_DMA_ALLOCNOW, /* flags */ 1864129794Stackerman#if __FreeBSD_version >= 502000 1865129794Stackerman NULL, /* lockfunc */ 1866129794Stackerman NULL, /* lockfuncarg */ 1867129794Stackerman#endif 1868129794Stackerman &adapter->rxtag); 1869129794Stackerman if (error != 0) { 1870198987Sjhb device_printf(adapter->dev, "ixgb_allocate_receive_structures: " 1871129794Stackerman "bus_dma_tag_create failed; error %u\n", 1872198987Sjhb error); 1873129794Stackerman goto fail_0; 1874129794Stackerman } 1875129794Stackerman rx_buffer = adapter->rx_buffer_area; 1876129794Stackerman for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 1877129794Stackerman error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT, 1878129794Stackerman &rx_buffer->map); 1879129794Stackerman if (error != 0) { 1880198987Sjhb device_printf(adapter->dev, 1881198987Sjhb "ixgb_allocate_receive_structures: " 1882129794Stackerman "bus_dmamap_create failed; error %u\n", 1883198987Sjhb error); 1884129794Stackerman goto fail_1; 1885129794Stackerman } 1886129794Stackerman } 1887129794Stackerman 1888129794Stackerman for (i = 0; i < adapter->num_rx_desc; i++) { 1889129794Stackerman if (ixgb_get_buf(i, adapter, NULL) == ENOBUFS) { 1890129794Stackerman adapter->rx_buffer_area[i].m_head = NULL; 1891129794Stackerman adapter->rx_desc_base[i].buff_addr = 0; 1892129794Stackerman return (ENOBUFS); 1893129794Stackerman } 1894129794Stackerman } 1895129794Stackerman 1896129794Stackerman return (0); 1897129794Stackermanfail_1: 1898129794Stackerman bus_dma_tag_destroy(adapter->rxtag); 1899129794Stackermanfail_0: 1900129794Stackerman adapter->rxtag = NULL; 1901129794Stackerman free(adapter->rx_buffer_area, M_DEVBUF); 1902129794Stackerman adapter->rx_buffer_area = NULL; 1903129794Stackerman return (error); 1904129794Stackerman} 1905129794Stackerman 1906129794Stackerman/********************************************************************* 1907129794Stackerman * 1908129794Stackerman * Allocate and initialize receive structures. 1909129794Stackerman * 1910129794Stackerman **********************************************************************/ 1911129794Stackermanstatic int 1912129794Stackermanixgb_setup_receive_structures(struct adapter * adapter) 1913129794Stackerman{ 1914129794Stackerman bzero((void *)adapter->rx_desc_base, 1915129794Stackerman (sizeof(struct ixgb_rx_desc)) * adapter->num_rx_desc); 1916129794Stackerman 1917129794Stackerman if (ixgb_allocate_receive_structures(adapter)) 1918129794Stackerman return ENOMEM; 1919129794Stackerman 1920129794Stackerman /* Setup our descriptor pointers */ 1921129794Stackerman adapter->next_rx_desc_to_check = 0; 1922129794Stackerman adapter->next_rx_desc_to_use = 0; 1923129794Stackerman return (0); 1924129794Stackerman} 1925129794Stackerman 1926129794Stackerman/********************************************************************* 1927129794Stackerman * 1928129794Stackerman * Enable receive unit. 1929129794Stackerman * 1930129794Stackerman **********************************************************************/ 1931129794Stackermanstatic void 1932129794Stackermanixgb_initialize_receive_unit(struct adapter * adapter) 1933129794Stackerman{ 1934129794Stackerman u_int32_t reg_rctl; 1935129794Stackerman u_int32_t reg_rxcsum; 1936129794Stackerman u_int32_t reg_rxdctl; 1937129794Stackerman struct ifnet *ifp; 1938144183Smux u_int64_t rdba = adapter->rxdma.dma_paddr; 1939129794Stackerman 1940147256Sbrooks ifp = adapter->ifp; 1941129794Stackerman 1942129794Stackerman /* 1943129794Stackerman * Make sure receives are disabled while setting up the descriptor 1944129794Stackerman * ring 1945129794Stackerman */ 1946129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1947129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl & ~IXGB_RCTL_RXEN); 1948129794Stackerman 1949129794Stackerman /* Set the Receive Delay Timer Register */ 1950129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDTR, 1951129794Stackerman adapter->rx_int_delay); 1952129794Stackerman 1953129794Stackerman 1954129794Stackerman /* Setup the Base and Length of the Rx Descriptor Ring */ 1955129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDBAL, 1956129794Stackerman (rdba & 0x00000000ffffffffULL)); 1957129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32)); 1958129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDLEN, adapter->num_rx_desc * 1959129794Stackerman sizeof(struct ixgb_rx_desc)); 1960129794Stackerman 1961129794Stackerman /* Setup the HW Rx Head and Tail Descriptor Pointers */ 1962129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDH, 0); 1963129794Stackerman 1964129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDT, adapter->num_rx_desc - 1); 1965129794Stackerman 1966129794Stackerman 1967129794Stackerman 1968129794Stackerman reg_rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT 1969129794Stackerman | RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT 1970129794Stackerman | RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT; 1971129794Stackerman IXGB_WRITE_REG(&adapter->hw, RXDCTL, reg_rxdctl); 1972129794Stackerman 1973129794Stackerman 1974129794Stackerman adapter->raidc = 1; 1975129794Stackerman if (adapter->raidc) { 1976129794Stackerman uint32_t raidc; 1977129794Stackerman uint8_t poll_threshold; 1978129794Stackerman#define IXGB_RAIDC_POLL_DEFAULT 120 1979129794Stackerman 1980129794Stackerman poll_threshold = ((adapter->num_rx_desc - 1) >> 3); 1981129794Stackerman poll_threshold >>= 1; 1982129794Stackerman poll_threshold &= 0x3F; 1983129794Stackerman raidc = IXGB_RAIDC_EN | IXGB_RAIDC_RXT_GATE | 1984129794Stackerman (IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) | 1985129794Stackerman (adapter->rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) | 1986129794Stackerman poll_threshold; 1987129794Stackerman IXGB_WRITE_REG(&adapter->hw, RAIDC, raidc); 1988129794Stackerman } 1989129794Stackerman /* Enable Receive Checksum Offload for TCP and UDP ? */ 1990129794Stackerman if (ifp->if_capenable & IFCAP_RXCSUM) { 1991129794Stackerman reg_rxcsum = IXGB_READ_REG(&adapter->hw, RXCSUM); 1992129794Stackerman reg_rxcsum |= IXGB_RXCSUM_TUOFL; 1993129794Stackerman IXGB_WRITE_REG(&adapter->hw, RXCSUM, reg_rxcsum); 1994129794Stackerman } 1995129794Stackerman /* Setup the Receive Control Register */ 1996129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1997129794Stackerman reg_rctl &= ~(3 << IXGB_RCTL_MO_SHIFT); 1998129794Stackerman reg_rctl |= IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 | IXGB_RCTL_SECRC | 1999129794Stackerman IXGB_RCTL_CFF | 2000129794Stackerman (adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT); 2001129794Stackerman 2002129794Stackerman switch (adapter->rx_buffer_len) { 2003129794Stackerman default: 2004129794Stackerman case IXGB_RXBUFFER_2048: 2005129794Stackerman reg_rctl |= IXGB_RCTL_BSIZE_2048; 2006129794Stackerman break; 2007129794Stackerman case IXGB_RXBUFFER_4096: 2008129794Stackerman reg_rctl |= IXGB_RCTL_BSIZE_4096; 2009129794Stackerman break; 2010129794Stackerman case IXGB_RXBUFFER_8192: 2011129794Stackerman reg_rctl |= IXGB_RCTL_BSIZE_8192; 2012129794Stackerman break; 2013129794Stackerman case IXGB_RXBUFFER_16384: 2014129794Stackerman reg_rctl |= IXGB_RCTL_BSIZE_16384; 2015129794Stackerman break; 2016129794Stackerman } 2017129794Stackerman 2018129794Stackerman reg_rctl |= IXGB_RCTL_RXEN; 2019129794Stackerman 2020129794Stackerman 2021129794Stackerman /* Enable Receives */ 2022129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 2023129794Stackerman 2024129794Stackerman return; 2025129794Stackerman} 2026129794Stackerman 2027129794Stackerman/********************************************************************* 2028129794Stackerman * 2029129794Stackerman * Free receive related data structures. 2030129794Stackerman * 2031129794Stackerman **********************************************************************/ 2032129794Stackermanstatic void 2033129794Stackermanixgb_free_receive_structures(struct adapter * adapter) 2034129794Stackerman{ 2035129794Stackerman struct ixgb_buffer *rx_buffer; 2036129794Stackerman int i; 2037129794Stackerman 2038129794Stackerman INIT_DEBUGOUT("free_receive_structures: begin"); 2039129794Stackerman 2040129794Stackerman if (adapter->rx_buffer_area != NULL) { 2041129794Stackerman rx_buffer = adapter->rx_buffer_area; 2042129794Stackerman for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 2043129794Stackerman if (rx_buffer->map != NULL) { 2044129794Stackerman bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 2045129794Stackerman bus_dmamap_destroy(adapter->rxtag, rx_buffer->map); 2046129794Stackerman } 2047129794Stackerman if (rx_buffer->m_head != NULL) 2048129794Stackerman m_freem(rx_buffer->m_head); 2049129794Stackerman rx_buffer->m_head = NULL; 2050129794Stackerman } 2051129794Stackerman } 2052129794Stackerman if (adapter->rx_buffer_area != NULL) { 2053129794Stackerman free(adapter->rx_buffer_area, M_DEVBUF); 2054129794Stackerman adapter->rx_buffer_area = NULL; 2055129794Stackerman } 2056129794Stackerman if (adapter->rxtag != NULL) { 2057129794Stackerman bus_dma_tag_destroy(adapter->rxtag); 2058129794Stackerman adapter->rxtag = NULL; 2059129794Stackerman } 2060129794Stackerman return; 2061129794Stackerman} 2062129794Stackerman 2063129794Stackerman/********************************************************************* 2064129794Stackerman * 2065129794Stackerman * This routine executes in interrupt context. It replenishes 2066129794Stackerman * the mbufs in the descriptor and sends data which has been 2067129794Stackerman * dma'ed into host memory to upper layer. 2068129794Stackerman * 2069129794Stackerman * We loop at most count times if count is > 0, or until done if 2070129794Stackerman * count < 0. 2071129794Stackerman * 2072129794Stackerman *********************************************************************/ 2073193096Sattiliostatic int 2074129794Stackermanixgb_process_receive_interrupts(struct adapter * adapter, int count) 2075129794Stackerman{ 2076129794Stackerman struct ifnet *ifp; 2077129794Stackerman struct mbuf *mp; 2078129794Stackerman#if __FreeBSD_version < 500000 2079129794Stackerman struct ether_header *eh; 2080129794Stackerman#endif 2081129794Stackerman int eop = 0; 2082129794Stackerman int len; 2083129794Stackerman u_int8_t accept_frame = 0; 2084129794Stackerman int i; 2085129794Stackerman int next_to_use = 0; 2086129794Stackerman int eop_desc; 2087193096Sattilio int rx_npkts = 0; 2088129794Stackerman /* Pointer to the receive descriptor being examined. */ 2089129794Stackerman struct ixgb_rx_desc *current_desc; 2090129794Stackerman 2091144651Salc IXGB_LOCK_ASSERT(adapter); 2092144651Salc 2093147256Sbrooks ifp = adapter->ifp; 2094129794Stackerman i = adapter->next_rx_desc_to_check; 2095129794Stackerman next_to_use = adapter->next_rx_desc_to_use; 2096129794Stackerman eop_desc = adapter->next_rx_desc_to_check; 2097129794Stackerman current_desc = &adapter->rx_desc_base[i]; 2098129794Stackerman 2099129794Stackerman if (!((current_desc->status) & IXGB_RX_DESC_STATUS_DD)) { 2100129794Stackerman#ifdef _SV_ 2101129794Stackerman adapter->no_pkts_avail++; 2102129794Stackerman#endif 2103193096Sattilio return (rx_npkts); 2104129794Stackerman } 2105129794Stackerman while ((current_desc->status & IXGB_RX_DESC_STATUS_DD) && (count != 0)) { 2106129794Stackerman 2107129794Stackerman mp = adapter->rx_buffer_area[i].m_head; 2108129794Stackerman bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map, 2109129794Stackerman BUS_DMASYNC_POSTREAD); 2110129794Stackerman accept_frame = 1; 2111129794Stackerman if (current_desc->status & IXGB_RX_DESC_STATUS_EOP) { 2112129794Stackerman count--; 2113129794Stackerman eop = 1; 2114129794Stackerman } else { 2115129794Stackerman eop = 0; 2116129794Stackerman } 2117129794Stackerman len = current_desc->length; 2118129794Stackerman 2119129794Stackerman if (current_desc->errors & (IXGB_RX_DESC_ERRORS_CE | 2120129794Stackerman IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P | 2121129794Stackerman IXGB_RX_DESC_ERRORS_RXE)) { 2122129794Stackerman accept_frame = 0; 2123129794Stackerman } 2124129794Stackerman if (accept_frame) { 2125129794Stackerman 2126129794Stackerman /* Assign correct length to the current fragment */ 2127129794Stackerman mp->m_len = len; 2128129794Stackerman 2129129794Stackerman if (adapter->fmp == NULL) { 2130129794Stackerman mp->m_pkthdr.len = len; 2131129794Stackerman adapter->fmp = mp; /* Store the first mbuf */ 2132129794Stackerman adapter->lmp = mp; 2133129794Stackerman } else { 2134129794Stackerman /* Chain mbuf's together */ 2135129794Stackerman mp->m_flags &= ~M_PKTHDR; 2136129794Stackerman adapter->lmp->m_next = mp; 2137129794Stackerman adapter->lmp = adapter->lmp->m_next; 2138129794Stackerman adapter->fmp->m_pkthdr.len += len; 2139129794Stackerman } 2140129794Stackerman 2141129794Stackerman if (eop) { 2142129794Stackerman eop_desc = i; 2143129794Stackerman adapter->fmp->m_pkthdr.rcvif = ifp; 2144129794Stackerman 2145129794Stackerman#if __FreeBSD_version < 500000 2146129794Stackerman eh = mtod(adapter->fmp, struct ether_header *); 2147129794Stackerman 2148129794Stackerman /* Remove ethernet header from mbuf */ 2149129794Stackerman m_adj(adapter->fmp, sizeof(struct ether_header)); 2150129794Stackerman ixgb_receive_checksum(adapter, current_desc, 2151129794Stackerman adapter->fmp); 2152129794Stackerman 2153129794Stackerman if (current_desc->status & IXGB_RX_DESC_STATUS_VP) 2154129794Stackerman VLAN_INPUT_TAG(eh, adapter->fmp, 2155129794Stackerman current_desc->special); 2156129794Stackerman else 2157129794Stackerman ether_input(ifp, eh, adapter->fmp); 2158129794Stackerman#else 2159129794Stackerman ixgb_receive_checksum(adapter, current_desc, 2160129794Stackerman adapter->fmp); 2161162375Sandre#if __FreeBSD_version < 700000 2162129794Stackerman if (current_desc->status & IXGB_RX_DESC_STATUS_VP) 2163129794Stackerman VLAN_INPUT_TAG(ifp, adapter->fmp, 2164153512Sglebius current_desc->special); 2165162375Sandre#else 2166162375Sandre if (current_desc->status & IXGB_RX_DESC_STATUS_VP) { 2167162375Sandre adapter->fmp->m_pkthdr.ether_vtag = 2168162375Sandre current_desc->special; 2169162375Sandre adapter->fmp->m_flags |= M_VLANTAG; 2170162375Sandre } 2171162375Sandre#endif 2172129794Stackerman 2173144651Salc if (adapter->fmp != NULL) { 2174144651Salc IXGB_UNLOCK(adapter); 2175129794Stackerman (*ifp->if_input) (ifp, adapter->fmp); 2176144651Salc IXGB_LOCK(adapter); 2177193096Sattilio rx_npkts++; 2178144651Salc } 2179129794Stackerman#endif 2180129794Stackerman adapter->fmp = NULL; 2181129794Stackerman adapter->lmp = NULL; 2182129794Stackerman } 2183129794Stackerman adapter->rx_buffer_area[i].m_head = NULL; 2184129794Stackerman } else { 2185129794Stackerman adapter->dropped_pkts++; 2186129794Stackerman if (adapter->fmp != NULL) 2187129794Stackerman m_freem(adapter->fmp); 2188129794Stackerman adapter->fmp = NULL; 2189129794Stackerman adapter->lmp = NULL; 2190129794Stackerman } 2191129794Stackerman 2192129794Stackerman /* Zero out the receive descriptors status */ 2193129794Stackerman current_desc->status = 0; 2194129794Stackerman 2195129794Stackerman /* Advance our pointers to the next descriptor */ 2196129794Stackerman if (++i == adapter->num_rx_desc) { 2197129794Stackerman i = 0; 2198129794Stackerman current_desc = adapter->rx_desc_base; 2199129794Stackerman } else 2200129794Stackerman current_desc++; 2201129794Stackerman } 2202129794Stackerman adapter->next_rx_desc_to_check = i; 2203129794Stackerman 2204129794Stackerman if (--i < 0) 2205129794Stackerman i = (adapter->num_rx_desc - 1); 2206129794Stackerman 2207129794Stackerman /* 2208129794Stackerman * 82597EX: Workaround for redundent write back in receive descriptor ring (causes 2209129794Stackerman * memory corruption). Avoid using and re-submitting the most recently received RX 2210129794Stackerman * descriptor back to hardware. 2211129794Stackerman * 2212129794Stackerman * if(Last written back descriptor == EOP bit set descriptor) 2213129794Stackerman * then avoid re-submitting the most recently received RX descriptor 2214129794Stackerman * back to hardware. 2215129794Stackerman * if(Last written back descriptor != EOP bit set descriptor) 2216129794Stackerman * then avoid re-submitting the most recently received RX descriptors 2217129794Stackerman * till last EOP bit set descriptor. 2218129794Stackerman */ 2219129794Stackerman if (eop_desc != i) { 2220129794Stackerman if (++eop_desc == adapter->num_rx_desc) 2221129794Stackerman eop_desc = 0; 2222129794Stackerman i = eop_desc; 2223129794Stackerman } 2224129794Stackerman /* Replenish the descriptors with new mbufs till last EOP bit set descriptor */ 2225129794Stackerman while (next_to_use != i) { 2226129794Stackerman current_desc = &adapter->rx_desc_base[next_to_use]; 2227129794Stackerman if ((current_desc->errors & (IXGB_RX_DESC_ERRORS_CE | 2228129794Stackerman IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P | 2229129794Stackerman IXGB_RX_DESC_ERRORS_RXE))) { 2230129794Stackerman mp = adapter->rx_buffer_area[next_to_use].m_head; 2231129794Stackerman ixgb_get_buf(next_to_use, adapter, mp); 2232129794Stackerman } else { 2233129794Stackerman if (ixgb_get_buf(next_to_use, adapter, NULL) == ENOBUFS) 2234129794Stackerman break; 2235129794Stackerman } 2236129794Stackerman /* Advance our pointers to the next descriptor */ 2237129794Stackerman if (++next_to_use == adapter->num_rx_desc) { 2238129794Stackerman next_to_use = 0; 2239129794Stackerman current_desc = adapter->rx_desc_base; 2240129794Stackerman } else 2241129794Stackerman current_desc++; 2242129794Stackerman } 2243129794Stackerman adapter->next_rx_desc_to_use = next_to_use; 2244129794Stackerman if (--next_to_use < 0) 2245129794Stackerman next_to_use = (adapter->num_rx_desc - 1); 2246129794Stackerman /* Advance the IXGB's Receive Queue #0 "Tail Pointer" */ 2247129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDT, next_to_use); 2248129794Stackerman 2249193096Sattilio return (rx_npkts); 2250129794Stackerman} 2251129794Stackerman 2252129794Stackerman/********************************************************************* 2253129794Stackerman * 2254129794Stackerman * Verify that the hardware indicated that the checksum is valid. 2255129794Stackerman * Inform the stack about the status of checksum so that stack 2256129794Stackerman * doesn't spend time verifying the checksum. 2257129794Stackerman * 2258129794Stackerman *********************************************************************/ 2259129794Stackermanstatic void 2260129794Stackermanixgb_receive_checksum(struct adapter * adapter, 2261129794Stackerman struct ixgb_rx_desc * rx_desc, 2262129794Stackerman struct mbuf * mp) 2263129794Stackerman{ 2264129794Stackerman if (rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) { 2265129794Stackerman mp->m_pkthdr.csum_flags = 0; 2266129794Stackerman return; 2267129794Stackerman } 2268129794Stackerman if (rx_desc->status & IXGB_RX_DESC_STATUS_IPCS) { 2269129794Stackerman /* Did it pass? */ 2270129794Stackerman if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_IPE)) { 2271129794Stackerman /* IP Checksum Good */ 2272129794Stackerman mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; 2273129794Stackerman mp->m_pkthdr.csum_flags |= CSUM_IP_VALID; 2274129794Stackerman 2275129794Stackerman } else { 2276129794Stackerman mp->m_pkthdr.csum_flags = 0; 2277129794Stackerman } 2278129794Stackerman } 2279129794Stackerman if (rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS) { 2280129794Stackerman /* Did it pass? */ 2281129794Stackerman if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE)) { 2282129794Stackerman mp->m_pkthdr.csum_flags |= 2283129794Stackerman (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); 2284129794Stackerman mp->m_pkthdr.csum_data = htons(0xffff); 2285129794Stackerman } 2286129794Stackerman } 2287129794Stackerman return; 2288129794Stackerman} 2289129794Stackerman 2290129794Stackerman 2291129794Stackermanstatic void 2292129794Stackermanixgb_enable_vlans(struct adapter * adapter) 2293129794Stackerman{ 2294129794Stackerman uint32_t ctrl; 2295129794Stackerman 2296129794Stackerman ctrl = IXGB_READ_REG(&adapter->hw, CTRL0); 2297129794Stackerman ctrl |= IXGB_CTRL0_VME; 2298129794Stackerman IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl); 2299129794Stackerman 2300129794Stackerman return; 2301129794Stackerman} 2302129794Stackerman 2303129794Stackerman 2304129794Stackermanstatic void 2305129794Stackermanixgb_enable_intr(struct adapter * adapter) 2306129794Stackerman{ 2307129794Stackerman IXGB_WRITE_REG(&adapter->hw, IMS, (IXGB_INT_RXT0 | IXGB_INT_TXDW | 2308129794Stackerman IXGB_INT_RXDMT0 | IXGB_INT_LSC | IXGB_INT_RXO)); 2309129794Stackerman return; 2310129794Stackerman} 2311129794Stackerman 2312129794Stackermanstatic void 2313129794Stackermanixgb_disable_intr(struct adapter * adapter) 2314129794Stackerman{ 2315129794Stackerman IXGB_WRITE_REG(&adapter->hw, IMC, ~0); 2316129794Stackerman return; 2317129794Stackerman} 2318129794Stackerman 2319129794Stackermanvoid 2320129794Stackermanixgb_write_pci_cfg(struct ixgb_hw * hw, 2321129794Stackerman uint32_t reg, 2322129794Stackerman uint16_t * value) 2323129794Stackerman{ 2324129794Stackerman pci_write_config(((struct ixgb_osdep *) hw->back)->dev, reg, 2325129794Stackerman *value, 2); 2326129794Stackerman} 2327129794Stackerman 2328129794Stackerman/********************************************************************** 2329129794Stackerman * 2330129794Stackerman * Update the board statistics counters. 2331129794Stackerman * 2332129794Stackerman **********************************************************************/ 2333129794Stackermanstatic void 2334129794Stackermanixgb_update_stats_counters(struct adapter * adapter) 2335129794Stackerman{ 2336129794Stackerman struct ifnet *ifp; 2337129794Stackerman 2338129794Stackerman adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS); 2339129794Stackerman adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL); 2340129794Stackerman adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH); 2341129794Stackerman adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL); 2342129794Stackerman adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH); 2343129794Stackerman adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL); 2344129794Stackerman adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH); 2345129794Stackerman adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL); 2346129794Stackerman adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH); 2347129794Stackerman adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC); 2348129794Stackerman 2349129794Stackerman adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC); 2350129794Stackerman adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC); 2351129794Stackerman adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC); 2352129794Stackerman adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC); 2353129794Stackerman adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC); 2354129794Stackerman adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC); 2355129794Stackerman adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC); 2356129794Stackerman adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL); 2357129794Stackerman adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH); 2358129794Stackerman adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL); 2359129794Stackerman adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH); 2360129794Stackerman adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC); 2361129794Stackerman adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC); 2362129794Stackerman adapter->stats.rjc += IXGB_READ_REG(&adapter->hw, RJC); 2363129794Stackerman adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL); 2364129794Stackerman adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH); 2365129794Stackerman adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL); 2366129794Stackerman adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH); 2367129794Stackerman adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL); 2368129794Stackerman adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH); 2369129794Stackerman adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL); 2370129794Stackerman adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH); 2371129794Stackerman adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C); 2372129794Stackerman adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL); 2373129794Stackerman adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH); 2374129794Stackerman adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL); 2375129794Stackerman adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH); 2376129794Stackerman 2377129794Stackerman adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL); 2378129794Stackerman adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH); 2379129794Stackerman adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL); 2380129794Stackerman adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH); 2381129794Stackerman adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL); 2382129794Stackerman adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH); 2383129794Stackerman adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC); 2384129794Stackerman adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC); 2385129794Stackerman adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC); 2386129794Stackerman adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL); 2387129794Stackerman adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH); 2388129794Stackerman adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL); 2389129794Stackerman adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH); 2390129794Stackerman adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL); 2391129794Stackerman adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH); 2392129794Stackerman adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC); 2393129794Stackerman adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC); 2394129794Stackerman adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC); 2395129794Stackerman adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC); 2396129794Stackerman adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC); 2397129794Stackerman adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC); 2398129794Stackerman adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC); 2399129794Stackerman 2400147256Sbrooks ifp = adapter->ifp; 2401129794Stackerman 2402129794Stackerman /* Fill out the OS statistics structure */ 2403129794Stackerman ifp->if_ipackets = adapter->stats.gprcl; 2404129794Stackerman ifp->if_opackets = adapter->stats.gptcl; 2405129794Stackerman ifp->if_ibytes = adapter->stats.gorcl; 2406129794Stackerman ifp->if_obytes = adapter->stats.gotcl; 2407129794Stackerman ifp->if_imcasts = adapter->stats.mprcl; 2408129794Stackerman ifp->if_collisions = 0; 2409129794Stackerman 2410129794Stackerman /* Rx Errors */ 2411129794Stackerman ifp->if_ierrors = 2412129794Stackerman adapter->dropped_pkts + 2413129794Stackerman adapter->stats.crcerrs + 2414129794Stackerman adapter->stats.rnbc + 2415129794Stackerman adapter->stats.mpc + 2416129794Stackerman adapter->stats.rlec; 2417129794Stackerman 2418129794Stackerman 2419129794Stackerman} 2420129794Stackerman 2421129794Stackerman 2422129794Stackerman/********************************************************************** 2423129794Stackerman * 2424129794Stackerman * This routine is called only when ixgb_display_debug_stats is enabled. 2425129794Stackerman * This routine provides a way to take a look at important statistics 2426129794Stackerman * maintained by the driver and hardware. 2427129794Stackerman * 2428129794Stackerman **********************************************************************/ 2429129794Stackermanstatic void 2430129794Stackermanixgb_print_hw_stats(struct adapter * adapter) 2431129794Stackerman{ 2432129794Stackerman char buf_speed[100], buf_type[100]; 2433129794Stackerman ixgb_bus_speed bus_speed; 2434129794Stackerman ixgb_bus_type bus_type; 2435198987Sjhb device_t dev; 2436129794Stackerman 2437198987Sjhb dev = adapter->dev; 2438129794Stackerman#ifdef _SV_ 2439198987Sjhb device_printf(dev, "Packets not Avail = %ld\n", 2440129794Stackerman adapter->no_pkts_avail); 2441198987Sjhb device_printf(dev, "CleanTxInterrupts = %ld\n", 2442129794Stackerman adapter->clean_tx_interrupts); 2443198987Sjhb device_printf(dev, "ICR RXDMT0 = %lld\n", 2444129794Stackerman (long long)adapter->sv_stats.icr_rxdmt0); 2445198987Sjhb device_printf(dev, "ICR RXO = %lld\n", 2446129794Stackerman (long long)adapter->sv_stats.icr_rxo); 2447198987Sjhb device_printf(dev, "ICR RXT0 = %lld\n", 2448129794Stackerman (long long)adapter->sv_stats.icr_rxt0); 2449198987Sjhb device_printf(dev, "ICR TXDW = %lld\n", 2450129794Stackerman (long long)adapter->sv_stats.icr_TXDW); 2451129794Stackerman#endif /* _SV_ */ 2452129794Stackerman 2453129794Stackerman bus_speed = adapter->hw.bus.speed; 2454129794Stackerman bus_type = adapter->hw.bus.type; 2455129794Stackerman sprintf(buf_speed, 2456129794Stackerman bus_speed == ixgb_bus_speed_33 ? "33MHz" : 2457129794Stackerman bus_speed == ixgb_bus_speed_66 ? "66MHz" : 2458129794Stackerman bus_speed == ixgb_bus_speed_100 ? "100MHz" : 2459129794Stackerman bus_speed == ixgb_bus_speed_133 ? "133MHz" : 2460129794Stackerman "UNKNOWN"); 2461198987Sjhb device_printf(dev, "PCI_Bus_Speed = %s\n", 2462129794Stackerman buf_speed); 2463129794Stackerman 2464129794Stackerman sprintf(buf_type, 2465129794Stackerman bus_type == ixgb_bus_type_pci ? "PCI" : 2466129794Stackerman bus_type == ixgb_bus_type_pcix ? "PCI-X" : 2467129794Stackerman "UNKNOWN"); 2468198987Sjhb device_printf(dev, "PCI_Bus_Type = %s\n", 2469129794Stackerman buf_type); 2470129794Stackerman 2471198987Sjhb device_printf(dev, "Tx Descriptors not Avail1 = %ld\n", 2472129794Stackerman adapter->no_tx_desc_avail1); 2473198987Sjhb device_printf(dev, "Tx Descriptors not Avail2 = %ld\n", 2474129794Stackerman adapter->no_tx_desc_avail2); 2475198987Sjhb device_printf(dev, "Std Mbuf Failed = %ld\n", 2476129794Stackerman adapter->mbuf_alloc_failed); 2477198987Sjhb device_printf(dev, "Std Cluster Failed = %ld\n", 2478129794Stackerman adapter->mbuf_cluster_failed); 2479129794Stackerman 2480198987Sjhb device_printf(dev, "Defer count = %lld\n", 2481129794Stackerman (long long)adapter->stats.dc); 2482198987Sjhb device_printf(dev, "Missed Packets = %lld\n", 2483129794Stackerman (long long)adapter->stats.mpc); 2484198987Sjhb device_printf(dev, "Receive No Buffers = %lld\n", 2485129794Stackerman (long long)adapter->stats.rnbc); 2486198987Sjhb device_printf(dev, "Receive length errors = %lld\n", 2487129794Stackerman (long long)adapter->stats.rlec); 2488198987Sjhb device_printf(dev, "Crc errors = %lld\n", 2489129794Stackerman (long long)adapter->stats.crcerrs); 2490198987Sjhb device_printf(dev, "Driver dropped packets = %ld\n", 2491129794Stackerman adapter->dropped_pkts); 2492129794Stackerman 2493198987Sjhb device_printf(dev, "XON Rcvd = %lld\n", 2494129794Stackerman (long long)adapter->stats.xonrxc); 2495198987Sjhb device_printf(dev, "XON Xmtd = %lld\n", 2496129794Stackerman (long long)adapter->stats.xontxc); 2497198987Sjhb device_printf(dev, "XOFF Rcvd = %lld\n", 2498129794Stackerman (long long)adapter->stats.xoffrxc); 2499198987Sjhb device_printf(dev, "XOFF Xmtd = %lld\n", 2500129794Stackerman (long long)adapter->stats.xofftxc); 2501129794Stackerman 2502198987Sjhb device_printf(dev, "Good Packets Rcvd = %lld\n", 2503129794Stackerman (long long)adapter->stats.gprcl); 2504198987Sjhb device_printf(dev, "Good Packets Xmtd = %lld\n", 2505129794Stackerman (long long)adapter->stats.gptcl); 2506129794Stackerman 2507198987Sjhb device_printf(dev, "Jumbo frames recvd = %lld\n", 2508129794Stackerman (long long)adapter->stats.jprcl); 2509198987Sjhb device_printf(dev, "Jumbo frames Xmtd = %lld\n", 2510129794Stackerman (long long)adapter->stats.jptcl); 2511129794Stackerman 2512129794Stackerman return; 2513129794Stackerman 2514129794Stackerman} 2515129794Stackerman 2516129794Stackermanstatic int 2517129794Stackermanixgb_sysctl_stats(SYSCTL_HANDLER_ARGS) 2518129794Stackerman{ 2519129794Stackerman int error; 2520129794Stackerman int result; 2521129794Stackerman struct adapter *adapter; 2522129794Stackerman 2523129794Stackerman result = -1; 2524129794Stackerman error = sysctl_handle_int(oidp, &result, 0, req); 2525129794Stackerman 2526129794Stackerman if (error || !req->newptr) 2527129794Stackerman return (error); 2528129794Stackerman 2529129794Stackerman if (result == 1) { 2530129794Stackerman adapter = (struct adapter *) arg1; 2531129794Stackerman ixgb_print_hw_stats(adapter); 2532129794Stackerman } 2533129794Stackerman return error; 2534129794Stackerman} 2535