diff options
Diffstat (limited to 'sys/dev/em/if_em.c')
| -rw-r--r-- | sys/dev/em/if_em.c | 360 |
1 files changed, 230 insertions, 130 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index f5cbf56d6685..ce1c55a81377 100644 --- a/sys/dev/em/if_em.c +++ b/sys/dev/em/if_em.c @@ -51,7 +51,7 @@ struct adapter *em_adapter_list = NULL; * Driver version *********************************************************************/ -char em_driver_version[] = "1.5.31"; +char em_driver_version[] = "1.6.6"; /********************************************************************* @@ -87,6 +87,7 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, 0x101A, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} @@ -158,6 +159,10 @@ static void em_82547_move_tail(void *arg); static int em_dma_malloc(struct adapter *, bus_size_t, struct em_dma_alloc *, int); static void em_dma_free(struct adapter *, struct em_dma_alloc *); +static void em_print_debug_info(struct adapter *); +static int em_is_valid_ether_addr(u_int8_t *); +static int em_sysctl_stats(SYSCTL_HANDLER_ARGS); +static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS); /********************************************************************* * FreeBSD Device Interface Entry Points @@ -249,6 +254,7 @@ em_attach(device_t dev) struct adapter * adapter; int s; int tsize, rsize; + int error = 0; INIT_DEBUGOUT("em_attach: begin"); s = splimp(); @@ -269,6 +275,31 @@ em_attach(device_t dev) adapter->next = em_adapter_list; em_adapter_list = adapter; + /* SYSCTL stuff */ + sysctl_ctx_init(&adapter->sysctl_ctx); + adapter->sysctl_tree = SYSCTL_ADD_NODE(&adapter->sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_hw), + OID_AUTO, + device_get_nameunit(dev), + CTLFLAG_RD, + 0, ""); + if (adapter->sysctl_tree == NULL) { + error = EIO; + goto err_sysctl; + } + + SYSCTL_ADD_PROC(&adapter->sysctl_ctx, + SYSCTL_CHILDREN(adapter->sysctl_tree), + OID_AUTO, "debug_info", CTLTYPE_INT|CTLFLAG_RW, + (void *)adapter, 0, + em_sysctl_debug_info, "I", "Debug Information"); + + SYSCTL_ADD_PROC(&adapter->sysctl_ctx, + SYSCTL_CHILDREN(adapter->sysctl_tree), + OID_AUTO, "stats", CTLTYPE_INT|CTLFLAG_RW, + (void *)adapter, 0, + em_sysctl_stats, "I", "Statistics"); + callout_handle_init(&adapter->timer_handle); callout_handle_init(&adapter->tx_fifo_timer_handle); @@ -288,9 +319,10 @@ em_attach(device_t dev) adapter->hw.tbi_compatibility_en = TRUE; adapter->rx_buffer_len = EM_RXBUFFER_2048; - /* These parameters control the automatic generation(Tx) and - * response(Rx) to Ethernet PAUSE frames. - */ + /* + * These parameters control the automatic generation(Tx) and + * response(Rx) to Ethernet PAUSE frames. + */ adapter->hw.fc_high_water = FC_DEFAULT_HI_THRESH; adapter->hw.fc_low_water = FC_DEFAULT_LO_THRESH; adapter->hw.fc_pause_time = FC_DEFAULT_TX_TIMER; @@ -319,9 +351,8 @@ em_attach(device_t dev) if (em_allocate_pci_resources(adapter)) { printf("em%d: Allocation of PCI resources failed\n", adapter->unit); - em_free_pci_resources(adapter); - splx(s); - return(ENXIO); + error = ENXIO; + goto err_pci; } @@ -335,9 +366,8 @@ em_attach(device_t dev) if (em_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) { printf("em%d: Unable to allocate tx_desc memory\n", adapter->unit); - em_free_pci_resources(adapter); - splx(s); - return(ENOMEM); + error = ENOMEM; + goto err_tx_desc; } adapter->tx_desc_base = (struct em_tx_desc *) adapter->txdma.dma_vaddr; @@ -348,10 +378,8 @@ em_attach(device_t dev) if (em_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) { printf("em%d: Unable to allocate rx_desc memory\n", adapter->unit); - em_free_pci_resources(adapter); - em_dma_free(adapter, &adapter->txdma); - splx(s); - return(ENOMEM); + error = ENOMEM; + goto err_rx_desc; } adapter->rx_desc_base = (struct em_rx_desc *) adapter->rxdma.dma_vaddr; @@ -359,24 +387,24 @@ em_attach(device_t dev) if (em_hardware_init(adapter)) { printf("em%d: Unable to initialize the hardware\n", adapter->unit); - em_free_pci_resources(adapter); - em_dma_free(adapter, &adapter->txdma); - em_dma_free(adapter, &adapter->rxdma); - splx(s); - return(EIO); + error = EIO; + goto err_hw_init; } /* Copy the permanent MAC address out of the EEPROM */ if (em_read_mac_addr(&adapter->hw) < 0) { printf("em%d: EEPROM read error while reading mac address\n", adapter->unit); - em_free_pci_resources(adapter); - em_dma_free(adapter, &adapter->txdma); - em_dma_free(adapter, &adapter->rxdma); - splx(s); - return(EIO); + error = EIO; + goto err_mac_addr; } + if (!em_is_valid_ether_addr(adapter->hw.mac_addr)) { + printf("em%d: Invalid mac address\n", adapter->unit); + error = EIO; + goto err_mac_addr; + } + bcopy(adapter->hw.mac_addr, adapter->interface_data.ac_enaddr, ETHER_ADDR_LEN); @@ -403,6 +431,20 @@ em_attach(device_t dev) INIT_DEBUGOUT("em_attach: end"); splx(s); return(0); + +err_mac_addr: +err_hw_init: + em_dma_free(adapter, &adapter->rxdma); +err_rx_desc: + em_dma_free(adapter, &adapter->txdma); +err_tx_desc: +err_pci: + em_free_pci_resources(adapter); + sysctl_ctx_free(&adapter->sysctl_ctx); +err_sysctl: + splx(s); + return(error); + } /********************************************************************* @@ -579,9 +621,13 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if (ifp->if_flags & IFF_RUNNING) { em_disable_intr(adapter); em_set_multi(adapter); - if (adapter->hw.mac_type == em_82542_rev2_0) + if (adapter->hw.mac_type == em_82542_rev2_0) { em_initialize_receive_unit(adapter); - em_enable_intr(adapter); + } +#ifdef DEVICE_POLLING + if (!(ifp->if_ipending & IFF_POLLING)) +#endif + em_enable_intr(adapter); } break; case SIOCSIFMEDIA: @@ -787,31 +833,30 @@ em_intr(void *arg) } #endif /* DEVICE_POLLING */ + reg_icr = E1000_READ_REG(&adapter->hw, ICR); + if (!reg_icr) { + return; + } - em_disable_intr(adapter); - while (loop_cnt > 0 && - (reg_icr = E1000_READ_REG(&adapter->hw, ICR)) != 0) { - - /* Link status change */ - if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { - untimeout(em_local_timer, adapter, - adapter->timer_handle); - adapter->hw.get_link_status = 1; - em_check_for_link(&adapter->hw); - em_print_link_status(adapter); - adapter->timer_handle = - timeout(em_local_timer, adapter, 2*hz); - } + /* Link status change */ + if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + untimeout(em_local_timer, adapter, + adapter->timer_handle); + adapter->hw.get_link_status = 1; + em_check_for_link(&adapter->hw); + em_print_link_status(adapter); + adapter->timer_handle = + timeout(em_local_timer, adapter, 2*hz); + } + while (loop_cnt > 0) { if (ifp->if_flags & IFF_RUNNING) { em_process_receive_interrupts(adapter, -1); em_clean_transmit_interrupts(adapter); } loop_cnt--; } - - em_enable_intr(adapter); - + if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL) em_start(ifp); @@ -1915,32 +1960,23 @@ em_initialize_transmit_unit(struct adapter * adapter) E1000_READ_REG(&adapter->hw, TDBAL), E1000_READ_REG(&adapter->hw, TDLEN)); - /* Set the default values for the Tx Inter Packet Gap timer */ switch (adapter->hw.mac_type) { - case em_82543: - case em_82544: - case em_82540: - case em_82545: - case em_82546: - case em_82541: - case em_82547: - if (adapter->hw.media_type == em_media_type_fiber) - reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER; - else - reg_tipg = DEFAULT_82543_TIPG_IPGT_COPPER; - reg_tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; - reg_tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; - break; case em_82542_rev2_0: - case em_82542_rev2_1: - reg_tipg = DEFAULT_82542_TIPG_IPGT; - reg_tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; - reg_tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; - break; - default: - printf("em%d: Invalid mac type detected\n", adapter->unit); - } + case em_82542_rev2_1: + reg_tipg = DEFAULT_82542_TIPG_IPGT; + reg_tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; + reg_tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; + break; + default: + if (adapter->hw.media_type == em_media_type_fiber) + reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER; + else + reg_tipg = DEFAULT_82543_TIPG_IPGT_COPPER; + reg_tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; + reg_tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; + } + E1000_WRITE_REG(&adapter->hw, TIPG, reg_tipg); E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay); if(adapter->hw.mac_type >= em_82540) @@ -2100,6 +2136,7 @@ em_clean_transmit_interrupts(struct adapter * adapter) int i, num_avail; struct em_buffer *tx_buffer; struct em_tx_desc *tx_desc; + struct ifnet *ifp = &adapter->interface_data.ac_if; if (adapter->num_tx_desc_avail == adapter->num_tx_desc) return; @@ -2120,7 +2157,7 @@ em_clean_transmit_interrupts(struct adapter * adapter) num_avail++; if (tx_buffer->m_head) { - + ifp->if_opackets++; bus_dmamap_sync(adapter->txtag, tx_buffer->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(adapter->txtag, tx_buffer->map); @@ -2128,7 +2165,6 @@ em_clean_transmit_interrupts(struct adapter * adapter) m_freem(tx_buffer->m_head); tx_buffer->m_head = NULL; - } if (++i == adapter->num_tx_desc) @@ -2146,9 +2182,7 @@ em_clean_transmit_interrupts(struct adapter * adapter) * If there are no pending descriptors, clear the timeout. Otherwise, * if some descriptors have been freed, restart the timeout. */ - if (num_avail > EM_TX_CLEANUP_THRESHOLD) { - struct ifnet *ifp = &adapter->interface_data.ac_if; - + if (num_avail > EM_TX_CLEANUP_THRESHOLD) { ifp->if_flags &= ~IFF_OACTIVE; if (num_avail == adapter->num_tx_desc) ifp->if_timer = 0; @@ -2535,6 +2569,7 @@ em_process_receive_interrupts(struct adapter * adapter, int count) if (eop) { adapter->fmp->m_pkthdr.rcvif = ifp; + ifp->if_ipackets++; #if __FreeBSD_version < 500000 eh = mtod(adapter->fmp, struct ether_header *); @@ -2664,6 +2699,18 @@ em_disable_intr(struct adapter *adapter) return; } +static int +em_is_valid_ether_addr(u_int8_t *addr) +{ + char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; + + if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) { + return (FALSE); + } + + return(TRUE); +} + void em_write_pci_cfg(struct em_hw *hw, uint32_t reg, @@ -2798,8 +2845,6 @@ em_update_stats_counters(struct adapter *adapter) ifp = &adapter->interface_data.ac_if; /* Fill out the OS statistics structure */ - ifp->if_ipackets = adapter->stats.gprc; - ifp->if_opackets = adapter->stats.gptc; ifp->if_ibytes = adapter->stats.gorcl; ifp->if_obytes = adapter->stats.gotcl; ifp->if_imcasts = adapter->stats.mprc; @@ -2828,68 +2873,123 @@ em_update_stats_counters(struct adapter *adapter) * **********************************************************************/ static void -em_print_hw_stats(struct adapter *adapter) +em_print_debug_info(struct adapter *adapter) { - int unit = adapter->unit; + int unit = adapter->unit; #ifdef DBG_STATS - printf("em%d: Packets not Avail = %ld\n", unit, - adapter->no_pkts_avail); - printf("em%d: CleanTxInterrupts = %ld\n", unit, - adapter->clean_tx_interrupts); + printf("em%d: Packets not Avail = %ld\n", unit, + adapter->no_pkts_avail); + printf("em%d: CleanTxInterrupts = %ld\n", unit, + adapter->clean_tx_interrupts); #endif + printf("em%d: fifo workaround = %lld, fifo_reset = %lld\n", unit, + (long long)adapter->tx_fifo_wrk, + (long long)adapter->tx_fifo_reset); + printf("em%d: hw tdh = %d, hw tdt = %d\n", unit, + E1000_READ_REG(&adapter->hw, TDH), + E1000_READ_REG(&adapter->hw, TDT)); + printf("em%d: Num Tx descriptors avail = %d\n", unit, + adapter->num_tx_desc_avail); + printf("em%d: Tx Descriptors not avail1 = %ld\n", unit, + adapter->no_tx_desc_avail1); + printf("em%d: Tx Descriptors not avail2 = %ld\n", unit, + adapter->no_tx_desc_avail2); + printf("em%d: Std mbuf failed = %ld\n", unit, + adapter->mbuf_alloc_failed); + printf("em%d: Std mbuf cluster failed = %ld\n", unit, + adapter->mbuf_cluster_failed); + printf("em%d: Driver dropped packets = %ld\n", unit, + adapter->dropped_pkts); - printf("em%d: fifo workaround = %lld, fifo_reset = %lld\n", unit, - (long long)adapter->tx_fifo_wrk, - (long long)adapter->tx_fifo_reset); - printf("em%d: hw tdh = %d, hw tdt = %d\n", unit, - E1000_READ_REG(&adapter->hw, TDH), - E1000_READ_REG(&adapter->hw, TDT)); - printf("em%d: Excessive collisions = %lld\n", unit, - (long long)adapter->stats.ecol); - printf("em%d: Tx Descriptors not avail1 = %ld\n", unit, - adapter->no_tx_desc_avail1); - printf("em%d: Tx Descriptors not avail2 = %ld\n", unit, - adapter->no_tx_desc_avail2); - - printf("em%d: Symbol errors = %lld\n", unit, - (long long)adapter->stats.symerrs); - printf("em%d: Sequence errors = %lld\n", unit, - (long long)adapter->stats.sec); - printf("em%d: Defer count = %lld\n", unit, - (long long)adapter->stats.dc); - - printf("em%d: Missed Packets = %lld\n", unit, - (long long)adapter->stats.mpc); - printf("em%d: Receive No Buffers = %lld\n", unit, - (long long)adapter->stats.rnbc); - printf("em%d: Receive length errors = %lld\n", unit, - (long long)adapter->stats.rlec); - printf("em%d: Receive errors = %lld\n", unit, - (long long)adapter->stats.rxerrc); - printf("em%d: Crc errors = %lld\n", unit, - (long long)adapter->stats.crcerrs); - printf("em%d: Alignment errors = %lld\n", unit, - (long long)adapter->stats.algnerrc); - printf("em%d: Carrier extension errors = %lld\n", unit, - (long long)adapter->stats.cexterr); - printf("em%d: Driver dropped packets = %ld\n", unit, - adapter->dropped_pkts); - - printf("em%d: XON Rcvd = %lld\n", unit, - (long long)adapter->stats.xonrxc); - printf("em%d: XON Xmtd = %lld\n", unit, - (long long)adapter->stats.xontxc); - printf("em%d: XOFF Rcvd = %lld\n", unit, - (long long)adapter->stats.xoffrxc); - printf("em%d: XOFF Xmtd = %lld\n", unit, - (long long)adapter->stats.xofftxc); - - printf("em%d: Good Packets Rcvd = %lld\n", unit, - (long long)adapter->stats.gprc); - printf("em%d: Good Packets Xmtd = %lld\n", unit, - (long long)adapter->stats.gptc); + return; +} - return; +static void +em_print_hw_stats(struct adapter *adapter) +{ + int unit = adapter->unit; + + printf("em%d: Excessive collisions = %lld\n", unit, + (long long)adapter->stats.ecol); + printf("em%d: Symbol errors = %lld\n", unit, + (long long)adapter->stats.symerrs); + printf("em%d: Sequence errors = %lld\n", unit, + (long long)adapter->stats.sec); + printf("em%d: Defer count = %lld\n", unit, + (long long)adapter->stats.dc); + + printf("em%d: Missed Packets = %lld\n", unit, + (long long)adapter->stats.mpc); + printf("em%d: Receive No Buffers = %lld\n", unit, + (long long)adapter->stats.rnbc); + printf("em%d: Receive length errors = %lld\n", unit, + (long long)adapter->stats.rlec); + printf("em%d: Receive errors = %lld\n", unit, + (long long)adapter->stats.rxerrc); + printf("em%d: Crc errors = %lld\n", unit, + (long long)adapter->stats.crcerrs); + printf("em%d: Alignment errors = %lld\n", unit, + (long long)adapter->stats.algnerrc); + printf("em%d: Carrier extension errors = %lld\n", unit, + (long long)adapter->stats.cexterr); + + printf("em%d: XON Rcvd = %lld\n", unit, + (long long)adapter->stats.xonrxc); + printf("em%d: XON Xmtd = %lld\n", unit, + (long long)adapter->stats.xontxc); + printf("em%d: XOFF Rcvd = %lld\n", unit, + (long long)adapter->stats.xoffrxc); + printf("em%d: XOFF Xmtd = %lld\n", unit, + (long long)adapter->stats.xofftxc); + + printf("em%d: Good Packets Rcvd = %lld\n", unit, + (long long)adapter->stats.gprc); + printf("em%d: Good Packets Xmtd = %lld\n", unit, + (long long)adapter->stats.gptc); + + return; } +static int +em_sysctl_debug_info(SYSCTL_HANDLER_ARGS) +{ + int error; + int result; + struct adapter *adapter; + + result = -1; + error = sysctl_handle_int(oidp, &result, 0, req); + + if (error || !req->newptr) + return (error); + + if (result == 1) { + adapter = (struct adapter *)arg1; + em_print_debug_info(adapter); + } + + return error; +} + + +static int +em_sysctl_stats(SYSCTL_HANDLER_ARGS) +{ + int error; + int result; + struct adapter *adapter; + + result = -1; + error = sysctl_handle_int(oidp, &result, 0, req); + + if (error || !req->newptr) + return (error); + + if (result == 1) { + adapter = (struct adapter *)arg1; + em_print_hw_stats(adapter); + } + + return error; +} |
