diff options
| author | Prafulla Deuskar <pdeuskar@FreeBSD.org> | 2003-08-27 21:52:37 +0000 |
|---|---|---|
| committer | Prafulla Deuskar <pdeuskar@FreeBSD.org> | 2003-08-27 21:52:37 +0000 |
| commit | 3a47a99d78722cf543c0e90caf157f8b22d9db12 (patch) | |
| tree | ce908ffb0bfff042753843ad1101e8dac4bc56f9 /sys/dev/em/if_em.c | |
| parent | 5e1847b4d167c586e715c6cbcbcf88a0aa7b65f2 (diff) | |
Notes
Diffstat (limited to 'sys/dev/em/if_em.c')
| -rw-r--r-- | sys/dev/em/if_em.c | 187 |
1 files changed, 168 insertions, 19 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index dd895894f9fd..984f7574a4d7 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.6.6"; +char em_driver_version[] = "1.7.16"; /********************************************************************* @@ -89,6 +89,16 @@ static em_vendor_info_t em_vendor_info_array[] = { 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}, + { 0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} }; @@ -163,6 +173,9 @@ 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); +static u_int32_t em_fill_descriptors (u_int64_t address, + u_int32_t length, + PDESC_ARRAY desc_array); static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS); static void em_add_int_delay_sysctl(struct adapter *, const char *, const char *, struct em_int_delay_info *, @@ -367,7 +380,13 @@ em_attach(device_t dev) adapter->hw.fc = em_fc_full; adapter->hw.phy_init_script = 1; + adapter->hw.phy_reset_disable = FALSE; +#ifndef EM_MASTER_SLAVE + adapter->hw.master_slave = em_ms_hw_default; +#else + adapter->hw.master_slave = EM_MASTER_SLAVE; +#endif /* * Set the max frame size assuming standard ethernet * sized frames @@ -465,6 +484,15 @@ em_attach(device_t dev) } else printf("em%d: Speed:N/A Duplex:N/A\n", adapter->unit); + /* Identify 82544 on PCIX */ + em_get_bus_info(&adapter->hw); + if(adapter->hw.bus_type == em_bus_type_pcix && + adapter->hw.mac_type == em_82544) { + adapter->pcix_82544 = TRUE; + } + else { + adapter->pcix_82544 = FALSE; + } INIT_DEBUGOUT("em_attach: end"); splx(s); return(0); @@ -525,6 +553,9 @@ em_detach(device_t dev) adapter->rx_desc_base = NULL; } + /* Free the sysctl tree */ + sysctl_ctx_free(&adapter->sysctl_ctx); + /* Remove from the adapter list */ if (em_adapter_list == adapter) em_adapter_list = adapter->next; @@ -641,8 +672,11 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) case SIOCSIFFLAGS: IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)"); if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_flags & IFF_RUNNING)) + if (!(ifp->if_flags & IFF_RUNNING)) { + bcopy(IF_LLADDR(ifp), adapter->hw.mac_addr, + ETHER_ADDR_LEN); em_init(adapter); + } em_disable_promisc(adapter); em_set_promisc(adapter); @@ -685,7 +719,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } break; default: - IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%d)\n", (int)command); + IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%x)\n", (int)command); error = EINVAL; } @@ -1052,9 +1086,15 @@ static int em_encap(struct adapter *adapter, struct mbuf *m_head) { u_int32_t txd_upper; - u_int32_t txd_lower; + u_int32_t txd_lower, txd_used = 0, txd_saved = 0; int i, j, error; - + u_int64_t address; + + /* For 82544 Workaround */ + DESC_ARRAY desc_array; + u_int32_t array_elements; + u_int32_t counter; + #if __FreeBSD_version < 500000 struct ifvlan *ifv = NULL; #else @@ -1118,23 +1158,66 @@ em_encap(struct adapter *adapter, struct mbuf *m_head) #endif i = adapter->next_avail_tx_desc; + if (adapter->pcix_82544) { + txd_saved = i; + txd_used = 0; + } for (j = 0; j < q.nsegs; j++) { - tx_buffer = &adapter->tx_buffer_area[i]; - current_tx_desc = &adapter->tx_desc_base[i]; + /* If adapter is 82544 and on PCIX bus */ + if(adapter->pcix_82544) { + array_elements = 0; + address = htole64(q.segs[j].ds_addr); + /* + * Check the Address and Length combination and + * split the data accordingly + */ + array_elements = em_fill_descriptors(address, + htole32(q.segs[j].ds_len), + &desc_array); + for (counter = 0; counter < array_elements; counter++) { + if (txd_used == adapter->num_tx_desc_avail) { + adapter->next_avail_tx_desc = txd_saved; + adapter->no_tx_desc_avail2++; + bus_dmamap_destroy(adapter->txtag, q.map); + return (ENOBUFS); + } + tx_buffer = &adapter->tx_buffer_area[i]; + current_tx_desc = &adapter->tx_desc_base[i]; + current_tx_desc->buffer_addr = htole64( + desc_array.descriptor[counter].address); + current_tx_desc->lower.data = htole32( + (adapter->txd_cmd | txd_lower | + (u_int16_t)desc_array.descriptor[counter].length)); + current_tx_desc->upper.data = htole32((txd_upper)); + if (++i == adapter->num_tx_desc) + i = 0; - current_tx_desc->buffer_addr = htole64(q.segs[j].ds_addr); - current_tx_desc->lower.data = htole32( - adapter->txd_cmd | txd_lower | q.segs[j].ds_len); - current_tx_desc->upper.data = htole32(txd_upper); + tx_buffer->m_head = NULL; + txd_used++; + } + } else { + tx_buffer = &adapter->tx_buffer_area[i]; + current_tx_desc = &adapter->tx_desc_base[i]; - if (++i == adapter->num_tx_desc) - i = 0; + current_tx_desc->buffer_addr = htole64(q.segs[j].ds_addr); + current_tx_desc->lower.data = htole32( + adapter->txd_cmd | txd_lower | q.segs[j].ds_len); + current_tx_desc->upper.data = htole32(txd_upper); + + if (++i == adapter->num_tx_desc) + i = 0; - tx_buffer->m_head = NULL; + tx_buffer->m_head = NULL; + } } - adapter->num_tx_desc_avail -= q.nsegs; - adapter->next_avail_tx_desc = i; + adapter->next_avail_tx_desc = i; + if (adapter->pcix_82544) { + adapter->num_tx_desc_avail -= txd_used; + } + else { + adapter->num_tx_desc_avail -= q.nsegs; + } #if __FreeBSD_version < 500000 if (ifv != NULL) { @@ -1474,7 +1557,7 @@ em_stop(void *arg) struct adapter * adapter = arg; ifp = &adapter->interface_data.ac_if; - INIT_DEBUGOUT("em_stop: begin\n"); + INIT_DEBUGOUT("em_stop: begin"); em_disable_intr(adapter); em_reset_hw(&adapter->hw); untimeout(em_local_timer, adapter, adapter->timer_handle); @@ -1522,6 +1605,12 @@ em_identify_hardware(struct adapter * adapter) /* Identify the MAC */ if (em_set_mac_type(&adapter->hw)) printf("em%d: Unknown MAC Type\n", adapter->unit); + + if(adapter->hw.mac_type == em_82541 || + adapter->hw.mac_type == em_82541_rev_2 || + adapter->hw.mac_type == em_82547 || + adapter->hw.mac_type == em_82547_rev_2) + adapter->hw.phy_init_script = TRUE; return; } @@ -1629,6 +1718,7 @@ em_free_pci_resources(struct adapter * adapter) static int em_hardware_init(struct adapter * adapter) { + INIT_DEBUGOUT("em_hardware_init: begin"); /* Issue a global reset */ em_reset_hw(&adapter->hw); @@ -1984,6 +2074,7 @@ em_initialize_transmit_unit(struct adapter * adapter) u_int32_t reg_tipg = 0; u_int64_t bus_addr; + INIT_DEBUGOUT("em_initialize_transmit_unit: begin"); /* Setup the Base and Length of the Tx Descriptor Ring */ bus_addr = adapter->txdma.dma_paddr; E1000_WRITE_REG(&adapter->hw, TDBAL, (u_int32_t)bus_addr); @@ -2399,6 +2490,7 @@ em_initialize_receive_unit(struct adapter * adapter) struct ifnet *ifp; u_int64_t bus_addr; + INIT_DEBUGOUT("em_initialize_receive_unit: begin"); ifp = &adapter->interface_data.ac_if; /* Make sure receives are disabled while setting up the descriptor ring */ @@ -2469,6 +2561,7 @@ em_initialize_receive_unit(struct adapter * adapter) /* Enable Receives */ E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl); + em_set_promisc(adapter); return; } @@ -2805,6 +2898,59 @@ em_io_write(struct em_hw *hw, uint32_t port, uint32_t value) return; } +/********************************************************************* +* 82544 Coexistence issue workaround. +* There are 2 issues. +* 1. Transmit Hang issue. +* To detect this issue, following equation can be used... +* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. +* If SUM[3:0] is in between 1 to 4, we will have this issue. +* +* 2. DAC issue. +* To detect this issue, following equation can be used... +* SIZE[3:0] + ADDR[2:0] = SUM[3:0]. +* If SUM[3:0] is in between 9 to c, we will have this issue. +* +* +* WORKAROUND: +* Make sure we do not have ending address as 1,2,3,4(Hang) or 9,a,b,c (DAC) +* +*** *********************************************************************/ +static u_int32_t +em_fill_descriptors (u_int64_t address, + u_int32_t length, + PDESC_ARRAY desc_array) +{ + /* Since issue is sensitive to length and address.*/ + /* Let us first check the address...*/ + u_int32_t safe_terminator; + if (length <= 4) { + desc_array->descriptor[0].address = address; + desc_array->descriptor[0].length = length; + desc_array->elements = 1; + return desc_array->elements; + } + safe_terminator = (u_int32_t)((((u_int32_t)address & 0x7) + (length & 0xF)) & 0xF); + /* if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then return */ + if (safe_terminator == 0 || + (safe_terminator > 4 && + safe_terminator < 9) || + (safe_terminator > 0xC && + safe_terminator <= 0xF)) { + desc_array->descriptor[0].address = address; + desc_array->descriptor[0].length = length; + desc_array->elements = 1; + return desc_array->elements; + } + + desc_array->descriptor[0].address = address; + desc_array->descriptor[0].length = length - 4; + desc_array->descriptor[1].address = address + (length - 4); + desc_array->descriptor[1].length = 4; + desc_array->elements = 2; + return desc_array->elements; +} + /********************************************************************** * * Update the board statistics counters. @@ -2815,8 +2961,12 @@ em_update_stats_counters(struct adapter *adapter) { struct ifnet *ifp; + if(adapter->hw.media_type == em_media_type_copper || + (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) { + adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, SYMERRS); + adapter->stats.sec += E1000_READ_REG(&adapter->hw, SEC); + } adapter->stats.crcerrs += E1000_READ_REG(&adapter->hw, CRCERRS); - adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, SYMERRS); adapter->stats.mpc += E1000_READ_REG(&adapter->hw, MPC); adapter->stats.scc += E1000_READ_REG(&adapter->hw, SCC); adapter->stats.ecol += E1000_READ_REG(&adapter->hw, ECOL); @@ -2825,7 +2975,6 @@ em_update_stats_counters(struct adapter *adapter) adapter->stats.latecol += E1000_READ_REG(&adapter->hw, LATECOL); adapter->stats.colc += E1000_READ_REG(&adapter->hw, COLC); adapter->stats.dc += E1000_READ_REG(&adapter->hw, DC); - adapter->stats.sec += E1000_READ_REG(&adapter->hw, SEC); adapter->stats.rlec += E1000_READ_REG(&adapter->hw, RLEC); adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, XONRXC); adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, XONTXC); |
