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