if_ixgb.c revision 150789
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 150789 2005-10-01 18:56:19Z glebius $*/ 35129794Stackerman 36129794Stackerman#include <dev/ixgb/if_ixgb.h> 37129794Stackerman 38129794Stackerman/********************************************************************* 39129794Stackerman * Set this to one to display debug statistics 40129794Stackerman *********************************************************************/ 41129794Stackermanint ixgb_display_debug_stats = 0; 42129794Stackerman 43129794Stackerman/********************************************************************* 44129794Stackerman * Linked list of board private structures for all NICs found 45129794Stackerman *********************************************************************/ 46129794Stackerman 47129794Stackermanstruct adapter *ixgb_adapter_list = NULL; 48129794Stackerman 49129794Stackerman 50129794Stackerman 51129794Stackerman/********************************************************************* 52129794Stackerman * Driver version 53129794Stackerman *********************************************************************/ 54129794Stackerman 55129794Stackermanchar ixgb_driver_version[] = "1.0.6"; 56129794Stackermanchar ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation."; 57129794Stackerman 58129794Stackerman/********************************************************************* 59129794Stackerman * PCI Device ID Table 60129794Stackerman * 61129794Stackerman * Used by probe to select devices to load on 62129794Stackerman * Last field stores an index into ixgb_strings 63129794Stackerman * Last entry must be all 0s 64129794Stackerman * 65129794Stackerman * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } 66129794Stackerman *********************************************************************/ 67129794Stackerman 68129794Stackermanstatic ixgb_vendor_info_t ixgb_vendor_info_array[] = 69129794Stackerman{ 70129794Stackerman /* Intel(R) PRO/10000 Network Connection */ 71129794Stackerman {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX, PCI_ANY_ID, PCI_ANY_ID, 0}, 72129794Stackerman {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR, PCI_ANY_ID, PCI_ANY_ID, 0}, 73129794Stackerman /* required last entry */ 74129794Stackerman {0, 0, 0, 0, 0} 75129794Stackerman}; 76129794Stackerman 77129794Stackerman/********************************************************************* 78129794Stackerman * Table of branding strings for all supported NICs. 79129794Stackerman *********************************************************************/ 80129794Stackerman 81129794Stackermanstatic char *ixgb_strings[] = { 82129794Stackerman "Intel(R) PRO/10GbE Network Driver" 83129794Stackerman}; 84129794Stackerman 85129794Stackerman/********************************************************************* 86129794Stackerman * Function prototypes 87129794Stackerman *********************************************************************/ 88129794Stackermanstatic int ixgb_probe(device_t); 89129794Stackermanstatic int ixgb_attach(device_t); 90129794Stackermanstatic int ixgb_detach(device_t); 91129794Stackermanstatic int ixgb_shutdown(device_t); 92129794Stackermanstatic void ixgb_intr(void *); 93129794Stackermanstatic void ixgb_start(struct ifnet *); 94144651Salcstatic void ixgb_start_locked(struct ifnet *); 95129794Stackermanstatic int ixgb_ioctl(struct ifnet *, IOCTL_CMD_TYPE, caddr_t); 96129794Stackermanstatic void ixgb_watchdog(struct ifnet *); 97129794Stackermanstatic void ixgb_init(void *); 98144651Salcstatic void ixgb_init_locked(struct adapter *); 99129794Stackermanstatic void ixgb_stop(void *); 100129794Stackermanstatic void ixgb_media_status(struct ifnet *, struct ifmediareq *); 101129794Stackermanstatic int ixgb_media_change(struct ifnet *); 102129794Stackermanstatic void ixgb_identify_hardware(struct adapter *); 103129794Stackermanstatic int ixgb_allocate_pci_resources(struct adapter *); 104129794Stackermanstatic void ixgb_free_pci_resources(struct adapter *); 105129794Stackermanstatic void ixgb_local_timer(void *); 106129794Stackermanstatic int ixgb_hardware_init(struct adapter *); 107129794Stackermanstatic void ixgb_setup_interface(device_t, struct adapter *); 108129794Stackermanstatic int ixgb_setup_transmit_structures(struct adapter *); 109129794Stackermanstatic void ixgb_initialize_transmit_unit(struct adapter *); 110129794Stackermanstatic int ixgb_setup_receive_structures(struct adapter *); 111129794Stackermanstatic void ixgb_initialize_receive_unit(struct adapter *); 112129794Stackermanstatic void ixgb_enable_intr(struct adapter *); 113129794Stackermanstatic void ixgb_disable_intr(struct adapter *); 114129794Stackermanstatic void ixgb_free_transmit_structures(struct adapter *); 115129794Stackermanstatic void ixgb_free_receive_structures(struct adapter *); 116129794Stackermanstatic void ixgb_update_stats_counters(struct adapter *); 117129794Stackermanstatic void ixgb_clean_transmit_interrupts(struct adapter *); 118129794Stackermanstatic int ixgb_allocate_receive_structures(struct adapter *); 119129794Stackermanstatic int ixgb_allocate_transmit_structures(struct adapter *); 120129794Stackermanstatic void ixgb_process_receive_interrupts(struct adapter *, int); 121129794Stackermanstatic void 122129794Stackermanixgb_receive_checksum(struct adapter *, 123129794Stackerman struct ixgb_rx_desc * rx_desc, 124129794Stackerman struct mbuf *); 125129794Stackermanstatic void 126129794Stackermanixgb_transmit_checksum_setup(struct adapter *, 127129794Stackerman struct mbuf *, 128129794Stackerman u_int8_t *); 129129794Stackermanstatic void ixgb_set_promisc(struct adapter *); 130129794Stackermanstatic void ixgb_disable_promisc(struct adapter *); 131129794Stackermanstatic void ixgb_set_multi(struct adapter *); 132129794Stackermanstatic void ixgb_print_hw_stats(struct adapter *); 133129794Stackermanstatic void ixgb_print_link_status(struct adapter *); 134129794Stackermanstatic int 135129794Stackermanixgb_get_buf(int i, struct adapter *, 136129794Stackerman struct mbuf *); 137129794Stackermanstatic void ixgb_enable_vlans(struct adapter * adapter); 138129794Stackermanstatic int ixgb_encap(struct adapter * adapter, struct mbuf * m_head); 139129794Stackermanstatic int ixgb_sysctl_stats(SYSCTL_HANDLER_ARGS); 140129794Stackermanstatic int 141129794Stackermanixgb_dma_malloc(struct adapter *, bus_size_t, 142129794Stackerman struct ixgb_dma_alloc *, int); 143129794Stackermanstatic void ixgb_dma_free(struct adapter *, struct ixgb_dma_alloc *); 144150789Sglebius#ifdef DEVICE_POLLING 145150789Sglebiusstatic poll_handler_t ixgb_poll; 146150789Sglebius#endif 147129794Stackerman 148129794Stackerman/********************************************************************* 149129794Stackerman * FreeBSD Device Interface Entry Points 150129794Stackerman *********************************************************************/ 151129794Stackerman 152129794Stackermanstatic device_method_t ixgb_methods[] = { 153129794Stackerman /* Device interface */ 154129794Stackerman DEVMETHOD(device_probe, ixgb_probe), 155129794Stackerman DEVMETHOD(device_attach, ixgb_attach), 156129794Stackerman DEVMETHOD(device_detach, ixgb_detach), 157129794Stackerman DEVMETHOD(device_shutdown, ixgb_shutdown), 158129794Stackerman {0, 0} 159129794Stackerman}; 160129794Stackerman 161129794Stackermanstatic driver_t ixgb_driver = { 162129794Stackerman "ixgb", ixgb_methods, sizeof(struct adapter), 163129794Stackerman}; 164129794Stackerman 165129794Stackermanstatic devclass_t ixgb_devclass; 166129794StackermanDRIVER_MODULE(if_ixgb, pci, ixgb_driver, ixgb_devclass, 0, 0); 167129794Stackerman 168144190SmuxMODULE_DEPEND(if_ixgb, pci, 1, 1, 1); 169144190SmuxMODULE_DEPEND(if_ixgb, ether, 1, 1, 1); 170144183Smux 171129794Stackerman/* some defines for controlling descriptor fetches in h/w */ 172129794Stackerman#define RXDCTL_PTHRESH_DEFAULT 128 /* chip considers prefech below this */ 173129794Stackerman#define RXDCTL_HTHRESH_DEFAULT 16 /* chip will only prefetch if tail is 174129794Stackerman * pushed this many descriptors from 175129794Stackerman * head */ 176129794Stackerman#define RXDCTL_WTHRESH_DEFAULT 0 /* chip writes back at this many or RXT0 */ 177129794Stackerman 178129794Stackerman 179129794Stackerman/********************************************************************* 180129794Stackerman * Device identification routine 181129794Stackerman * 182129794Stackerman * ixgb_probe determines if the driver should be loaded on 183129794Stackerman * adapter based on PCI vendor/device id of the adapter. 184129794Stackerman * 185129794Stackerman * return 0 on success, positive on failure 186129794Stackerman *********************************************************************/ 187129794Stackerman 188129794Stackermanstatic int 189129794Stackermanixgb_probe(device_t dev) 190129794Stackerman{ 191129794Stackerman ixgb_vendor_info_t *ent; 192129794Stackerman 193129794Stackerman u_int16_t pci_vendor_id = 0; 194129794Stackerman u_int16_t pci_device_id = 0; 195129794Stackerman u_int16_t pci_subvendor_id = 0; 196129794Stackerman u_int16_t pci_subdevice_id = 0; 197129794Stackerman char adapter_name[60]; 198129794Stackerman 199129794Stackerman INIT_DEBUGOUT("ixgb_probe: begin"); 200129794Stackerman 201129794Stackerman pci_vendor_id = pci_get_vendor(dev); 202129794Stackerman if (pci_vendor_id != IXGB_VENDOR_ID) 203129794Stackerman return (ENXIO); 204129794Stackerman 205129794Stackerman pci_device_id = pci_get_device(dev); 206129794Stackerman pci_subvendor_id = pci_get_subvendor(dev); 207129794Stackerman pci_subdevice_id = pci_get_subdevice(dev); 208129794Stackerman 209129794Stackerman ent = ixgb_vendor_info_array; 210129794Stackerman while (ent->vendor_id != 0) { 211129794Stackerman if ((pci_vendor_id == ent->vendor_id) && 212129794Stackerman (pci_device_id == ent->device_id) && 213129794Stackerman 214129794Stackerman ((pci_subvendor_id == ent->subvendor_id) || 215129794Stackerman (ent->subvendor_id == PCI_ANY_ID)) && 216129794Stackerman 217129794Stackerman ((pci_subdevice_id == ent->subdevice_id) || 218129794Stackerman (ent->subdevice_id == PCI_ANY_ID))) { 219129794Stackerman sprintf(adapter_name, "%s, Version - %s", 220129794Stackerman ixgb_strings[ent->index], 221129794Stackerman ixgb_driver_version); 222129794Stackerman device_set_desc_copy(dev, adapter_name); 223143160Simp return (BUS_PROBE_DEFAULT); 224129794Stackerman } 225129794Stackerman ent++; 226129794Stackerman } 227129794Stackerman 228129794Stackerman return (ENXIO); 229129794Stackerman} 230129794Stackerman 231129794Stackerman/********************************************************************* 232129794Stackerman * Device initialization routine 233129794Stackerman * 234129794Stackerman * The attach entry point is called when the driver is being loaded. 235129794Stackerman * This routine identifies the type of hardware, allocates all resources 236129794Stackerman * and initializes the hardware. 237129794Stackerman * 238129794Stackerman * return 0 on success, positive on failure 239129794Stackerman *********************************************************************/ 240129794Stackerman 241129794Stackermanstatic int 242129794Stackermanixgb_attach(device_t dev) 243129794Stackerman{ 244129794Stackerman struct adapter *adapter; 245129794Stackerman int tsize, rsize; 246129794Stackerman int error = 0; 247129794Stackerman 248129794Stackerman printf("ixgb%d: %s\n", device_get_unit(dev), ixgb_copyright); 249129794Stackerman INIT_DEBUGOUT("ixgb_attach: begin"); 250129794Stackerman 251129794Stackerman /* Allocate, clear, and link in our adapter structure */ 252129794Stackerman if (!(adapter = device_get_softc(dev))) { 253129794Stackerman printf("ixgb: adapter structure allocation failed\n"); 254129794Stackerman return (ENOMEM); 255129794Stackerman } 256129794Stackerman bzero(adapter, sizeof(struct adapter)); 257129794Stackerman adapter->dev = dev; 258129794Stackerman adapter->osdep.dev = dev; 259129794Stackerman adapter->unit = device_get_unit(dev); 260144651Salc IXGB_LOCK_INIT(adapter, device_get_nameunit(dev)); 261129794Stackerman 262129794Stackerman if (ixgb_adapter_list != NULL) 263129794Stackerman ixgb_adapter_list->prev = adapter; 264129794Stackerman adapter->next = ixgb_adapter_list; 265129794Stackerman ixgb_adapter_list = adapter; 266129794Stackerman 267129794Stackerman /* SYSCTL APIs */ 268144183Smux SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 269144183Smux SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 270129794Stackerman OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW, 271129794Stackerman (void *)adapter, 0, 272129794Stackerman ixgb_sysctl_stats, "I", "Statistics"); 273129794Stackerman 274144651Salc callout_init(&adapter->timer, CALLOUT_MPSAFE); 275129794Stackerman 276129794Stackerman /* Determine hardware revision */ 277129794Stackerman ixgb_identify_hardware(adapter); 278129794Stackerman 279129794Stackerman /* Parameters (to be read from user) */ 280129794Stackerman adapter->num_tx_desc = IXGB_MAX_TXD; 281129794Stackerman adapter->num_rx_desc = IXGB_MAX_RXD; 282129794Stackerman adapter->tx_int_delay = TIDV; 283129794Stackerman adapter->rx_int_delay = RDTR; 284129794Stackerman adapter->rx_buffer_len = IXGB_RXBUFFER_2048; 285129794Stackerman 286129794Stackerman adapter->hw.fc.high_water = FCRTH; 287129794Stackerman adapter->hw.fc.low_water = FCRTL; 288129794Stackerman adapter->hw.fc.pause_time = FCPAUSE; 289129794Stackerman adapter->hw.fc.send_xon = TRUE; 290129794Stackerman adapter->hw.fc.type = FLOW_CONTROL; 291129794Stackerman 292129794Stackerman 293129794Stackerman /* Set the max frame size assuming standard ethernet sized frames */ 294129794Stackerman adapter->hw.max_frame_size = 295129794Stackerman ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN; 296129794Stackerman 297129794Stackerman if (ixgb_allocate_pci_resources(adapter)) { 298129794Stackerman printf("ixgb%d: Allocation of PCI resources failed\n", 299129794Stackerman adapter->unit); 300129794Stackerman error = ENXIO; 301129794Stackerman goto err_pci; 302129794Stackerman } 303129794Stackerman tsize = IXGB_ROUNDUP(adapter->num_tx_desc * 304129794Stackerman sizeof(struct ixgb_tx_desc), 4096); 305129794Stackerman 306129794Stackerman /* Allocate Transmit Descriptor ring */ 307129794Stackerman if (ixgb_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) { 308129794Stackerman printf("ixgb%d: Unable to allocate TxDescriptor memory\n", 309129794Stackerman adapter->unit); 310129794Stackerman error = ENOMEM; 311129794Stackerman goto err_tx_desc; 312129794Stackerman } 313129794Stackerman adapter->tx_desc_base = (struct ixgb_tx_desc *) adapter->txdma.dma_vaddr; 314129794Stackerman 315129794Stackerman rsize = IXGB_ROUNDUP(adapter->num_rx_desc * 316129794Stackerman sizeof(struct ixgb_rx_desc), 4096); 317129794Stackerman 318129794Stackerman /* Allocate Receive Descriptor ring */ 319129794Stackerman if (ixgb_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) { 320129794Stackerman printf("ixgb%d: Unable to allocate rx_desc memory\n", 321129794Stackerman adapter->unit); 322129794Stackerman error = ENOMEM; 323129794Stackerman goto err_rx_desc; 324129794Stackerman } 325129794Stackerman adapter->rx_desc_base = (struct ixgb_rx_desc *) adapter->rxdma.dma_vaddr; 326129794Stackerman 327129794Stackerman /* Initialize the hardware */ 328129794Stackerman if (ixgb_hardware_init(adapter)) { 329129794Stackerman printf("ixgb%d: Unable to initialize the hardware\n", 330129794Stackerman adapter->unit); 331129794Stackerman error = EIO; 332129794Stackerman goto err_hw_init; 333129794Stackerman } 334129794Stackerman /* Setup OS specific network interface */ 335129794Stackerman ixgb_setup_interface(dev, adapter); 336129794Stackerman 337129794Stackerman /* Initialize statistics */ 338129794Stackerman ixgb_clear_hw_cntrs(&adapter->hw); 339129794Stackerman ixgb_update_stats_counters(adapter); 340129794Stackerman 341129794Stackerman INIT_DEBUGOUT("ixgb_attach: end"); 342129794Stackerman return (0); 343129794Stackerman 344129794Stackermanerr_hw_init: 345129794Stackerman ixgb_dma_free(adapter, &adapter->rxdma); 346129794Stackermanerr_rx_desc: 347129794Stackerman ixgb_dma_free(adapter, &adapter->txdma); 348129794Stackermanerr_tx_desc: 349129794Stackermanerr_pci: 350129794Stackerman ixgb_free_pci_resources(adapter); 351129794Stackerman sysctl_ctx_free(&adapter->sysctl_ctx); 352129794Stackerman return (error); 353129794Stackerman 354129794Stackerman} 355129794Stackerman 356129794Stackerman/********************************************************************* 357129794Stackerman * Device removal routine 358129794Stackerman * 359129794Stackerman * The detach entry point is called when the driver is being removed. 360129794Stackerman * This routine stops the adapter and deallocates all the resources 361129794Stackerman * that were allocated for driver operation. 362129794Stackerman * 363129794Stackerman * return 0 on success, positive on failure 364129794Stackerman *********************************************************************/ 365129794Stackerman 366129794Stackermanstatic int 367129794Stackermanixgb_detach(device_t dev) 368129794Stackerman{ 369129794Stackerman struct adapter *adapter = device_get_softc(dev); 370147256Sbrooks struct ifnet *ifp = adapter->ifp; 371129794Stackerman 372129794Stackerman INIT_DEBUGOUT("ixgb_detach: begin"); 373129794Stackerman 374150789Sglebius#ifdef DEVICE_POLLING 375150789Sglebius if (ifp->if_capenable & IFCAP_POLLING) 376150789Sglebius ether_poll_deregister(ifp); 377150789Sglebius#endif 378150789Sglebius 379144651Salc IXGB_LOCK(adapter); 380129794Stackerman adapter->in_detach = 1; 381129794Stackerman 382129794Stackerman ixgb_stop(adapter); 383144651Salc IXGB_UNLOCK(adapter); 384129794Stackerman 385129794Stackerman#if __FreeBSD_version < 500000 386147256Sbrooks ether_ifdetach(adapter->ifp, ETHER_BPF_SUPPORTED); 387129794Stackerman#else 388147256Sbrooks ether_ifdetach(adapter->ifp); 389150306Simp#endif 390150306Simp ixgb_free_pci_resources(adapter); 391150306Simp#if __FreeBSD_version >= 500000 392147256Sbrooks if_free(adapter->ifp); 393129794Stackerman#endif 394129794Stackerman 395129794Stackerman /* Free Transmit Descriptor ring */ 396129794Stackerman if (adapter->tx_desc_base) { 397129794Stackerman ixgb_dma_free(adapter, &adapter->txdma); 398129794Stackerman adapter->tx_desc_base = NULL; 399129794Stackerman } 400129794Stackerman /* Free Receive Descriptor ring */ 401129794Stackerman if (adapter->rx_desc_base) { 402129794Stackerman ixgb_dma_free(adapter, &adapter->rxdma); 403129794Stackerman adapter->rx_desc_base = NULL; 404129794Stackerman } 405129794Stackerman /* Remove from the adapter list */ 406129794Stackerman if (ixgb_adapter_list == adapter) 407129794Stackerman ixgb_adapter_list = adapter->next; 408129794Stackerman if (adapter->next != NULL) 409129794Stackerman adapter->next->prev = adapter->prev; 410129794Stackerman if (adapter->prev != NULL) 411129794Stackerman adapter->prev->next = adapter->next; 412129794Stackerman 413148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 414129794Stackerman ifp->if_timer = 0; 415129794Stackerman 416144651Salc IXGB_LOCK_DESTROY(adapter); 417129794Stackerman return (0); 418129794Stackerman} 419129794Stackerman 420129794Stackerman/********************************************************************* 421129794Stackerman * 422129794Stackerman * Shutdown entry point 423129794Stackerman * 424129794Stackerman **********************************************************************/ 425129794Stackerman 426129794Stackermanstatic int 427129794Stackermanixgb_shutdown(device_t dev) 428129794Stackerman{ 429129794Stackerman struct adapter *adapter = device_get_softc(dev); 430144651Salc IXGB_LOCK(adapter); 431129794Stackerman ixgb_stop(adapter); 432144651Salc IXGB_UNLOCK(adapter); 433129794Stackerman return (0); 434129794Stackerman} 435129794Stackerman 436129794Stackerman 437129794Stackerman/********************************************************************* 438129794Stackerman * Transmit entry point 439129794Stackerman * 440129794Stackerman * ixgb_start is called by the stack to initiate a transmit. 441129794Stackerman * The driver will remain in this routine as long as there are 442129794Stackerman * packets to transmit and transmit resources are available. 443129794Stackerman * In case resources are not available stack is notified and 444129794Stackerman * the packet is requeued. 445129794Stackerman **********************************************************************/ 446129794Stackerman 447129794Stackermanstatic void 448144651Salcixgb_start_locked(struct ifnet * ifp) 449129794Stackerman{ 450129794Stackerman struct mbuf *m_head; 451129794Stackerman struct adapter *adapter = ifp->if_softc; 452129794Stackerman 453144651Salc IXGB_LOCK_ASSERT(adapter); 454129794Stackerman 455129794Stackerman if (!adapter->link_active) 456129794Stackerman return; 457129794Stackerman 458129794Stackerman while (ifp->if_snd.ifq_head != NULL) { 459129794Stackerman IF_DEQUEUE(&ifp->if_snd, m_head); 460129794Stackerman 461129794Stackerman if (m_head == NULL) 462129794Stackerman break; 463129794Stackerman 464129794Stackerman if (ixgb_encap(adapter, m_head)) { 465148887Srwatson ifp->if_drv_flags |= IFF_DRV_OACTIVE; 466129794Stackerman IF_PREPEND(&ifp->if_snd, m_head); 467129794Stackerman break; 468129794Stackerman } 469129794Stackerman /* Send a copy of the frame to the BPF listener */ 470129794Stackerman#if __FreeBSD_version < 500000 471129794Stackerman if (ifp->if_bpf) 472129794Stackerman bpf_mtap(ifp, m_head); 473129794Stackerman#else 474129794Stackerman BPF_MTAP(ifp, m_head); 475129794Stackerman#endif 476129794Stackerman /* Set timeout in case hardware has problems transmitting */ 477129794Stackerman ifp->if_timer = IXGB_TX_TIMEOUT; 478129794Stackerman 479129794Stackerman } 480129794Stackerman return; 481129794Stackerman} 482129794Stackerman 483144651Salcstatic void 484144651Salcixgb_start(struct ifnet *ifp) 485144651Salc{ 486144651Salc struct adapter *adapter = ifp->if_softc; 487144651Salc 488144651Salc IXGB_LOCK(adapter); 489144651Salc ixgb_start_locked(ifp); 490144651Salc IXGB_UNLOCK(adapter); 491144651Salc return; 492144651Salc} 493144651Salc 494129794Stackerman/********************************************************************* 495129794Stackerman * Ioctl entry point 496129794Stackerman * 497129794Stackerman * ixgb_ioctl is called when the user wants to configure the 498129794Stackerman * interface. 499129794Stackerman * 500129794Stackerman * return 0 on success, positive on failure 501129794Stackerman **********************************************************************/ 502129794Stackerman 503129794Stackermanstatic int 504129794Stackermanixgb_ioctl(struct ifnet * ifp, IOCTL_CMD_TYPE command, caddr_t data) 505129794Stackerman{ 506144651Salc int mask, error = 0; 507129794Stackerman struct ifreq *ifr = (struct ifreq *) data; 508129794Stackerman struct adapter *adapter = ifp->if_softc; 509129794Stackerman 510129794Stackerman if (adapter->in_detach) 511129794Stackerman goto out; 512129794Stackerman 513129794Stackerman switch (command) { 514129794Stackerman case SIOCSIFADDR: 515129794Stackerman case SIOCGIFADDR: 516129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFADDR (Get/Set Interface Addr)"); 517129794Stackerman ether_ioctl(ifp, command, data); 518129794Stackerman break; 519129794Stackerman case SIOCSIFMTU: 520129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)"); 521129794Stackerman if (ifr->ifr_mtu > IXGB_MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN) { 522129794Stackerman error = EINVAL; 523129794Stackerman } else { 524144651Salc IXGB_LOCK(adapter); 525129794Stackerman ifp->if_mtu = ifr->ifr_mtu; 526129794Stackerman adapter->hw.max_frame_size = 527129794Stackerman ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 528129794Stackerman 529144651Salc ixgb_init_locked(adapter); 530144651Salc IXGB_UNLOCK(adapter); 531129794Stackerman } 532129794Stackerman break; 533129794Stackerman case SIOCSIFFLAGS: 534129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)"); 535144651Salc IXGB_LOCK(adapter); 536129794Stackerman if (ifp->if_flags & IFF_UP) { 537148887Srwatson if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 538144651Salc ixgb_init_locked(adapter); 539129794Stackerman } 540129794Stackerman ixgb_disable_promisc(adapter); 541129794Stackerman ixgb_set_promisc(adapter); 542129794Stackerman } else { 543148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 544129794Stackerman ixgb_stop(adapter); 545129794Stackerman } 546129794Stackerman } 547144651Salc IXGB_UNLOCK(adapter); 548129794Stackerman break; 549129794Stackerman case SIOCADDMULTI: 550129794Stackerman case SIOCDELMULTI: 551129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI"); 552148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 553144651Salc IXGB_LOCK(adapter); 554129794Stackerman ixgb_disable_intr(adapter); 555129794Stackerman ixgb_set_multi(adapter); 556129794Stackerman ixgb_enable_intr(adapter); 557144651Salc IXGB_UNLOCK(adapter); 558129794Stackerman } 559129794Stackerman break; 560129794Stackerman case SIOCSIFMEDIA: 561129794Stackerman case SIOCGIFMEDIA: 562129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA (Get/Set Interface Media)"); 563129794Stackerman error = ifmedia_ioctl(ifp, ifr, &adapter->media, command); 564129794Stackerman break; 565129794Stackerman case SIOCSIFCAP: 566129794Stackerman IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)"); 567129794Stackerman mask = ifr->ifr_reqcap ^ ifp->if_capenable; 568150789Sglebius#ifdef DEVICE_POLLING 569150789Sglebius if (mask & IFCAP_POLLING) { 570150789Sglebius if (ifr->ifr_reqcap & IFCAP_POLLING) { 571150789Sglebius error = ether_poll_register(ixgb_poll, ifp); 572150789Sglebius if (error) 573150789Sglebius return(error); 574150789Sglebius IXGB_LOCK(adapter); 575150789Sglebius ixgb_disable_intr(adapter); 576150789Sglebius ifp->if_capenable |= IFCAP_POLLING; 577150789Sglebius IXGB_UNLOCK(adapter); 578150789Sglebius } else { 579150789Sglebius error = ether_poll_deregister(ifp); 580150789Sglebius /* Enable interrupt even in error case */ 581150789Sglebius IXGB_LOCK(adapter); 582150789Sglebius ixgb_enable_intr(adapter); 583150789Sglebius ifp->if_capenable &= ~IFCAP_POLLING; 584150789Sglebius IXGB_UNLOCK(adapter); 585150789Sglebius } 586150789Sglebius } 587150789Sglebius#endif /* DEVICE_POLLING */ 588129794Stackerman if (mask & IFCAP_HWCSUM) { 589129794Stackerman if (IFCAP_HWCSUM & ifp->if_capenable) 590129794Stackerman ifp->if_capenable &= ~IFCAP_HWCSUM; 591129794Stackerman else 592129794Stackerman ifp->if_capenable |= IFCAP_HWCSUM; 593148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) 594129794Stackerman ixgb_init(adapter); 595129794Stackerman } 596129794Stackerman break; 597129794Stackerman default: 598129794Stackerman IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%X)\n", (int)command); 599129794Stackerman error = EINVAL; 600129794Stackerman } 601129794Stackerman 602129794Stackermanout: 603129794Stackerman return (error); 604129794Stackerman} 605129794Stackerman 606129794Stackerman/********************************************************************* 607129794Stackerman * Watchdog entry point 608129794Stackerman * 609129794Stackerman * This routine is called whenever hardware quits transmitting. 610129794Stackerman * 611129794Stackerman **********************************************************************/ 612129794Stackerman 613129794Stackermanstatic void 614129794Stackermanixgb_watchdog(struct ifnet * ifp) 615129794Stackerman{ 616129794Stackerman struct adapter *adapter; 617129794Stackerman adapter = ifp->if_softc; 618129794Stackerman 619129794Stackerman /* 620129794Stackerman * If we are in this routine because of pause frames, then don't 621129794Stackerman * reset the hardware. 622129794Stackerman */ 623129794Stackerman if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF) { 624129794Stackerman ifp->if_timer = IXGB_TX_TIMEOUT; 625129794Stackerman return; 626129794Stackerman } 627129794Stackerman printf("ixgb%d: watchdog timeout -- resetting\n", adapter->unit); 628129794Stackerman 629148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 630129794Stackerman 631129794Stackerman 632129794Stackerman ixgb_stop(adapter); 633129794Stackerman ixgb_init(adapter); 634129794Stackerman 635129794Stackerman 636129794Stackerman ifp->if_oerrors++; 637129794Stackerman 638129794Stackerman return; 639129794Stackerman} 640129794Stackerman 641129794Stackerman/********************************************************************* 642129794Stackerman * Init entry point 643129794Stackerman * 644129794Stackerman * This routine is used in two ways. It is used by the stack as 645129794Stackerman * init entry point in network interface structure. It is also used 646129794Stackerman * by the driver as a hw/sw initialization routine to get to a 647129794Stackerman * consistent state. 648129794Stackerman * 649129794Stackerman * return 0 on success, positive on failure 650129794Stackerman **********************************************************************/ 651129794Stackerman 652129794Stackermanstatic void 653144651Salcixgb_init_locked(struct adapter *adapter) 654129794Stackerman{ 655129794Stackerman struct ifnet *ifp; 656129794Stackerman 657129794Stackerman INIT_DEBUGOUT("ixgb_init: begin"); 658129794Stackerman 659144651Salc IXGB_LOCK_ASSERT(adapter); 660129794Stackerman 661129794Stackerman ixgb_stop(adapter); 662129794Stackerman 663129794Stackerman /* Get the latest mac address, User can use a LAA */ 664147256Sbrooks bcopy(IFP2ENADDR(adapter->ifp), adapter->hw.curr_mac_addr, 665129794Stackerman IXGB_ETH_LENGTH_OF_ADDRESS); 666129794Stackerman 667129794Stackerman /* Initialize the hardware */ 668129794Stackerman if (ixgb_hardware_init(adapter)) { 669129794Stackerman printf("ixgb%d: Unable to initialize the hardware\n", 670129794Stackerman adapter->unit); 671129794Stackerman return; 672129794Stackerman } 673129794Stackerman ixgb_enable_vlans(adapter); 674129794Stackerman 675129794Stackerman /* Prepare transmit descriptors and buffers */ 676129794Stackerman if (ixgb_setup_transmit_structures(adapter)) { 677129794Stackerman printf("ixgb%d: Could not setup transmit structures\n", 678129794Stackerman adapter->unit); 679129794Stackerman ixgb_stop(adapter); 680129794Stackerman return; 681129794Stackerman } 682129794Stackerman ixgb_initialize_transmit_unit(adapter); 683129794Stackerman 684129794Stackerman /* Setup Multicast table */ 685129794Stackerman ixgb_set_multi(adapter); 686129794Stackerman 687129794Stackerman /* Prepare receive descriptors and buffers */ 688129794Stackerman if (ixgb_setup_receive_structures(adapter)) { 689129794Stackerman printf("ixgb%d: Could not setup receive structures\n", 690129794Stackerman adapter->unit); 691129794Stackerman ixgb_stop(adapter); 692129794Stackerman return; 693129794Stackerman } 694129794Stackerman ixgb_initialize_receive_unit(adapter); 695129794Stackerman 696129794Stackerman /* Don't loose promiscuous settings */ 697129794Stackerman ixgb_set_promisc(adapter); 698129794Stackerman 699147256Sbrooks ifp = adapter->ifp; 700148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 701148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 702129794Stackerman 703129794Stackerman 704129794Stackerman if (ifp->if_capenable & IFCAP_TXCSUM) 705129794Stackerman ifp->if_hwassist = IXGB_CHECKSUM_FEATURES; 706129794Stackerman else 707129794Stackerman ifp->if_hwassist = 0; 708129794Stackerman 709129794Stackerman 710129794Stackerman /* Enable jumbo frames */ 711129794Stackerman if (ifp->if_mtu > ETHERMTU) { 712129794Stackerman uint32_t temp_reg; 713129794Stackerman IXGB_WRITE_REG(&adapter->hw, MFS, 714129794Stackerman adapter->hw.max_frame_size << IXGB_MFS_SHIFT); 715129794Stackerman temp_reg = IXGB_READ_REG(&adapter->hw, CTRL0); 716129794Stackerman temp_reg |= IXGB_CTRL0_JFE; 717129794Stackerman IXGB_WRITE_REG(&adapter->hw, CTRL0, temp_reg); 718129794Stackerman } 719144651Salc callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, adapter); 720129794Stackerman ixgb_clear_hw_cntrs(&adapter->hw); 721129794Stackerman#ifdef DEVICE_POLLING 722129794Stackerman /* 723129794Stackerman * Only disable interrupts if we are polling, make sure they are on 724129794Stackerman * otherwise. 725129794Stackerman */ 726150789Sglebius if (ifp->if_capenable & IFCAP_POLLING) 727129794Stackerman ixgb_disable_intr(adapter); 728129794Stackerman else 729150789Sglebius#endif 730129794Stackerman ixgb_enable_intr(adapter); 731129794Stackerman 732129794Stackerman return; 733129794Stackerman} 734129794Stackerman 735144651Salcstatic void 736144651Salcixgb_init(void *arg) 737144651Salc{ 738144651Salc struct adapter *adapter = arg; 739129794Stackerman 740144651Salc IXGB_LOCK(adapter); 741144651Salc ixgb_init_locked(adapter); 742144651Salc IXGB_UNLOCK(adapter); 743144651Salc return; 744144651Salc} 745144651Salc 746129794Stackerman#ifdef DEVICE_POLLING 747129794Stackermanstatic void 748144651Salcixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count) 749129794Stackerman{ 750129794Stackerman struct adapter *adapter = ifp->if_softc; 751129794Stackerman u_int32_t reg_icr; 752129794Stackerman 753144651Salc IXGB_LOCK_ASSERT(adapter); 754144651Salc 755129794Stackerman if (cmd == POLL_AND_CHECK_STATUS) { 756129794Stackerman reg_icr = IXGB_READ_REG(&adapter->hw, ICR); 757129794Stackerman if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) { 758144651Salc callout_stop(&adapter->timer); 759129794Stackerman ixgb_check_for_link(&adapter->hw); 760129794Stackerman ixgb_print_link_status(adapter); 761144651Salc callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, 762144651Salc adapter); 763129794Stackerman } 764129794Stackerman } 765150789Sglebius ixgb_process_receive_interrupts(adapter, count); 766150789Sglebius ixgb_clean_transmit_interrupts(adapter); 767150789Sglebius 768150789Sglebius if (ifp->if_snd.ifq_head != NULL) 769144651Salc ixgb_start_locked(ifp); 770129794Stackerman} 771144651Salc 772144651Salcstatic void 773144651Salcixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count) 774144651Salc{ 775144651Salc struct adapter *adapter = ifp->if_softc; 776144651Salc 777144651Salc IXGB_LOCK(adapter); 778150789Sglebius if (ifp->if_drv_flags & IFF_DRV_RUNNING) 779150789Sglebius ixgb_poll_locked(ifp, cmd, count); 780144651Salc IXGB_UNLOCK(adapter); 781144651Salc} 782150789Sglebius#endif /* DEVICE_POLLING */ 783129794Stackerman 784129794Stackerman/********************************************************************* 785129794Stackerman * 786129794Stackerman * Interrupt Service routine 787129794Stackerman * 788129794Stackerman **********************************************************************/ 789129794Stackerman 790129794Stackermanstatic void 791129794Stackermanixgb_intr(void *arg) 792129794Stackerman{ 793129794Stackerman u_int32_t loop_cnt = IXGB_MAX_INTR; 794129794Stackerman u_int32_t reg_icr; 795129794Stackerman struct ifnet *ifp; 796129794Stackerman struct adapter *adapter = arg; 797129794Stackerman boolean_t rxdmt0 = FALSE; 798129794Stackerman 799144651Salc IXGB_LOCK(adapter); 800144651Salc 801147256Sbrooks ifp = adapter->ifp; 802129794Stackerman 803129794Stackerman#ifdef DEVICE_POLLING 804150789Sglebius if (ifp->if_capenable & IFCAP_POLLING) { 805144651Salc IXGB_UNLOCK(adapter); 806129794Stackerman return; 807144651Salc } 808150789Sglebius#endif 809129794Stackerman 810144651Salc reg_icr = IXGB_READ_REG(&adapter->hw, ICR); 811144651Salc if (reg_icr == 0) { 812144651Salc IXGB_UNLOCK(adapter); 813129794Stackerman return; 814144651Salc } 815129794Stackerman 816129794Stackerman if (reg_icr & IXGB_INT_RXDMT0) 817129794Stackerman rxdmt0 = TRUE; 818129794Stackerman 819129794Stackerman#ifdef _SV_ 820129794Stackerman if (reg_icr & IXGB_INT_RXDMT0) 821129794Stackerman adapter->sv_stats.icr_rxdmt0++; 822129794Stackerman if (reg_icr & IXGB_INT_RXO) 823129794Stackerman adapter->sv_stats.icr_rxo++; 824129794Stackerman if (reg_icr & IXGB_INT_RXT0) 825129794Stackerman adapter->sv_stats.icr_rxt0++; 826129794Stackerman if (reg_icr & IXGB_INT_TXDW) 827129794Stackerman adapter->sv_stats.icr_TXDW++; 828129794Stackerman#endif /* _SV_ */ 829129794Stackerman 830129794Stackerman /* Link status change */ 831129794Stackerman if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) { 832144651Salc callout_stop(&adapter->timer); 833129794Stackerman ixgb_check_for_link(&adapter->hw); 834129794Stackerman ixgb_print_link_status(adapter); 835144651Salc callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, 836144651Salc adapter); 837129794Stackerman } 838129794Stackerman while (loop_cnt > 0) { 839148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 840129794Stackerman ixgb_process_receive_interrupts(adapter, -1); 841129794Stackerman ixgb_clean_transmit_interrupts(adapter); 842129794Stackerman } 843129794Stackerman loop_cnt--; 844129794Stackerman } 845129794Stackerman 846129794Stackerman if (rxdmt0 && adapter->raidc) { 847129794Stackerman IXGB_WRITE_REG(&adapter->hw, IMC, IXGB_INT_RXDMT0); 848129794Stackerman IXGB_WRITE_REG(&adapter->hw, IMS, IXGB_INT_RXDMT0); 849129794Stackerman } 850148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING && ifp->if_snd.ifq_head != NULL) 851144651Salc ixgb_start_locked(ifp); 852129794Stackerman 853144651Salc IXGB_UNLOCK(adapter); 854129794Stackerman return; 855129794Stackerman} 856129794Stackerman 857129794Stackerman 858129794Stackerman/********************************************************************* 859129794Stackerman * 860129794Stackerman * Media Ioctl callback 861129794Stackerman * 862129794Stackerman * This routine is called whenever the user queries the status of 863129794Stackerman * the interface using ifconfig. 864129794Stackerman * 865129794Stackerman **********************************************************************/ 866129794Stackermanstatic void 867129794Stackermanixgb_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) 868129794Stackerman{ 869129794Stackerman struct adapter *adapter = ifp->if_softc; 870129794Stackerman 871129794Stackerman INIT_DEBUGOUT("ixgb_media_status: begin"); 872129794Stackerman 873129794Stackerman ixgb_check_for_link(&adapter->hw); 874129794Stackerman ixgb_print_link_status(adapter); 875129794Stackerman 876129794Stackerman ifmr->ifm_status = IFM_AVALID; 877129794Stackerman ifmr->ifm_active = IFM_ETHER; 878129794Stackerman 879129794Stackerman if (!adapter->hw.link_up) 880129794Stackerman return; 881129794Stackerman 882129794Stackerman ifmr->ifm_status |= IFM_ACTIVE; 883129794Stackerman ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; 884129794Stackerman 885129794Stackerman return; 886129794Stackerman} 887129794Stackerman 888129794Stackerman/********************************************************************* 889129794Stackerman * 890129794Stackerman * Media Ioctl callback 891129794Stackerman * 892129794Stackerman * This routine is called when the user changes speed/duplex using 893129794Stackerman * media/mediopt option with ifconfig. 894129794Stackerman * 895129794Stackerman **********************************************************************/ 896129794Stackermanstatic int 897129794Stackermanixgb_media_change(struct ifnet * ifp) 898129794Stackerman{ 899129794Stackerman struct adapter *adapter = ifp->if_softc; 900129794Stackerman struct ifmedia *ifm = &adapter->media; 901129794Stackerman 902129794Stackerman INIT_DEBUGOUT("ixgb_media_change: begin"); 903129794Stackerman 904129794Stackerman if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 905129794Stackerman return (EINVAL); 906129794Stackerman 907129794Stackerman return (0); 908129794Stackerman} 909129794Stackerman 910129794Stackerman/********************************************************************* 911129794Stackerman * 912129794Stackerman * This routine maps the mbufs to tx descriptors. 913129794Stackerman * 914129794Stackerman * return 0 on success, positive on failure 915129794Stackerman **********************************************************************/ 916129794Stackerman 917129794Stackermanstatic int 918129794Stackermanixgb_encap(struct adapter * adapter, struct mbuf * m_head) 919129794Stackerman{ 920129794Stackerman u_int8_t txd_popts; 921146339Salc int i, j, error, nsegs; 922129794Stackerman 923129794Stackerman#if __FreeBSD_version < 500000 924129794Stackerman struct ifvlan *ifv = NULL; 925129794Stackerman#else 926129794Stackerman struct m_tag *mtag; 927129794Stackerman#endif 928146339Salc bus_dma_segment_t segs[IXGB_MAX_SCATTER]; 929146339Salc bus_dmamap_t map; 930129794Stackerman struct ixgb_buffer *tx_buffer = NULL; 931129794Stackerman struct ixgb_tx_desc *current_tx_desc = NULL; 932147256Sbrooks struct ifnet *ifp = adapter->ifp; 933129794Stackerman 934129794Stackerman /* 935129794Stackerman * Force a cleanup if number of TX descriptors available hits the 936129794Stackerman * threshold 937129794Stackerman */ 938129794Stackerman if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) { 939129794Stackerman ixgb_clean_transmit_interrupts(adapter); 940129794Stackerman } 941129794Stackerman if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) { 942129794Stackerman adapter->no_tx_desc_avail1++; 943129794Stackerman return (ENOBUFS); 944129794Stackerman } 945129794Stackerman /* 946129794Stackerman * Map the packet for DMA. 947129794Stackerman */ 948146339Salc if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &map)) { 949129794Stackerman adapter->no_tx_map_avail++; 950129794Stackerman return (ENOMEM); 951129794Stackerman } 952146339Salc error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs, 953146339Salc &nsegs, BUS_DMA_NOWAIT); 954129794Stackerman if (error != 0) { 955129794Stackerman adapter->no_tx_dma_setup++; 956129794Stackerman printf("ixgb%d: ixgb_encap: bus_dmamap_load_mbuf failed; " 957129794Stackerman "error %u\n", adapter->unit, error); 958146339Salc bus_dmamap_destroy(adapter->txtag, map); 959129794Stackerman return (error); 960129794Stackerman } 961146339Salc KASSERT(nsegs != 0, ("ixgb_encap: empty packet")); 962129794Stackerman 963146339Salc if (nsegs > adapter->num_tx_desc_avail) { 964129794Stackerman adapter->no_tx_desc_avail2++; 965146339Salc bus_dmamap_destroy(adapter->txtag, map); 966129794Stackerman return (ENOBUFS); 967129794Stackerman } 968129794Stackerman if (ifp->if_hwassist > 0) { 969129794Stackerman ixgb_transmit_checksum_setup(adapter, m_head, 970129794Stackerman &txd_popts); 971129794Stackerman } else 972129794Stackerman txd_popts = 0; 973129794Stackerman 974129794Stackerman /* Find out if we are in vlan mode */ 975129794Stackerman#if __FreeBSD_version < 500000 976129794Stackerman if ((m_head->m_flags & (M_PROTO1 | M_PKTHDR)) == (M_PROTO1 | M_PKTHDR) && 977129794Stackerman m_head->m_pkthdr.rcvif != NULL && 978129794Stackerman m_head->m_pkthdr.rcvif->if_type == IFT_L2VLAN) 979129794Stackerman ifv = m_head->m_pkthdr.rcvif->if_softc; 980129794Stackerman#else 981129794Stackerman mtag = VLAN_OUTPUT_TAG(ifp, m_head); 982129794Stackerman#endif 983129794Stackerman i = adapter->next_avail_tx_desc; 984146339Salc for (j = 0; j < nsegs; j++) { 985129794Stackerman tx_buffer = &adapter->tx_buffer_area[i]; 986129794Stackerman current_tx_desc = &adapter->tx_desc_base[i]; 987129794Stackerman 988146339Salc current_tx_desc->buff_addr = htole64(segs[j].ds_addr); 989146339Salc current_tx_desc->cmd_type_len = (adapter->txd_cmd | segs[j].ds_len); 990129794Stackerman current_tx_desc->popts = txd_popts; 991129794Stackerman if (++i == adapter->num_tx_desc) 992129794Stackerman i = 0; 993129794Stackerman 994129794Stackerman tx_buffer->m_head = NULL; 995129794Stackerman } 996129794Stackerman 997146339Salc adapter->num_tx_desc_avail -= nsegs; 998129794Stackerman adapter->next_avail_tx_desc = i; 999129794Stackerman 1000129794Stackerman#if __FreeBSD_version < 500000 1001129794Stackerman if (ifv != NULL) { 1002129794Stackerman /* Set the vlan id */ 1003129794Stackerman current_tx_desc->vlan = ifv->ifv_tag; 1004129794Stackerman#else 1005129794Stackerman if (mtag != NULL) { 1006129794Stackerman /* Set the vlan id */ 1007129794Stackerman current_tx_desc->vlan = VLAN_TAG_VALUE(mtag); 1008129794Stackerman#endif 1009129794Stackerman 1010129794Stackerman /* Tell hardware to add tag */ 1011129794Stackerman current_tx_desc->cmd_type_len |= IXGB_TX_DESC_CMD_VLE; 1012129794Stackerman } 1013129794Stackerman tx_buffer->m_head = m_head; 1014146339Salc tx_buffer->map = map; 1015146339Salc bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE); 1016129794Stackerman 1017129794Stackerman /* 1018129794Stackerman * Last Descriptor of Packet needs End Of Packet (EOP) 1019129794Stackerman */ 1020129794Stackerman current_tx_desc->cmd_type_len |= (IXGB_TX_DESC_CMD_EOP); 1021129794Stackerman 1022129794Stackerman /* 1023129794Stackerman * Advance the Transmit Descriptor Tail (Tdt), this tells the E1000 1024129794Stackerman * that this frame is available to transmit. 1025129794Stackerman */ 1026129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDT, i); 1027129794Stackerman 1028129794Stackerman return (0); 1029129794Stackerman} 1030129794Stackerman 1031129794Stackermanstatic void 1032129794Stackermanixgb_set_promisc(struct adapter * adapter) 1033129794Stackerman{ 1034129794Stackerman 1035129794Stackerman u_int32_t reg_rctl; 1036147256Sbrooks struct ifnet *ifp = adapter->ifp; 1037129794Stackerman 1038129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1039129794Stackerman 1040129794Stackerman if (ifp->if_flags & IFF_PROMISC) { 1041129794Stackerman reg_rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE); 1042129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 1043129794Stackerman } else if (ifp->if_flags & IFF_ALLMULTI) { 1044129794Stackerman reg_rctl |= IXGB_RCTL_MPE; 1045129794Stackerman reg_rctl &= ~IXGB_RCTL_UPE; 1046129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 1047129794Stackerman } 1048129794Stackerman return; 1049129794Stackerman} 1050129794Stackerman 1051129794Stackermanstatic void 1052129794Stackermanixgb_disable_promisc(struct adapter * adapter) 1053129794Stackerman{ 1054129794Stackerman u_int32_t reg_rctl; 1055129794Stackerman 1056129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1057129794Stackerman 1058129794Stackerman reg_rctl &= (~IXGB_RCTL_UPE); 1059129794Stackerman reg_rctl &= (~IXGB_RCTL_MPE); 1060129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 1061129794Stackerman 1062129794Stackerman return; 1063129794Stackerman} 1064129794Stackerman 1065129794Stackerman 1066129794Stackerman/********************************************************************* 1067129794Stackerman * Multicast Update 1068129794Stackerman * 1069129794Stackerman * This routine is called whenever multicast address list is updated. 1070129794Stackerman * 1071129794Stackerman **********************************************************************/ 1072129794Stackerman 1073129794Stackermanstatic void 1074129794Stackermanixgb_set_multi(struct adapter * adapter) 1075129794Stackerman{ 1076129794Stackerman u_int32_t reg_rctl = 0; 1077129794Stackerman u_int8_t mta[MAX_NUM_MULTICAST_ADDRESSES * IXGB_ETH_LENGTH_OF_ADDRESS]; 1078129794Stackerman struct ifmultiaddr *ifma; 1079129794Stackerman int mcnt = 0; 1080147256Sbrooks struct ifnet *ifp = adapter->ifp; 1081129794Stackerman 1082129794Stackerman IOCTL_DEBUGOUT("ixgb_set_multi: begin"); 1083129794Stackerman 1084148654Srwatson IF_ADDR_LOCK(ifp); 1085129794Stackerman#if __FreeBSD_version < 500000 1086129794Stackerman LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1087129794Stackerman#else 1088129794Stackerman TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1089129794Stackerman#endif 1090129794Stackerman if (ifma->ifma_addr->sa_family != AF_LINK) 1091129794Stackerman continue; 1092129794Stackerman 1093129794Stackerman bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr), 1094129794Stackerman &mta[mcnt * IXGB_ETH_LENGTH_OF_ADDRESS], IXGB_ETH_LENGTH_OF_ADDRESS); 1095129794Stackerman mcnt++; 1096129794Stackerman } 1097148654Srwatson IF_ADDR_UNLOCK(ifp); 1098129794Stackerman 1099129794Stackerman if (mcnt > MAX_NUM_MULTICAST_ADDRESSES) { 1100129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1101129794Stackerman reg_rctl |= IXGB_RCTL_MPE; 1102129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 1103129794Stackerman } else 1104129794Stackerman ixgb_mc_addr_list_update(&adapter->hw, mta, mcnt, 0); 1105129794Stackerman 1106129794Stackerman return; 1107129794Stackerman} 1108129794Stackerman 1109129794Stackerman 1110129794Stackerman/********************************************************************* 1111129794Stackerman * Timer routine 1112129794Stackerman * 1113129794Stackerman * This routine checks for link status and updates statistics. 1114129794Stackerman * 1115129794Stackerman **********************************************************************/ 1116129794Stackerman 1117129794Stackermanstatic void 1118129794Stackermanixgb_local_timer(void *arg) 1119129794Stackerman{ 1120129794Stackerman struct ifnet *ifp; 1121129794Stackerman struct adapter *adapter = arg; 1122147256Sbrooks ifp = adapter->ifp; 1123129794Stackerman 1124144651Salc IXGB_LOCK(adapter); 1125129794Stackerman 1126129794Stackerman ixgb_check_for_link(&adapter->hw); 1127129794Stackerman ixgb_print_link_status(adapter); 1128129794Stackerman ixgb_update_stats_counters(adapter); 1129148887Srwatson if (ixgb_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) { 1130129794Stackerman ixgb_print_hw_stats(adapter); 1131129794Stackerman } 1132144651Salc callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, adapter); 1133129794Stackerman 1134144651Salc IXGB_UNLOCK(adapter); 1135129794Stackerman return; 1136129794Stackerman} 1137129794Stackerman 1138129794Stackermanstatic void 1139129794Stackermanixgb_print_link_status(struct adapter * adapter) 1140129794Stackerman{ 1141129794Stackerman if (adapter->hw.link_up) { 1142129794Stackerman if (!adapter->link_active) { 1143129794Stackerman printf("ixgb%d: Link is up %d Mbps %s \n", 1144129794Stackerman adapter->unit, 1145129794Stackerman 10000, 1146129794Stackerman "Full Duplex"); 1147129794Stackerman adapter->link_active = 1; 1148129794Stackerman } 1149129794Stackerman } else { 1150129794Stackerman if (adapter->link_active) { 1151129794Stackerman printf("ixgb%d: Link is Down \n", adapter->unit); 1152129794Stackerman adapter->link_active = 0; 1153129794Stackerman } 1154129794Stackerman } 1155129794Stackerman 1156129794Stackerman return; 1157129794Stackerman} 1158129794Stackerman 1159129794Stackerman 1160129794Stackerman 1161129794Stackerman/********************************************************************* 1162129794Stackerman * 1163129794Stackerman * This routine disables all traffic on the adapter by issuing a 1164129794Stackerman * global reset on the MAC and deallocates TX/RX buffers. 1165129794Stackerman * 1166129794Stackerman **********************************************************************/ 1167129794Stackerman 1168129794Stackermanstatic void 1169129794Stackermanixgb_stop(void *arg) 1170129794Stackerman{ 1171129794Stackerman struct ifnet *ifp; 1172129794Stackerman struct adapter *adapter = arg; 1173147256Sbrooks ifp = adapter->ifp; 1174129794Stackerman 1175144651Salc IXGB_LOCK_ASSERT(adapter); 1176144651Salc 1177129794Stackerman INIT_DEBUGOUT("ixgb_stop: begin\n"); 1178129794Stackerman ixgb_disable_intr(adapter); 1179129794Stackerman adapter->hw.adapter_stopped = FALSE; 1180129794Stackerman ixgb_adapter_stop(&adapter->hw); 1181144651Salc callout_stop(&adapter->timer); 1182129794Stackerman ixgb_free_transmit_structures(adapter); 1183129794Stackerman ixgb_free_receive_structures(adapter); 1184129794Stackerman 1185129794Stackerman 1186129794Stackerman /* Tell the stack that the interface is no longer active */ 1187148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1188129794Stackerman 1189129794Stackerman return; 1190129794Stackerman} 1191129794Stackerman 1192129794Stackerman 1193129794Stackerman/********************************************************************* 1194129794Stackerman * 1195129794Stackerman * Determine hardware revision. 1196129794Stackerman * 1197129794Stackerman **********************************************************************/ 1198129794Stackermanstatic void 1199129794Stackermanixgb_identify_hardware(struct adapter * adapter) 1200129794Stackerman{ 1201129794Stackerman device_t dev = adapter->dev; 1202129794Stackerman 1203129794Stackerman /* Make sure our PCI config space has the necessary stuff set */ 1204129794Stackerman adapter->hw.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); 1205129794Stackerman if (!((adapter->hw.pci_cmd_word & PCIM_CMD_BUSMASTEREN) && 1206129794Stackerman (adapter->hw.pci_cmd_word & PCIM_CMD_MEMEN))) { 1207129794Stackerman printf("ixgb%d: Memory Access and/or Bus Master bits were not set!\n", 1208129794Stackerman adapter->unit); 1209129794Stackerman adapter->hw.pci_cmd_word |= 1210129794Stackerman (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); 1211129794Stackerman pci_write_config(dev, PCIR_COMMAND, adapter->hw.pci_cmd_word, 2); 1212129794Stackerman } 1213129794Stackerman /* Save off the information about this board */ 1214129794Stackerman adapter->hw.vendor_id = pci_get_vendor(dev); 1215129794Stackerman adapter->hw.device_id = pci_get_device(dev); 1216129794Stackerman adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1); 1217129794Stackerman adapter->hw.subsystem_vendor_id = pci_read_config(dev, PCIR_SUBVEND_0, 2); 1218129794Stackerman adapter->hw.subsystem_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 1219129794Stackerman 1220129794Stackerman /* Set MacType, etc. based on this PCI info */ 1221129794Stackerman switch (adapter->hw.device_id) { 1222129794Stackerman case IXGB_DEVICE_ID_82597EX: 1223129794Stackerman case IXGB_DEVICE_ID_82597EX_SR: 1224129794Stackerman adapter->hw.mac_type = ixgb_82597; 1225129794Stackerman break; 1226129794Stackerman default: 1227129794Stackerman INIT_DEBUGOUT1("Unknown device if 0x%x", adapter->hw.device_id); 1228129794Stackerman printf("ixgb%d: unsupported device id 0x%x\n", adapter->unit, adapter->hw.device_id); 1229129794Stackerman } 1230129794Stackerman 1231129794Stackerman return; 1232129794Stackerman} 1233129794Stackerman 1234129794Stackermanstatic int 1235129794Stackermanixgb_allocate_pci_resources(struct adapter * adapter) 1236129794Stackerman{ 1237129794Stackerman int rid; 1238129794Stackerman device_t dev = adapter->dev; 1239129794Stackerman 1240129794Stackerman rid = IXGB_MMBA; 1241129794Stackerman adapter->res_memory = bus_alloc_resource(dev, SYS_RES_MEMORY, 1242129794Stackerman &rid, 0, ~0, 1, 1243129794Stackerman RF_ACTIVE); 1244129794Stackerman if (!(adapter->res_memory)) { 1245129794Stackerman printf("ixgb%d: Unable to allocate bus resource: memory\n", 1246129794Stackerman adapter->unit); 1247129794Stackerman return (ENXIO); 1248129794Stackerman } 1249129794Stackerman adapter->osdep.mem_bus_space_tag = 1250129794Stackerman rman_get_bustag(adapter->res_memory); 1251129794Stackerman adapter->osdep.mem_bus_space_handle = 1252129794Stackerman rman_get_bushandle(adapter->res_memory); 1253129794Stackerman adapter->hw.hw_addr = (uint8_t *) & adapter->osdep.mem_bus_space_handle; 1254129794Stackerman 1255129794Stackerman rid = 0x0; 1256129794Stackerman adapter->res_interrupt = bus_alloc_resource(dev, SYS_RES_IRQ, 1257129794Stackerman &rid, 0, ~0, 1, 1258129794Stackerman RF_SHAREABLE | RF_ACTIVE); 1259129794Stackerman if (!(adapter->res_interrupt)) { 1260129794Stackerman printf("ixgb%d: Unable to allocate bus resource: interrupt\n", 1261129794Stackerman adapter->unit); 1262129794Stackerman return (ENXIO); 1263129794Stackerman } 1264144651Salc if (bus_setup_intr(dev, adapter->res_interrupt, 1265144651Salc INTR_TYPE_NET | INTR_MPSAFE, 1266129794Stackerman (void (*) (void *))ixgb_intr, adapter, 1267129794Stackerman &adapter->int_handler_tag)) { 1268129794Stackerman printf("ixgb%d: Error registering interrupt handler!\n", 1269129794Stackerman adapter->unit); 1270129794Stackerman return (ENXIO); 1271129794Stackerman } 1272129794Stackerman adapter->hw.back = &adapter->osdep; 1273129794Stackerman 1274129794Stackerman return (0); 1275129794Stackerman} 1276129794Stackerman 1277129794Stackermanstatic void 1278129794Stackermanixgb_free_pci_resources(struct adapter * adapter) 1279129794Stackerman{ 1280129794Stackerman device_t dev = adapter->dev; 1281129794Stackerman 1282129794Stackerman if (adapter->res_interrupt != NULL) { 1283129794Stackerman bus_teardown_intr(dev, adapter->res_interrupt, 1284129794Stackerman adapter->int_handler_tag); 1285129794Stackerman bus_release_resource(dev, SYS_RES_IRQ, 0, 1286129794Stackerman adapter->res_interrupt); 1287129794Stackerman } 1288129794Stackerman if (adapter->res_memory != NULL) { 1289129794Stackerman bus_release_resource(dev, SYS_RES_MEMORY, IXGB_MMBA, 1290129794Stackerman adapter->res_memory); 1291129794Stackerman } 1292129794Stackerman if (adapter->res_ioport != NULL) { 1293129794Stackerman bus_release_resource(dev, SYS_RES_IOPORT, adapter->io_rid, 1294129794Stackerman adapter->res_ioport); 1295129794Stackerman } 1296129794Stackerman return; 1297129794Stackerman} 1298129794Stackerman 1299129794Stackerman/********************************************************************* 1300129794Stackerman * 1301129794Stackerman * Initialize the hardware to a configuration as specified by the 1302129794Stackerman * adapter structure. The controller is reset, the EEPROM is 1303129794Stackerman * verified, the MAC address is set, then the shared initialization 1304129794Stackerman * routines are called. 1305129794Stackerman * 1306129794Stackerman **********************************************************************/ 1307129794Stackermanstatic int 1308129794Stackermanixgb_hardware_init(struct adapter * adapter) 1309129794Stackerman{ 1310129794Stackerman /* Issue a global reset */ 1311129794Stackerman adapter->hw.adapter_stopped = FALSE; 1312129794Stackerman ixgb_adapter_stop(&adapter->hw); 1313129794Stackerman 1314129794Stackerman /* Make sure we have a good EEPROM before we read from it */ 1315129794Stackerman if (!ixgb_validate_eeprom_checksum(&adapter->hw)) { 1316129794Stackerman printf("ixgb%d: The EEPROM Checksum Is Not Valid\n", 1317129794Stackerman adapter->unit); 1318129794Stackerman return (EIO); 1319129794Stackerman } 1320129794Stackerman if (!ixgb_init_hw(&adapter->hw)) { 1321129794Stackerman printf("ixgb%d: Hardware Initialization Failed", 1322129794Stackerman adapter->unit); 1323129794Stackerman return (EIO); 1324129794Stackerman } 1325129794Stackerman 1326129794Stackerman return (0); 1327129794Stackerman} 1328129794Stackerman 1329129794Stackerman/********************************************************************* 1330129794Stackerman * 1331129794Stackerman * Setup networking device structure and register an interface. 1332129794Stackerman * 1333129794Stackerman **********************************************************************/ 1334129794Stackermanstatic void 1335129794Stackermanixgb_setup_interface(device_t dev, struct adapter * adapter) 1336129794Stackerman{ 1337129794Stackerman struct ifnet *ifp; 1338129794Stackerman INIT_DEBUGOUT("ixgb_setup_interface: begin"); 1339129794Stackerman 1340147256Sbrooks ifp = adapter->ifp = if_alloc(IFT_ETHER); 1341147256Sbrooks if (ifp == NULL) 1342147256Sbrooks panic("%s: can not if_alloc()\n", device_get_nameunit(dev)); 1343129794Stackerman#if __FreeBSD_version >= 502000 1344129794Stackerman if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 1345129794Stackerman#else 1346129794Stackerman ifp->if_unit = adapter->unit; 1347129794Stackerman ifp->if_name = "ixgb"; 1348129794Stackerman#endif 1349129794Stackerman ifp->if_mtu = ETHERMTU; 1350129794Stackerman ifp->if_baudrate = 1000000000; 1351129794Stackerman ifp->if_init = ixgb_init; 1352129794Stackerman ifp->if_softc = adapter; 1353144651Salc ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1354129794Stackerman ifp->if_ioctl = ixgb_ioctl; 1355129794Stackerman ifp->if_start = ixgb_start; 1356129794Stackerman ifp->if_watchdog = ixgb_watchdog; 1357129794Stackerman ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 1; 1358129794Stackerman 1359129794Stackerman#if __FreeBSD_version < 500000 1360129794Stackerman ether_ifattach(ifp, ETHER_BPF_SUPPORTED); 1361129794Stackerman#else 1362147256Sbrooks ether_ifattach(ifp, adapter->hw.curr_mac_addr); 1363129794Stackerman#endif 1364129794Stackerman 1365129794Stackerman ifp->if_capabilities = IFCAP_HWCSUM; 1366129794Stackerman 1367129794Stackerman /* 1368129794Stackerman * Tell the upper layer(s) we support long frames. 1369129794Stackerman */ 1370129794Stackerman ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 1371129794Stackerman 1372129794Stackerman#if __FreeBSD_version >= 500000 1373129794Stackerman ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; 1374129794Stackerman#endif 1375148637Sbrueffer 1376148637Sbrueffer ifp->if_capenable = ifp->if_capabilities; 1377148637Sbrueffer 1378150789Sglebius#ifdef DEVICE_POLLING 1379150789Sglebius ifp->if_capabilities |= IFCAP_POLLING; 1380150789Sglebius#endif 1381150789Sglebius 1382129794Stackerman /* 1383129794Stackerman * Specify the media types supported by this adapter and register 1384129794Stackerman * callbacks to update media and link information 1385129794Stackerman */ 1386129794Stackerman ifmedia_init(&adapter->media, IFM_IMASK, ixgb_media_change, 1387129794Stackerman ixgb_media_status); 1388129794Stackerman ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX | IFM_FDX, 1389129794Stackerman 0, NULL); 1390129794Stackerman ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 1391129794Stackerman 0, NULL); 1392129794Stackerman ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL); 1393129794Stackerman ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); 1394129794Stackerman 1395129794Stackerman return; 1396129794Stackerman} 1397129794Stackerman 1398129794Stackerman/******************************************************************** 1399129794Stackerman * Manage DMA'able memory. 1400129794Stackerman *******************************************************************/ 1401129794Stackermanstatic void 1402129794Stackermanixgb_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg, int error) 1403129794Stackerman{ 1404129794Stackerman if (error) 1405129794Stackerman return; 1406129794Stackerman *(bus_addr_t *) arg = segs->ds_addr; 1407129794Stackerman return; 1408129794Stackerman} 1409129794Stackerman 1410129794Stackermanstatic int 1411129794Stackermanixgb_dma_malloc(struct adapter * adapter, bus_size_t size, 1412129794Stackerman struct ixgb_dma_alloc * dma, int mapflags) 1413129794Stackerman{ 1414129794Stackerman int r; 1415129794Stackerman 1416129794Stackerman r = bus_dma_tag_create(NULL, /* parent */ 1417129794Stackerman PAGE_SIZE, 0, /* alignment, bounds */ 1418129794Stackerman BUS_SPACE_MAXADDR, /* lowaddr */ 1419129794Stackerman BUS_SPACE_MAXADDR, /* highaddr */ 1420129794Stackerman NULL, NULL, /* filter, filterarg */ 1421129794Stackerman size, /* maxsize */ 1422129794Stackerman 1, /* nsegments */ 1423129794Stackerman size, /* maxsegsize */ 1424129794Stackerman BUS_DMA_ALLOCNOW, /* flags */ 1425129794Stackerman#if __FreeBSD_version >= 502000 1426129794Stackerman NULL, /* lockfunc */ 1427129794Stackerman NULL, /* lockfuncarg */ 1428129794Stackerman#endif 1429129794Stackerman &dma->dma_tag); 1430129794Stackerman if (r != 0) { 1431129794Stackerman printf("ixgb%d: ixgb_dma_malloc: bus_dma_tag_create failed; " 1432129794Stackerman "error %u\n", adapter->unit, r); 1433129794Stackerman goto fail_0; 1434129794Stackerman } 1435129794Stackerman r = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr, 1436129794Stackerman BUS_DMA_NOWAIT, &dma->dma_map); 1437129794Stackerman if (r != 0) { 1438129794Stackerman printf("ixgb%d: ixgb_dma_malloc: bus_dmamem_alloc failed; " 1439129794Stackerman "error %u\n", adapter->unit, r); 1440144183Smux goto fail_1; 1441129794Stackerman } 1442129794Stackerman r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, 1443129794Stackerman size, 1444129794Stackerman ixgb_dmamap_cb, 1445129794Stackerman &dma->dma_paddr, 1446129794Stackerman mapflags | BUS_DMA_NOWAIT); 1447129794Stackerman if (r != 0) { 1448129794Stackerman printf("ixgb%d: ixgb_dma_malloc: bus_dmamap_load failed; " 1449129794Stackerman "error %u\n", adapter->unit, r); 1450144183Smux goto fail_2; 1451129794Stackerman } 1452129794Stackerman dma->dma_size = size; 1453129794Stackerman return (0); 1454129794Stackermanfail_2: 1455129794Stackerman bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1456129794Stackermanfail_1: 1457129794Stackerman bus_dma_tag_destroy(dma->dma_tag); 1458129794Stackermanfail_0: 1459129794Stackerman dma->dma_map = NULL; 1460129794Stackerman dma->dma_tag = NULL; 1461129794Stackerman return (r); 1462129794Stackerman} 1463129794Stackerman 1464129794Stackerman 1465129794Stackerman 1466129794Stackermanstatic void 1467129794Stackermanixgb_dma_free(struct adapter * adapter, struct ixgb_dma_alloc * dma) 1468129794Stackerman{ 1469129794Stackerman bus_dmamap_unload(dma->dma_tag, dma->dma_map); 1470129794Stackerman bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); 1471129794Stackerman bus_dma_tag_destroy(dma->dma_tag); 1472129794Stackerman} 1473129794Stackerman 1474129794Stackerman/********************************************************************* 1475129794Stackerman * 1476129794Stackerman * Allocate memory for tx_buffer structures. The tx_buffer stores all 1477129794Stackerman * the information needed to transmit a packet on the wire. 1478129794Stackerman * 1479129794Stackerman **********************************************************************/ 1480129794Stackermanstatic int 1481129794Stackermanixgb_allocate_transmit_structures(struct adapter * adapter) 1482129794Stackerman{ 1483129794Stackerman if (!(adapter->tx_buffer_area = 1484129794Stackerman (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) * 1485129794Stackerman adapter->num_tx_desc, M_DEVBUF, 1486129794Stackerman M_NOWAIT | M_ZERO))) { 1487129794Stackerman printf("ixgb%d: Unable to allocate tx_buffer memory\n", 1488129794Stackerman adapter->unit); 1489129794Stackerman return ENOMEM; 1490129794Stackerman } 1491129794Stackerman bzero(adapter->tx_buffer_area, 1492129794Stackerman sizeof(struct ixgb_buffer) * adapter->num_tx_desc); 1493129794Stackerman 1494129794Stackerman return 0; 1495129794Stackerman} 1496129794Stackerman 1497129794Stackerman/********************************************************************* 1498129794Stackerman * 1499129794Stackerman * Allocate and initialize transmit structures. 1500129794Stackerman * 1501129794Stackerman **********************************************************************/ 1502129794Stackermanstatic int 1503129794Stackermanixgb_setup_transmit_structures(struct adapter * adapter) 1504129794Stackerman{ 1505129794Stackerman /* 1506129794Stackerman * Setup DMA descriptor areas. 1507129794Stackerman */ 1508129794Stackerman if (bus_dma_tag_create(NULL, /* parent */ 1509129794Stackerman PAGE_SIZE, 0, /* alignment, bounds */ 1510129794Stackerman BUS_SPACE_MAXADDR, /* lowaddr */ 1511129794Stackerman BUS_SPACE_MAXADDR, /* highaddr */ 1512129794Stackerman NULL, NULL, /* filter, filterarg */ 1513129794Stackerman MCLBYTES * IXGB_MAX_SCATTER, /* maxsize */ 1514129794Stackerman IXGB_MAX_SCATTER, /* nsegments */ 1515129794Stackerman MCLBYTES, /* maxsegsize */ 1516129794Stackerman BUS_DMA_ALLOCNOW, /* flags */ 1517129794Stackerman#if __FreeBSD_version >= 502000 1518129794Stackerman NULL, /* lockfunc */ 1519129794Stackerman NULL, /* lockfuncarg */ 1520129794Stackerman#endif 1521129794Stackerman &adapter->txtag)) { 1522129794Stackerman printf("ixgb%d: Unable to allocate TX DMA tag\n", adapter->unit); 1523129794Stackerman return (ENOMEM); 1524129794Stackerman } 1525129794Stackerman if (ixgb_allocate_transmit_structures(adapter)) 1526129794Stackerman return ENOMEM; 1527129794Stackerman 1528129794Stackerman bzero((void *)adapter->tx_desc_base, 1529129794Stackerman (sizeof(struct ixgb_tx_desc)) * adapter->num_tx_desc); 1530129794Stackerman 1531129794Stackerman adapter->next_avail_tx_desc = 0; 1532129794Stackerman adapter->oldest_used_tx_desc = 0; 1533129794Stackerman 1534129794Stackerman /* Set number of descriptors available */ 1535129794Stackerman adapter->num_tx_desc_avail = adapter->num_tx_desc; 1536129794Stackerman 1537129794Stackerman /* Set checksum context */ 1538129794Stackerman adapter->active_checksum_context = OFFLOAD_NONE; 1539129794Stackerman 1540129794Stackerman return 0; 1541129794Stackerman} 1542129794Stackerman 1543129794Stackerman/********************************************************************* 1544129794Stackerman * 1545129794Stackerman * Enable transmit unit. 1546129794Stackerman * 1547129794Stackerman **********************************************************************/ 1548129794Stackermanstatic void 1549129794Stackermanixgb_initialize_transmit_unit(struct adapter * adapter) 1550129794Stackerman{ 1551129794Stackerman u_int32_t reg_tctl; 1552144183Smux u_int64_t tdba = adapter->txdma.dma_paddr; 1553129794Stackerman 1554129794Stackerman /* Setup the Base and Length of the Tx Descriptor Ring */ 1555129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDBAL, 1556129794Stackerman (tdba & 0x00000000ffffffffULL)); 1557129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32)); 1558129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDLEN, 1559129794Stackerman adapter->num_tx_desc * 1560129794Stackerman sizeof(struct ixgb_tx_desc)); 1561129794Stackerman 1562129794Stackerman /* Setup the HW Tx Head and Tail descriptor pointers */ 1563129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDH, 0); 1564129794Stackerman IXGB_WRITE_REG(&adapter->hw, TDT, 0); 1565129794Stackerman 1566129794Stackerman 1567129794Stackerman HW_DEBUGOUT2("Base = %x, Length = %x\n", 1568129794Stackerman IXGB_READ_REG(&adapter->hw, TDBAL), 1569129794Stackerman IXGB_READ_REG(&adapter->hw, TDLEN)); 1570129794Stackerman 1571129794Stackerman IXGB_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay); 1572129794Stackerman 1573129794Stackerman 1574129794Stackerman /* Program the Transmit Control Register */ 1575129794Stackerman reg_tctl = IXGB_READ_REG(&adapter->hw, TCTL); 1576129794Stackerman reg_tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE; 1577129794Stackerman IXGB_WRITE_REG(&adapter->hw, TCTL, reg_tctl); 1578129794Stackerman 1579129794Stackerman /* Setup Transmit Descriptor Settings for this adapter */ 1580129794Stackerman adapter->txd_cmd = IXGB_TX_DESC_TYPE | IXGB_TX_DESC_CMD_RS; 1581129794Stackerman 1582129794Stackerman if (adapter->tx_int_delay > 0) 1583129794Stackerman adapter->txd_cmd |= IXGB_TX_DESC_CMD_IDE; 1584129794Stackerman return; 1585129794Stackerman} 1586129794Stackerman 1587129794Stackerman/********************************************************************* 1588129794Stackerman * 1589129794Stackerman * Free all transmit related data structures. 1590129794Stackerman * 1591129794Stackerman **********************************************************************/ 1592129794Stackermanstatic void 1593129794Stackermanixgb_free_transmit_structures(struct adapter * adapter) 1594129794Stackerman{ 1595129794Stackerman struct ixgb_buffer *tx_buffer; 1596129794Stackerman int i; 1597129794Stackerman 1598129794Stackerman INIT_DEBUGOUT("free_transmit_structures: begin"); 1599129794Stackerman 1600129794Stackerman if (adapter->tx_buffer_area != NULL) { 1601129794Stackerman tx_buffer = adapter->tx_buffer_area; 1602129794Stackerman for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) { 1603129794Stackerman if (tx_buffer->m_head != NULL) { 1604129794Stackerman bus_dmamap_unload(adapter->txtag, tx_buffer->map); 1605129794Stackerman bus_dmamap_destroy(adapter->txtag, tx_buffer->map); 1606129794Stackerman m_freem(tx_buffer->m_head); 1607129794Stackerman } 1608129794Stackerman tx_buffer->m_head = NULL; 1609129794Stackerman } 1610129794Stackerman } 1611129794Stackerman if (adapter->tx_buffer_area != NULL) { 1612129794Stackerman free(adapter->tx_buffer_area, M_DEVBUF); 1613129794Stackerman adapter->tx_buffer_area = NULL; 1614129794Stackerman } 1615129794Stackerman if (adapter->txtag != NULL) { 1616129794Stackerman bus_dma_tag_destroy(adapter->txtag); 1617129794Stackerman adapter->txtag = NULL; 1618129794Stackerman } 1619129794Stackerman return; 1620129794Stackerman} 1621129794Stackerman 1622129794Stackerman/********************************************************************* 1623129794Stackerman * 1624129794Stackerman * The offload context needs to be set when we transfer the first 1625129794Stackerman * packet of a particular protocol (TCP/UDP). We change the 1626129794Stackerman * context only if the protocol type changes. 1627129794Stackerman * 1628129794Stackerman **********************************************************************/ 1629129794Stackermanstatic void 1630129794Stackermanixgb_transmit_checksum_setup(struct adapter * adapter, 1631129794Stackerman struct mbuf * mp, 1632129794Stackerman u_int8_t * txd_popts) 1633129794Stackerman{ 1634129794Stackerman struct ixgb_context_desc *TXD; 1635129794Stackerman struct ixgb_buffer *tx_buffer; 1636129794Stackerman int curr_txd; 1637129794Stackerman 1638129794Stackerman if (mp->m_pkthdr.csum_flags) { 1639129794Stackerman 1640129794Stackerman if (mp->m_pkthdr.csum_flags & CSUM_TCP) { 1641129794Stackerman *txd_popts = IXGB_TX_DESC_POPTS_TXSM; 1642129794Stackerman if (adapter->active_checksum_context == OFFLOAD_TCP_IP) 1643129794Stackerman return; 1644129794Stackerman else 1645129794Stackerman adapter->active_checksum_context = OFFLOAD_TCP_IP; 1646129794Stackerman } else if (mp->m_pkthdr.csum_flags & CSUM_UDP) { 1647129794Stackerman *txd_popts = IXGB_TX_DESC_POPTS_TXSM; 1648129794Stackerman if (adapter->active_checksum_context == OFFLOAD_UDP_IP) 1649129794Stackerman return; 1650129794Stackerman else 1651129794Stackerman adapter->active_checksum_context = OFFLOAD_UDP_IP; 1652129794Stackerman } else { 1653129794Stackerman *txd_popts = 0; 1654129794Stackerman return; 1655129794Stackerman } 1656129794Stackerman } else { 1657129794Stackerman *txd_popts = 0; 1658129794Stackerman return; 1659129794Stackerman } 1660129794Stackerman 1661129794Stackerman /* 1662129794Stackerman * If we reach this point, the checksum offload context needs to be 1663129794Stackerman * reset. 1664129794Stackerman */ 1665129794Stackerman curr_txd = adapter->next_avail_tx_desc; 1666129794Stackerman tx_buffer = &adapter->tx_buffer_area[curr_txd]; 1667129794Stackerman TXD = (struct ixgb_context_desc *) & adapter->tx_desc_base[curr_txd]; 1668129794Stackerman 1669129794Stackerman 1670129794Stackerman TXD->tucss = ENET_HEADER_SIZE + sizeof(struct ip); 1671129794Stackerman TXD->tucse = 0; 1672129794Stackerman 1673129794Stackerman TXD->mss = 0; 1674129794Stackerman 1675129794Stackerman if (adapter->active_checksum_context == OFFLOAD_TCP_IP) { 1676129794Stackerman TXD->tucso = 1677129794Stackerman ENET_HEADER_SIZE + sizeof(struct ip) + 1678129794Stackerman offsetof(struct tcphdr, th_sum); 1679129794Stackerman } else if (adapter->active_checksum_context == OFFLOAD_UDP_IP) { 1680129794Stackerman TXD->tucso = 1681129794Stackerman ENET_HEADER_SIZE + sizeof(struct ip) + 1682129794Stackerman offsetof(struct udphdr, uh_sum); 1683129794Stackerman } 1684129794Stackerman TXD->cmd_type_len = IXGB_CONTEXT_DESC_CMD_TCP | IXGB_TX_DESC_CMD_RS | IXGB_CONTEXT_DESC_CMD_IDE; 1685129794Stackerman 1686129794Stackerman tx_buffer->m_head = NULL; 1687129794Stackerman 1688129794Stackerman if (++curr_txd == adapter->num_tx_desc) 1689129794Stackerman curr_txd = 0; 1690129794Stackerman 1691129794Stackerman adapter->num_tx_desc_avail--; 1692129794Stackerman adapter->next_avail_tx_desc = curr_txd; 1693129794Stackerman return; 1694129794Stackerman} 1695129794Stackerman 1696129794Stackerman/********************************************************************** 1697129794Stackerman * 1698129794Stackerman * Examine each tx_buffer in the used queue. If the hardware is done 1699129794Stackerman * processing the packet then free associated resources. The 1700129794Stackerman * tx_buffer is put back on the free queue. 1701129794Stackerman * 1702129794Stackerman **********************************************************************/ 1703129794Stackermanstatic void 1704129794Stackermanixgb_clean_transmit_interrupts(struct adapter * adapter) 1705129794Stackerman{ 1706129794Stackerman int i, num_avail; 1707129794Stackerman struct ixgb_buffer *tx_buffer; 1708129794Stackerman struct ixgb_tx_desc *tx_desc; 1709129794Stackerman 1710144651Salc IXGB_LOCK_ASSERT(adapter); 1711129794Stackerman 1712129794Stackerman if (adapter->num_tx_desc_avail == adapter->num_tx_desc) 1713129794Stackerman return; 1714129794Stackerman 1715129794Stackerman#ifdef _SV_ 1716129794Stackerman adapter->clean_tx_interrupts++; 1717129794Stackerman#endif 1718129794Stackerman num_avail = adapter->num_tx_desc_avail; 1719129794Stackerman i = adapter->oldest_used_tx_desc; 1720129794Stackerman 1721129794Stackerman tx_buffer = &adapter->tx_buffer_area[i]; 1722129794Stackerman tx_desc = &adapter->tx_desc_base[i]; 1723129794Stackerman 1724129794Stackerman while (tx_desc->status & IXGB_TX_DESC_STATUS_DD) { 1725129794Stackerman 1726129794Stackerman tx_desc->status = 0; 1727129794Stackerman num_avail++; 1728129794Stackerman 1729129794Stackerman if (tx_buffer->m_head) { 1730129794Stackerman bus_dmamap_sync(adapter->txtag, tx_buffer->map, 1731129794Stackerman BUS_DMASYNC_POSTWRITE); 1732129794Stackerman bus_dmamap_unload(adapter->txtag, tx_buffer->map); 1733129794Stackerman bus_dmamap_destroy(adapter->txtag, tx_buffer->map); 1734129794Stackerman m_freem(tx_buffer->m_head); 1735129794Stackerman tx_buffer->m_head = NULL; 1736129794Stackerman } 1737129794Stackerman if (++i == adapter->num_tx_desc) 1738129794Stackerman i = 0; 1739129794Stackerman 1740129794Stackerman tx_buffer = &adapter->tx_buffer_area[i]; 1741129794Stackerman tx_desc = &adapter->tx_desc_base[i]; 1742129794Stackerman } 1743129794Stackerman 1744129794Stackerman adapter->oldest_used_tx_desc = i; 1745129794Stackerman 1746129794Stackerman /* 1747148887Srwatson * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that 1748129794Stackerman * it is OK to send packets. If there are no pending descriptors, 1749129794Stackerman * clear the timeout. Otherwise, if some descriptors have been freed, 1750129794Stackerman * restart the timeout. 1751129794Stackerman */ 1752129794Stackerman if (num_avail > IXGB_TX_CLEANUP_THRESHOLD) { 1753147256Sbrooks struct ifnet *ifp = adapter->ifp; 1754129794Stackerman 1755148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1756129794Stackerman if (num_avail == adapter->num_tx_desc) 1757129794Stackerman ifp->if_timer = 0; 1758129794Stackerman else if (num_avail == adapter->num_tx_desc_avail) 1759129794Stackerman ifp->if_timer = IXGB_TX_TIMEOUT; 1760129794Stackerman } 1761129794Stackerman adapter->num_tx_desc_avail = num_avail; 1762129794Stackerman return; 1763129794Stackerman} 1764129794Stackerman 1765129794Stackerman 1766129794Stackerman/********************************************************************* 1767129794Stackerman * 1768129794Stackerman * Get a buffer from system mbuf buffer pool. 1769129794Stackerman * 1770129794Stackerman **********************************************************************/ 1771129794Stackermanstatic int 1772129794Stackermanixgb_get_buf(int i, struct adapter * adapter, 1773129794Stackerman struct mbuf * nmp) 1774129794Stackerman{ 1775129794Stackerman register struct mbuf *mp = nmp; 1776129794Stackerman struct ixgb_buffer *rx_buffer; 1777129794Stackerman struct ifnet *ifp; 1778129794Stackerman bus_addr_t paddr; 1779129794Stackerman int error; 1780129794Stackerman 1781147256Sbrooks ifp = adapter->ifp; 1782129794Stackerman 1783129794Stackerman if (mp == NULL) { 1784129794Stackerman 1785129794Stackerman mp = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 1786129794Stackerman 1787129794Stackerman if (mp == NULL) { 1788129794Stackerman adapter->mbuf_alloc_failed++; 1789129794Stackerman return (ENOBUFS); 1790129794Stackerman } 1791129794Stackerman mp->m_len = mp->m_pkthdr.len = MCLBYTES; 1792129794Stackerman } else { 1793129794Stackerman mp->m_len = mp->m_pkthdr.len = MCLBYTES; 1794129794Stackerman mp->m_data = mp->m_ext.ext_buf; 1795129794Stackerman mp->m_next = NULL; 1796129794Stackerman } 1797129794Stackerman 1798129794Stackerman if (ifp->if_mtu <= ETHERMTU) { 1799129794Stackerman m_adj(mp, ETHER_ALIGN); 1800129794Stackerman } 1801129794Stackerman rx_buffer = &adapter->rx_buffer_area[i]; 1802129794Stackerman 1803129794Stackerman /* 1804129794Stackerman * Using memory from the mbuf cluster pool, invoke the bus_dma 1805129794Stackerman * machinery to arrange the memory mapping. 1806129794Stackerman */ 1807129794Stackerman error = bus_dmamap_load(adapter->rxtag, rx_buffer->map, 1808129794Stackerman mtod(mp, void *), mp->m_len, 1809129794Stackerman ixgb_dmamap_cb, &paddr, 0); 1810129794Stackerman if (error) { 1811129794Stackerman m_free(mp); 1812129794Stackerman return (error); 1813129794Stackerman } 1814129794Stackerman rx_buffer->m_head = mp; 1815129794Stackerman adapter->rx_desc_base[i].buff_addr = htole64(paddr); 1816129794Stackerman bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD); 1817129794Stackerman 1818129794Stackerman return (0); 1819129794Stackerman} 1820129794Stackerman 1821129794Stackerman/********************************************************************* 1822129794Stackerman * 1823129794Stackerman * Allocate memory for rx_buffer structures. Since we use one 1824129794Stackerman * rx_buffer per received packet, the maximum number of rx_buffer's 1825129794Stackerman * that we'll need is equal to the number of receive descriptors 1826129794Stackerman * that we've allocated. 1827129794Stackerman * 1828129794Stackerman **********************************************************************/ 1829129794Stackermanstatic int 1830129794Stackermanixgb_allocate_receive_structures(struct adapter * adapter) 1831129794Stackerman{ 1832129794Stackerman int i, error; 1833129794Stackerman struct ixgb_buffer *rx_buffer; 1834129794Stackerman 1835129794Stackerman if (!(adapter->rx_buffer_area = 1836129794Stackerman (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) * 1837129794Stackerman adapter->num_rx_desc, M_DEVBUF, 1838129794Stackerman M_NOWAIT | M_ZERO))) { 1839129794Stackerman printf("ixgb%d: Unable to allocate rx_buffer memory\n", 1840129794Stackerman adapter->unit); 1841129794Stackerman return (ENOMEM); 1842129794Stackerman } 1843129794Stackerman bzero(adapter->rx_buffer_area, 1844129794Stackerman sizeof(struct ixgb_buffer) * adapter->num_rx_desc); 1845129794Stackerman 1846129794Stackerman error = bus_dma_tag_create(NULL, /* parent */ 1847129794Stackerman PAGE_SIZE, 0, /* alignment, bounds */ 1848129794Stackerman BUS_SPACE_MAXADDR, /* lowaddr */ 1849129794Stackerman BUS_SPACE_MAXADDR, /* highaddr */ 1850129794Stackerman NULL, NULL, /* filter, filterarg */ 1851129794Stackerman MCLBYTES, /* maxsize */ 1852129794Stackerman 1, /* nsegments */ 1853129794Stackerman MCLBYTES, /* maxsegsize */ 1854129794Stackerman BUS_DMA_ALLOCNOW, /* flags */ 1855129794Stackerman#if __FreeBSD_version >= 502000 1856129794Stackerman NULL, /* lockfunc */ 1857129794Stackerman NULL, /* lockfuncarg */ 1858129794Stackerman#endif 1859129794Stackerman &adapter->rxtag); 1860129794Stackerman if (error != 0) { 1861129794Stackerman printf("ixgb%d: ixgb_allocate_receive_structures: " 1862129794Stackerman "bus_dma_tag_create failed; error %u\n", 1863129794Stackerman adapter->unit, error); 1864129794Stackerman goto fail_0; 1865129794Stackerman } 1866129794Stackerman rx_buffer = adapter->rx_buffer_area; 1867129794Stackerman for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 1868129794Stackerman error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT, 1869129794Stackerman &rx_buffer->map); 1870129794Stackerman if (error != 0) { 1871129794Stackerman printf("ixgb%d: ixgb_allocate_receive_structures: " 1872129794Stackerman "bus_dmamap_create failed; error %u\n", 1873129794Stackerman adapter->unit, error); 1874129794Stackerman goto fail_1; 1875129794Stackerman } 1876129794Stackerman } 1877129794Stackerman 1878129794Stackerman for (i = 0; i < adapter->num_rx_desc; i++) { 1879129794Stackerman if (ixgb_get_buf(i, adapter, NULL) == ENOBUFS) { 1880129794Stackerman adapter->rx_buffer_area[i].m_head = NULL; 1881129794Stackerman adapter->rx_desc_base[i].buff_addr = 0; 1882129794Stackerman return (ENOBUFS); 1883129794Stackerman } 1884129794Stackerman } 1885129794Stackerman 1886129794Stackerman return (0); 1887129794Stackermanfail_1: 1888129794Stackerman bus_dma_tag_destroy(adapter->rxtag); 1889129794Stackermanfail_0: 1890129794Stackerman adapter->rxtag = NULL; 1891129794Stackerman free(adapter->rx_buffer_area, M_DEVBUF); 1892129794Stackerman adapter->rx_buffer_area = NULL; 1893129794Stackerman return (error); 1894129794Stackerman} 1895129794Stackerman 1896129794Stackerman/********************************************************************* 1897129794Stackerman * 1898129794Stackerman * Allocate and initialize receive structures. 1899129794Stackerman * 1900129794Stackerman **********************************************************************/ 1901129794Stackermanstatic int 1902129794Stackermanixgb_setup_receive_structures(struct adapter * adapter) 1903129794Stackerman{ 1904129794Stackerman bzero((void *)adapter->rx_desc_base, 1905129794Stackerman (sizeof(struct ixgb_rx_desc)) * adapter->num_rx_desc); 1906129794Stackerman 1907129794Stackerman if (ixgb_allocate_receive_structures(adapter)) 1908129794Stackerman return ENOMEM; 1909129794Stackerman 1910129794Stackerman /* Setup our descriptor pointers */ 1911129794Stackerman adapter->next_rx_desc_to_check = 0; 1912129794Stackerman adapter->next_rx_desc_to_use = 0; 1913129794Stackerman return (0); 1914129794Stackerman} 1915129794Stackerman 1916129794Stackerman/********************************************************************* 1917129794Stackerman * 1918129794Stackerman * Enable receive unit. 1919129794Stackerman * 1920129794Stackerman **********************************************************************/ 1921129794Stackermanstatic void 1922129794Stackermanixgb_initialize_receive_unit(struct adapter * adapter) 1923129794Stackerman{ 1924129794Stackerman u_int32_t reg_rctl; 1925129794Stackerman u_int32_t reg_rxcsum; 1926129794Stackerman u_int32_t reg_rxdctl; 1927129794Stackerman struct ifnet *ifp; 1928144183Smux u_int64_t rdba = adapter->rxdma.dma_paddr; 1929129794Stackerman 1930147256Sbrooks ifp = adapter->ifp; 1931129794Stackerman 1932129794Stackerman /* 1933129794Stackerman * Make sure receives are disabled while setting up the descriptor 1934129794Stackerman * ring 1935129794Stackerman */ 1936129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1937129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl & ~IXGB_RCTL_RXEN); 1938129794Stackerman 1939129794Stackerman /* Set the Receive Delay Timer Register */ 1940129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDTR, 1941129794Stackerman adapter->rx_int_delay); 1942129794Stackerman 1943129794Stackerman 1944129794Stackerman /* Setup the Base and Length of the Rx Descriptor Ring */ 1945129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDBAL, 1946129794Stackerman (rdba & 0x00000000ffffffffULL)); 1947129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32)); 1948129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDLEN, adapter->num_rx_desc * 1949129794Stackerman sizeof(struct ixgb_rx_desc)); 1950129794Stackerman 1951129794Stackerman /* Setup the HW Rx Head and Tail Descriptor Pointers */ 1952129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDH, 0); 1953129794Stackerman 1954129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDT, adapter->num_rx_desc - 1); 1955129794Stackerman 1956129794Stackerman 1957129794Stackerman 1958129794Stackerman reg_rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT 1959129794Stackerman | RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT 1960129794Stackerman | RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT; 1961129794Stackerman IXGB_WRITE_REG(&adapter->hw, RXDCTL, reg_rxdctl); 1962129794Stackerman 1963129794Stackerman 1964129794Stackerman adapter->raidc = 1; 1965129794Stackerman if (adapter->raidc) { 1966129794Stackerman uint32_t raidc; 1967129794Stackerman uint8_t poll_threshold; 1968129794Stackerman#define IXGB_RAIDC_POLL_DEFAULT 120 1969129794Stackerman 1970129794Stackerman poll_threshold = ((adapter->num_rx_desc - 1) >> 3); 1971129794Stackerman poll_threshold >>= 1; 1972129794Stackerman poll_threshold &= 0x3F; 1973129794Stackerman raidc = IXGB_RAIDC_EN | IXGB_RAIDC_RXT_GATE | 1974129794Stackerman (IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) | 1975129794Stackerman (adapter->rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) | 1976129794Stackerman poll_threshold; 1977129794Stackerman IXGB_WRITE_REG(&adapter->hw, RAIDC, raidc); 1978129794Stackerman } 1979129794Stackerman /* Enable Receive Checksum Offload for TCP and UDP ? */ 1980129794Stackerman if (ifp->if_capenable & IFCAP_RXCSUM) { 1981129794Stackerman reg_rxcsum = IXGB_READ_REG(&adapter->hw, RXCSUM); 1982129794Stackerman reg_rxcsum |= IXGB_RXCSUM_TUOFL; 1983129794Stackerman IXGB_WRITE_REG(&adapter->hw, RXCSUM, reg_rxcsum); 1984129794Stackerman } 1985129794Stackerman /* Setup the Receive Control Register */ 1986129794Stackerman reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); 1987129794Stackerman reg_rctl &= ~(3 << IXGB_RCTL_MO_SHIFT); 1988129794Stackerman reg_rctl |= IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 | IXGB_RCTL_SECRC | 1989129794Stackerman IXGB_RCTL_CFF | 1990129794Stackerman (adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT); 1991129794Stackerman 1992129794Stackerman switch (adapter->rx_buffer_len) { 1993129794Stackerman default: 1994129794Stackerman case IXGB_RXBUFFER_2048: 1995129794Stackerman reg_rctl |= IXGB_RCTL_BSIZE_2048; 1996129794Stackerman break; 1997129794Stackerman case IXGB_RXBUFFER_4096: 1998129794Stackerman reg_rctl |= IXGB_RCTL_BSIZE_4096; 1999129794Stackerman break; 2000129794Stackerman case IXGB_RXBUFFER_8192: 2001129794Stackerman reg_rctl |= IXGB_RCTL_BSIZE_8192; 2002129794Stackerman break; 2003129794Stackerman case IXGB_RXBUFFER_16384: 2004129794Stackerman reg_rctl |= IXGB_RCTL_BSIZE_16384; 2005129794Stackerman break; 2006129794Stackerman } 2007129794Stackerman 2008129794Stackerman reg_rctl |= IXGB_RCTL_RXEN; 2009129794Stackerman 2010129794Stackerman 2011129794Stackerman /* Enable Receives */ 2012129794Stackerman IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl); 2013129794Stackerman 2014129794Stackerman return; 2015129794Stackerman} 2016129794Stackerman 2017129794Stackerman/********************************************************************* 2018129794Stackerman * 2019129794Stackerman * Free receive related data structures. 2020129794Stackerman * 2021129794Stackerman **********************************************************************/ 2022129794Stackermanstatic void 2023129794Stackermanixgb_free_receive_structures(struct adapter * adapter) 2024129794Stackerman{ 2025129794Stackerman struct ixgb_buffer *rx_buffer; 2026129794Stackerman int i; 2027129794Stackerman 2028129794Stackerman INIT_DEBUGOUT("free_receive_structures: begin"); 2029129794Stackerman 2030129794Stackerman if (adapter->rx_buffer_area != NULL) { 2031129794Stackerman rx_buffer = adapter->rx_buffer_area; 2032129794Stackerman for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { 2033129794Stackerman if (rx_buffer->map != NULL) { 2034129794Stackerman bus_dmamap_unload(adapter->rxtag, rx_buffer->map); 2035129794Stackerman bus_dmamap_destroy(adapter->rxtag, rx_buffer->map); 2036129794Stackerman } 2037129794Stackerman if (rx_buffer->m_head != NULL) 2038129794Stackerman m_freem(rx_buffer->m_head); 2039129794Stackerman rx_buffer->m_head = NULL; 2040129794Stackerman } 2041129794Stackerman } 2042129794Stackerman if (adapter->rx_buffer_area != NULL) { 2043129794Stackerman free(adapter->rx_buffer_area, M_DEVBUF); 2044129794Stackerman adapter->rx_buffer_area = NULL; 2045129794Stackerman } 2046129794Stackerman if (adapter->rxtag != NULL) { 2047129794Stackerman bus_dma_tag_destroy(adapter->rxtag); 2048129794Stackerman adapter->rxtag = NULL; 2049129794Stackerman } 2050129794Stackerman return; 2051129794Stackerman} 2052129794Stackerman 2053129794Stackerman/********************************************************************* 2054129794Stackerman * 2055129794Stackerman * This routine executes in interrupt context. It replenishes 2056129794Stackerman * the mbufs in the descriptor and sends data which has been 2057129794Stackerman * dma'ed into host memory to upper layer. 2058129794Stackerman * 2059129794Stackerman * We loop at most count times if count is > 0, or until done if 2060129794Stackerman * count < 0. 2061129794Stackerman * 2062129794Stackerman *********************************************************************/ 2063129794Stackermanstatic void 2064129794Stackermanixgb_process_receive_interrupts(struct adapter * adapter, int count) 2065129794Stackerman{ 2066129794Stackerman struct ifnet *ifp; 2067129794Stackerman struct mbuf *mp; 2068129794Stackerman#if __FreeBSD_version < 500000 2069129794Stackerman struct ether_header *eh; 2070129794Stackerman#endif 2071129794Stackerman int eop = 0; 2072129794Stackerman int len; 2073129794Stackerman u_int8_t accept_frame = 0; 2074129794Stackerman int i; 2075129794Stackerman int next_to_use = 0; 2076129794Stackerman int eop_desc; 2077129794Stackerman /* Pointer to the receive descriptor being examined. */ 2078129794Stackerman struct ixgb_rx_desc *current_desc; 2079129794Stackerman 2080144651Salc IXGB_LOCK_ASSERT(adapter); 2081144651Salc 2082147256Sbrooks ifp = adapter->ifp; 2083129794Stackerman i = adapter->next_rx_desc_to_check; 2084129794Stackerman next_to_use = adapter->next_rx_desc_to_use; 2085129794Stackerman eop_desc = adapter->next_rx_desc_to_check; 2086129794Stackerman current_desc = &adapter->rx_desc_base[i]; 2087129794Stackerman 2088129794Stackerman if (!((current_desc->status) & IXGB_RX_DESC_STATUS_DD)) { 2089129794Stackerman#ifdef _SV_ 2090129794Stackerman adapter->no_pkts_avail++; 2091129794Stackerman#endif 2092129794Stackerman return; 2093129794Stackerman } 2094129794Stackerman while ((current_desc->status & IXGB_RX_DESC_STATUS_DD) && (count != 0)) { 2095129794Stackerman 2096129794Stackerman mp = adapter->rx_buffer_area[i].m_head; 2097129794Stackerman bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map, 2098129794Stackerman BUS_DMASYNC_POSTREAD); 2099129794Stackerman accept_frame = 1; 2100129794Stackerman if (current_desc->status & IXGB_RX_DESC_STATUS_EOP) { 2101129794Stackerman count--; 2102129794Stackerman eop = 1; 2103129794Stackerman } else { 2104129794Stackerman eop = 0; 2105129794Stackerman } 2106129794Stackerman len = current_desc->length; 2107129794Stackerman 2108129794Stackerman if (current_desc->errors & (IXGB_RX_DESC_ERRORS_CE | 2109129794Stackerman IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P | 2110129794Stackerman IXGB_RX_DESC_ERRORS_RXE)) { 2111129794Stackerman accept_frame = 0; 2112129794Stackerman } 2113129794Stackerman if (accept_frame) { 2114129794Stackerman 2115129794Stackerman /* Assign correct length to the current fragment */ 2116129794Stackerman mp->m_len = len; 2117129794Stackerman 2118129794Stackerman if (adapter->fmp == NULL) { 2119129794Stackerman mp->m_pkthdr.len = len; 2120129794Stackerman adapter->fmp = mp; /* Store the first mbuf */ 2121129794Stackerman adapter->lmp = mp; 2122129794Stackerman } else { 2123129794Stackerman /* Chain mbuf's together */ 2124129794Stackerman mp->m_flags &= ~M_PKTHDR; 2125129794Stackerman adapter->lmp->m_next = mp; 2126129794Stackerman adapter->lmp = adapter->lmp->m_next; 2127129794Stackerman adapter->fmp->m_pkthdr.len += len; 2128129794Stackerman } 2129129794Stackerman 2130129794Stackerman if (eop) { 2131129794Stackerman eop_desc = i; 2132129794Stackerman adapter->fmp->m_pkthdr.rcvif = ifp; 2133129794Stackerman 2134129794Stackerman#if __FreeBSD_version < 500000 2135129794Stackerman eh = mtod(adapter->fmp, struct ether_header *); 2136129794Stackerman 2137129794Stackerman /* Remove ethernet header from mbuf */ 2138129794Stackerman m_adj(adapter->fmp, sizeof(struct ether_header)); 2139129794Stackerman ixgb_receive_checksum(adapter, current_desc, 2140129794Stackerman adapter->fmp); 2141129794Stackerman 2142129794Stackerman if (current_desc->status & IXGB_RX_DESC_STATUS_VP) 2143129794Stackerman VLAN_INPUT_TAG(eh, adapter->fmp, 2144129794Stackerman current_desc->special); 2145129794Stackerman else 2146129794Stackerman ether_input(ifp, eh, adapter->fmp); 2147129794Stackerman#else 2148129794Stackerman ixgb_receive_checksum(adapter, current_desc, 2149129794Stackerman adapter->fmp); 2150129794Stackerman if (current_desc->status & IXGB_RX_DESC_STATUS_VP) 2151129794Stackerman VLAN_INPUT_TAG(ifp, adapter->fmp, 2152129794Stackerman current_desc->special, 2153129794Stackerman adapter->fmp = NULL); 2154129794Stackerman 2155144651Salc if (adapter->fmp != NULL) { 2156144651Salc IXGB_UNLOCK(adapter); 2157129794Stackerman (*ifp->if_input) (ifp, adapter->fmp); 2158144651Salc IXGB_LOCK(adapter); 2159144651Salc } 2160129794Stackerman#endif 2161129794Stackerman adapter->fmp = NULL; 2162129794Stackerman adapter->lmp = NULL; 2163129794Stackerman } 2164129794Stackerman adapter->rx_buffer_area[i].m_head = NULL; 2165129794Stackerman } else { 2166129794Stackerman adapter->dropped_pkts++; 2167129794Stackerman if (adapter->fmp != NULL) 2168129794Stackerman m_freem(adapter->fmp); 2169129794Stackerman adapter->fmp = NULL; 2170129794Stackerman adapter->lmp = NULL; 2171129794Stackerman } 2172129794Stackerman 2173129794Stackerman /* Zero out the receive descriptors status */ 2174129794Stackerman current_desc->status = 0; 2175129794Stackerman 2176129794Stackerman /* Advance our pointers to the next descriptor */ 2177129794Stackerman if (++i == adapter->num_rx_desc) { 2178129794Stackerman i = 0; 2179129794Stackerman current_desc = adapter->rx_desc_base; 2180129794Stackerman } else 2181129794Stackerman current_desc++; 2182129794Stackerman } 2183129794Stackerman adapter->next_rx_desc_to_check = i; 2184129794Stackerman 2185129794Stackerman if (--i < 0) 2186129794Stackerman i = (adapter->num_rx_desc - 1); 2187129794Stackerman 2188129794Stackerman /* 2189129794Stackerman * 82597EX: Workaround for redundent write back in receive descriptor ring (causes 2190129794Stackerman * memory corruption). Avoid using and re-submitting the most recently received RX 2191129794Stackerman * descriptor back to hardware. 2192129794Stackerman * 2193129794Stackerman * if(Last written back descriptor == EOP bit set descriptor) 2194129794Stackerman * then avoid re-submitting the most recently received RX descriptor 2195129794Stackerman * back to hardware. 2196129794Stackerman * if(Last written back descriptor != EOP bit set descriptor) 2197129794Stackerman * then avoid re-submitting the most recently received RX descriptors 2198129794Stackerman * till last EOP bit set descriptor. 2199129794Stackerman */ 2200129794Stackerman if (eop_desc != i) { 2201129794Stackerman if (++eop_desc == adapter->num_rx_desc) 2202129794Stackerman eop_desc = 0; 2203129794Stackerman i = eop_desc; 2204129794Stackerman } 2205129794Stackerman /* Replenish the descriptors with new mbufs till last EOP bit set descriptor */ 2206129794Stackerman while (next_to_use != i) { 2207129794Stackerman current_desc = &adapter->rx_desc_base[next_to_use]; 2208129794Stackerman if ((current_desc->errors & (IXGB_RX_DESC_ERRORS_CE | 2209129794Stackerman IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P | 2210129794Stackerman IXGB_RX_DESC_ERRORS_RXE))) { 2211129794Stackerman mp = adapter->rx_buffer_area[next_to_use].m_head; 2212129794Stackerman ixgb_get_buf(next_to_use, adapter, mp); 2213129794Stackerman } else { 2214129794Stackerman if (ixgb_get_buf(next_to_use, adapter, NULL) == ENOBUFS) 2215129794Stackerman break; 2216129794Stackerman } 2217129794Stackerman /* Advance our pointers to the next descriptor */ 2218129794Stackerman if (++next_to_use == adapter->num_rx_desc) { 2219129794Stackerman next_to_use = 0; 2220129794Stackerman current_desc = adapter->rx_desc_base; 2221129794Stackerman } else 2222129794Stackerman current_desc++; 2223129794Stackerman } 2224129794Stackerman adapter->next_rx_desc_to_use = next_to_use; 2225129794Stackerman if (--next_to_use < 0) 2226129794Stackerman next_to_use = (adapter->num_rx_desc - 1); 2227129794Stackerman /* Advance the IXGB's Receive Queue #0 "Tail Pointer" */ 2228129794Stackerman IXGB_WRITE_REG(&adapter->hw, RDT, next_to_use); 2229129794Stackerman 2230129794Stackerman return; 2231129794Stackerman} 2232129794Stackerman 2233129794Stackerman/********************************************************************* 2234129794Stackerman * 2235129794Stackerman * Verify that the hardware indicated that the checksum is valid. 2236129794Stackerman * Inform the stack about the status of checksum so that stack 2237129794Stackerman * doesn't spend time verifying the checksum. 2238129794Stackerman * 2239129794Stackerman *********************************************************************/ 2240129794Stackermanstatic void 2241129794Stackermanixgb_receive_checksum(struct adapter * adapter, 2242129794Stackerman struct ixgb_rx_desc * rx_desc, 2243129794Stackerman struct mbuf * mp) 2244129794Stackerman{ 2245129794Stackerman if (rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) { 2246129794Stackerman mp->m_pkthdr.csum_flags = 0; 2247129794Stackerman return; 2248129794Stackerman } 2249129794Stackerman if (rx_desc->status & IXGB_RX_DESC_STATUS_IPCS) { 2250129794Stackerman /* Did it pass? */ 2251129794Stackerman if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_IPE)) { 2252129794Stackerman /* IP Checksum Good */ 2253129794Stackerman mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; 2254129794Stackerman mp->m_pkthdr.csum_flags |= CSUM_IP_VALID; 2255129794Stackerman 2256129794Stackerman } else { 2257129794Stackerman mp->m_pkthdr.csum_flags = 0; 2258129794Stackerman } 2259129794Stackerman } 2260129794Stackerman if (rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS) { 2261129794Stackerman /* Did it pass? */ 2262129794Stackerman if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE)) { 2263129794Stackerman mp->m_pkthdr.csum_flags |= 2264129794Stackerman (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); 2265129794Stackerman mp->m_pkthdr.csum_data = htons(0xffff); 2266129794Stackerman } 2267129794Stackerman } 2268129794Stackerman return; 2269129794Stackerman} 2270129794Stackerman 2271129794Stackerman 2272129794Stackermanstatic void 2273129794Stackermanixgb_enable_vlans(struct adapter * adapter) 2274129794Stackerman{ 2275129794Stackerman uint32_t ctrl; 2276129794Stackerman 2277129794Stackerman ctrl = IXGB_READ_REG(&adapter->hw, CTRL0); 2278129794Stackerman ctrl |= IXGB_CTRL0_VME; 2279129794Stackerman IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl); 2280129794Stackerman 2281129794Stackerman return; 2282129794Stackerman} 2283129794Stackerman 2284129794Stackerman 2285129794Stackermanstatic void 2286129794Stackermanixgb_enable_intr(struct adapter * adapter) 2287129794Stackerman{ 2288129794Stackerman IXGB_WRITE_REG(&adapter->hw, IMS, (IXGB_INT_RXT0 | IXGB_INT_TXDW | 2289129794Stackerman IXGB_INT_RXDMT0 | IXGB_INT_LSC | IXGB_INT_RXO)); 2290129794Stackerman return; 2291129794Stackerman} 2292129794Stackerman 2293129794Stackermanstatic void 2294129794Stackermanixgb_disable_intr(struct adapter * adapter) 2295129794Stackerman{ 2296129794Stackerman IXGB_WRITE_REG(&adapter->hw, IMC, ~0); 2297129794Stackerman return; 2298129794Stackerman} 2299129794Stackerman 2300129794Stackermanvoid 2301129794Stackermanixgb_write_pci_cfg(struct ixgb_hw * hw, 2302129794Stackerman uint32_t reg, 2303129794Stackerman uint16_t * value) 2304129794Stackerman{ 2305129794Stackerman pci_write_config(((struct ixgb_osdep *) hw->back)->dev, reg, 2306129794Stackerman *value, 2); 2307129794Stackerman} 2308129794Stackerman 2309129794Stackerman/********************************************************************** 2310129794Stackerman * 2311129794Stackerman * Update the board statistics counters. 2312129794Stackerman * 2313129794Stackerman **********************************************************************/ 2314129794Stackermanstatic void 2315129794Stackermanixgb_update_stats_counters(struct adapter * adapter) 2316129794Stackerman{ 2317129794Stackerman struct ifnet *ifp; 2318129794Stackerman 2319129794Stackerman adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS); 2320129794Stackerman adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL); 2321129794Stackerman adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH); 2322129794Stackerman adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL); 2323129794Stackerman adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH); 2324129794Stackerman adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL); 2325129794Stackerman adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH); 2326129794Stackerman adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL); 2327129794Stackerman adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH); 2328129794Stackerman adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC); 2329129794Stackerman 2330129794Stackerman adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC); 2331129794Stackerman adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC); 2332129794Stackerman adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC); 2333129794Stackerman adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC); 2334129794Stackerman adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC); 2335129794Stackerman adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC); 2336129794Stackerman adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC); 2337129794Stackerman adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL); 2338129794Stackerman adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH); 2339129794Stackerman adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL); 2340129794Stackerman adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH); 2341129794Stackerman adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC); 2342129794Stackerman adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC); 2343129794Stackerman adapter->stats.rjc += IXGB_READ_REG(&adapter->hw, RJC); 2344129794Stackerman adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL); 2345129794Stackerman adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH); 2346129794Stackerman adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL); 2347129794Stackerman adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH); 2348129794Stackerman adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL); 2349129794Stackerman adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH); 2350129794Stackerman adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL); 2351129794Stackerman adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH); 2352129794Stackerman adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C); 2353129794Stackerman adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL); 2354129794Stackerman adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH); 2355129794Stackerman adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL); 2356129794Stackerman adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH); 2357129794Stackerman 2358129794Stackerman adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL); 2359129794Stackerman adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH); 2360129794Stackerman adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL); 2361129794Stackerman adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH); 2362129794Stackerman adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL); 2363129794Stackerman adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH); 2364129794Stackerman adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC); 2365129794Stackerman adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC); 2366129794Stackerman adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC); 2367129794Stackerman adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL); 2368129794Stackerman adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH); 2369129794Stackerman adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL); 2370129794Stackerman adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH); 2371129794Stackerman adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL); 2372129794Stackerman adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH); 2373129794Stackerman adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC); 2374129794Stackerman adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC); 2375129794Stackerman adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC); 2376129794Stackerman adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC); 2377129794Stackerman adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC); 2378129794Stackerman adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC); 2379129794Stackerman adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC); 2380129794Stackerman 2381147256Sbrooks ifp = adapter->ifp; 2382129794Stackerman 2383129794Stackerman /* Fill out the OS statistics structure */ 2384129794Stackerman ifp->if_ipackets = adapter->stats.gprcl; 2385129794Stackerman ifp->if_opackets = adapter->stats.gptcl; 2386129794Stackerman ifp->if_ibytes = adapter->stats.gorcl; 2387129794Stackerman ifp->if_obytes = adapter->stats.gotcl; 2388129794Stackerman ifp->if_imcasts = adapter->stats.mprcl; 2389129794Stackerman ifp->if_collisions = 0; 2390129794Stackerman 2391129794Stackerman /* Rx Errors */ 2392129794Stackerman ifp->if_ierrors = 2393129794Stackerman adapter->dropped_pkts + 2394129794Stackerman adapter->stats.crcerrs + 2395129794Stackerman adapter->stats.rnbc + 2396129794Stackerman adapter->stats.mpc + 2397129794Stackerman adapter->stats.rlec; 2398129794Stackerman 2399129794Stackerman 2400129794Stackerman} 2401129794Stackerman 2402129794Stackerman 2403129794Stackerman/********************************************************************** 2404129794Stackerman * 2405129794Stackerman * This routine is called only when ixgb_display_debug_stats is enabled. 2406129794Stackerman * This routine provides a way to take a look at important statistics 2407129794Stackerman * maintained by the driver and hardware. 2408129794Stackerman * 2409129794Stackerman **********************************************************************/ 2410129794Stackermanstatic void 2411129794Stackermanixgb_print_hw_stats(struct adapter * adapter) 2412129794Stackerman{ 2413129794Stackerman char buf_speed[100], buf_type[100]; 2414129794Stackerman ixgb_bus_speed bus_speed; 2415129794Stackerman ixgb_bus_type bus_type; 2416129794Stackerman int unit = adapter->unit; 2417129794Stackerman 2418129794Stackerman#ifdef _SV_ 2419129794Stackerman printf("ixgb%d: Packets not Avail = %ld\n", unit, 2420129794Stackerman adapter->no_pkts_avail); 2421129794Stackerman printf("ixgb%d: CleanTxInterrupts = %ld\n", unit, 2422129794Stackerman adapter->clean_tx_interrupts); 2423129794Stackerman printf("ixgb%d: ICR RXDMT0 = %lld\n", unit, 2424129794Stackerman (long long)adapter->sv_stats.icr_rxdmt0); 2425129794Stackerman printf("ixgb%d: ICR RXO = %lld\n", unit, 2426129794Stackerman (long long)adapter->sv_stats.icr_rxo); 2427129794Stackerman printf("ixgb%d: ICR RXT0 = %lld\n", unit, 2428129794Stackerman (long long)adapter->sv_stats.icr_rxt0); 2429129794Stackerman printf("ixgb%d: ICR TXDW = %lld\n", unit, 2430129794Stackerman (long long)adapter->sv_stats.icr_TXDW); 2431129794Stackerman#endif /* _SV_ */ 2432129794Stackerman 2433129794Stackerman bus_speed = adapter->hw.bus.speed; 2434129794Stackerman bus_type = adapter->hw.bus.type; 2435129794Stackerman sprintf(buf_speed, 2436129794Stackerman bus_speed == ixgb_bus_speed_33 ? "33MHz" : 2437129794Stackerman bus_speed == ixgb_bus_speed_66 ? "66MHz" : 2438129794Stackerman bus_speed == ixgb_bus_speed_100 ? "100MHz" : 2439129794Stackerman bus_speed == ixgb_bus_speed_133 ? "133MHz" : 2440129794Stackerman "UNKNOWN"); 2441129794Stackerman printf("ixgb%d: PCI_Bus_Speed = %s\n", unit, 2442129794Stackerman buf_speed); 2443129794Stackerman 2444129794Stackerman sprintf(buf_type, 2445129794Stackerman bus_type == ixgb_bus_type_pci ? "PCI" : 2446129794Stackerman bus_type == ixgb_bus_type_pcix ? "PCI-X" : 2447129794Stackerman "UNKNOWN"); 2448129794Stackerman printf("ixgb%d: PCI_Bus_Type = %s\n", unit, 2449129794Stackerman buf_type); 2450129794Stackerman 2451129794Stackerman printf("ixgb%d: Tx Descriptors not Avail1 = %ld\n", unit, 2452129794Stackerman adapter->no_tx_desc_avail1); 2453129794Stackerman printf("ixgb%d: Tx Descriptors not Avail2 = %ld\n", unit, 2454129794Stackerman adapter->no_tx_desc_avail2); 2455129794Stackerman printf("ixgb%d: Std Mbuf Failed = %ld\n", unit, 2456129794Stackerman adapter->mbuf_alloc_failed); 2457129794Stackerman printf("ixgb%d: Std Cluster Failed = %ld\n", unit, 2458129794Stackerman adapter->mbuf_cluster_failed); 2459129794Stackerman 2460129794Stackerman printf("ixgb%d: Defer count = %lld\n", unit, 2461129794Stackerman (long long)adapter->stats.dc); 2462129794Stackerman printf("ixgb%d: Missed Packets = %lld\n", unit, 2463129794Stackerman (long long)adapter->stats.mpc); 2464129794Stackerman printf("ixgb%d: Receive No Buffers = %lld\n", unit, 2465129794Stackerman (long long)adapter->stats.rnbc); 2466129794Stackerman printf("ixgb%d: Receive length errors = %lld\n", unit, 2467129794Stackerman (long long)adapter->stats.rlec); 2468129794Stackerman printf("ixgb%d: Crc errors = %lld\n", unit, 2469129794Stackerman (long long)adapter->stats.crcerrs); 2470129794Stackerman printf("ixgb%d: Driver dropped packets = %ld\n", unit, 2471129794Stackerman adapter->dropped_pkts); 2472129794Stackerman 2473129794Stackerman printf("ixgb%d: XON Rcvd = %lld\n", unit, 2474129794Stackerman (long long)adapter->stats.xonrxc); 2475129794Stackerman printf("ixgb%d: XON Xmtd = %lld\n", unit, 2476129794Stackerman (long long)adapter->stats.xontxc); 2477129794Stackerman printf("ixgb%d: XOFF Rcvd = %lld\n", unit, 2478129794Stackerman (long long)adapter->stats.xoffrxc); 2479129794Stackerman printf("ixgb%d: XOFF Xmtd = %lld\n", unit, 2480129794Stackerman (long long)adapter->stats.xofftxc); 2481129794Stackerman 2482129794Stackerman printf("ixgb%d: Good Packets Rcvd = %lld\n", unit, 2483129794Stackerman (long long)adapter->stats.gprcl); 2484129794Stackerman printf("ixgb%d: Good Packets Xmtd = %lld\n", unit, 2485129794Stackerman (long long)adapter->stats.gptcl); 2486129794Stackerman 2487129794Stackerman printf("ixgb%d: Jumbo frames recvd = %lld\n", unit, 2488129794Stackerman (long long)adapter->stats.jprcl); 2489129794Stackerman printf("ixgb%d: Jumbo frames Xmtd = %lld\n", unit, 2490129794Stackerman (long long)adapter->stats.jptcl); 2491129794Stackerman 2492129794Stackerman return; 2493129794Stackerman 2494129794Stackerman} 2495129794Stackerman 2496129794Stackermanstatic int 2497129794Stackermanixgb_sysctl_stats(SYSCTL_HANDLER_ARGS) 2498129794Stackerman{ 2499129794Stackerman int error; 2500129794Stackerman int result; 2501129794Stackerman struct adapter *adapter; 2502129794Stackerman 2503129794Stackerman result = -1; 2504129794Stackerman error = sysctl_handle_int(oidp, &result, 0, req); 2505129794Stackerman 2506129794Stackerman if (error || !req->newptr) 2507129794Stackerman return (error); 2508129794Stackerman 2509129794Stackerman if (result == 1) { 2510129794Stackerman adapter = (struct adapter *) arg1; 2511129794Stackerman ixgb_print_hw_stats(adapter); 2512129794Stackerman } 2513129794Stackerman return error; 2514129794Stackerman} 2515