diff options
author | pdeuskar <pdeuskar@FreeBSD.org> | 2003-11-14 18:02:25 +0000 |
---|---|---|
committer | pdeuskar <pdeuskar@FreeBSD.org> | 2003-11-14 18:02:25 +0000 |
commit | 4d342b5b2bb7f2ae7f947bed3b5d8f0869908c70 (patch) | |
tree | ffa5bce04b91c721e30ad7234bf9284a144eacb3 /sys/dev/em | |
parent | 48c9756047d8f925c4839f0cefa81d1bbfb25264 (diff) | |
download | FreeBSD-src-4d342b5b2bb7f2ae7f947bed3b5d8f0869908c70.zip FreeBSD-src-4d342b5b2bb7f2ae7f947bed3b5d8f0869908c70.tar.gz |
- Code cleanup
- In the receive routine handle the case where last descriptor could have
less than 4 bytes of data.
- Handle race between detach/ioctl routine.
MFC after: 3 days
Diffstat (limited to 'sys/dev/em')
-rw-r--r-- | sys/dev/em/if_em.c | 36 | ||||
-rw-r--r-- | sys/dev/em/if_em.h | 1 | ||||
-rw-r--r-- | sys/dev/em/if_em_hw.c | 106 | ||||
-rw-r--r-- | sys/dev/em/if_em_hw.h | 10 |
4 files changed, 48 insertions, 105 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index 295fdb6..4572e33 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.7.16"; +char em_driver_version[] = "1.7.19"; /********************************************************************* @@ -529,6 +529,7 @@ em_detach(device_t dev) INIT_DEBUGOUT("em_detach: begin"); EM_LOCK(adapter); + adapter->in_detach = 1; em_stop(adapter); em_phy_hw_reset(&adapter->hw); EM_UNLOCK(adapter); @@ -662,6 +663,8 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) struct ifreq *ifr = (struct ifreq *) data; struct adapter * adapter = ifp->if_softc; + if (adapter->in_detach) return(error); + switch (command) { case SIOCSIFADDR: case SIOCGIFADDR: @@ -686,8 +689,6 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) EM_LOCK(adapter); if (ifp->if_flags & IFF_UP) { if (!(ifp->if_flags & IFF_RUNNING)) { - bcopy(IF_LLADDR(ifp), adapter->hw.mac_addr, - ETHER_ADDR_LEN); em_init_locked(adapter); } @@ -796,6 +797,10 @@ em_init_locked(struct adapter * adapter) em_stop(adapter); + /* Get the latest mac address, User can use a LAA */ + bcopy(adapter->interface_data.ac_enaddr, adapter->hw.mac_addr, + ETHER_ADDR_LEN); + /* Initialize the hardware */ if (em_hardware_init(adapter)) { printf("em%d: Unable to initialize the hardware\n", @@ -825,6 +830,9 @@ em_init_locked(struct adapter * adapter) return; } em_initialize_receive_unit(adapter); + + /* Don't loose promiscuous settings */ + em_set_promisc(adapter); ifp = &adapter->interface_data.ac_if; ifp->if_flags |= IFF_RUNNING; @@ -2601,7 +2609,6 @@ em_initialize_receive_unit(struct adapter * adapter) /* Enable Receives */ E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl); - em_set_promisc(adapter); return; } @@ -2661,7 +2668,7 @@ em_process_receive_interrupts(struct adapter * adapter, int count) #endif u_int8_t accept_frame = 0; u_int8_t eop = 0; - u_int16_t len, desc_len; + u_int16_t len, desc_len, prev_len_adj; int i; /* Pointer to the receive descriptor being examined. */ @@ -2687,11 +2694,18 @@ em_process_receive_interrupts(struct adapter * adapter, int count) BUS_DMASYNC_POSTREAD); accept_frame = 1; + prev_len_adj = 0; desc_len = le16toh(current_desc->length); if (current_desc->status & E1000_RXD_STAT_EOP) { count--; eop = 1; - len = desc_len - ETHER_CRC_LEN; + if (desc_len < ETHER_CRC_LEN) { + len = 0; + prev_len_adj = ETHER_CRC_LEN - desc_len; + } + else { + len = desc_len - ETHER_CRC_LEN; + } } else { eop = 0; len = desc_len; @@ -2713,7 +2727,7 @@ em_process_receive_interrupts(struct adapter * adapter, int count) &adapter->stats, pkt_len, adapter->hw.mac_addr); - len--; + if (len > 0) len--; } else { accept_frame = 0; @@ -2742,6 +2756,14 @@ em_process_receive_interrupts(struct adapter * adapter, int count) } else { /* Chain mbuf's together */ mp->m_flags &= ~M_PKTHDR; + /* + * Adjust length of previous mbuf in chain if we + * received less than 4 bytes in the last descriptor. + */ + if (prev_len_adj > 0) { + adapter->lmp->m_len -= prev_len_adj; + adapter->fmp->m_pkthdr.len -= prev_len_adj; + } adapter->lmp->m_next = mp; adapter->lmp = adapter->lmp->m_next; adapter->fmp->m_pkthdr.len += len; diff --git a/sys/dev/em/if_em.h b/sys/dev/em/if_em.h index 8818165..f3128f0 100644 --- a/sys/dev/em/if_em.h +++ b/sys/dev/em/if_em.h @@ -416,6 +416,7 @@ struct adapter { /* For 82544 PCIX Workaround */ boolean_t pcix_82544; + boolean_t in_detach; #ifdef DBG_STATS unsigned long no_pkts_avail; diff --git a/sys/dev/em/if_em_hw.c b/sys/dev/em/if_em_hw.c index 2bee94f..fab8004 100644 --- a/sys/dev/em/if_em_hw.c +++ b/sys/dev/em/if_em_hw.c @@ -844,18 +844,16 @@ em_setup_fiber_serdes_link(struct em_hw *hw) if(i == (LINK_UP_TIMEOUT / 10)) { DEBUGOUT("Never got a valid link from auto-neg!!!\n"); hw->autoneg_failed = 1; - if(hw->media_type == em_media_type_fiber) { - /* AutoNeg failed to achieve a link, so we'll call - * em_check_for_link. This routine will force the link up if - * we detect a signal. This will allow us to communicate with - * non-autonegotiating link partners. - */ - if((ret_val = em_check_for_link(hw))) { - DEBUGOUT("Error while checking for link\n"); - return ret_val; - } - hw->autoneg_failed = 0; + /* AutoNeg failed to achieve a link, so we'll call + * em_check_for_link. This routine will force the link up if + * we detect a signal. This will allow us to communicate with + * non-autonegotiating link partners. + */ + if((ret_val = em_check_for_link(hw))) { + DEBUGOUT("Error while checking for link\n"); + return ret_val; } + hw->autoneg_failed = 0; } else { hw->autoneg_failed = 0; DEBUGOUT("Valid Link Found\n"); @@ -1873,11 +1871,12 @@ em_config_fc_after_link_up(struct em_hw *hw) * be asked to delay transmission of packets than asking * our link partner to pause transmission of frames. */ - else if(hw->original_fc == em_fc_none || - hw->original_fc == em_fc_tx_pause) { + else if((hw->original_fc == em_fc_none || + hw->original_fc == em_fc_tx_pause) || + hw->fc_strict_ieee) { hw->fc = em_fc_none; DEBUGOUT("Flow Control = NONE.\r\n"); - } else if(!hw->fc_strict_ieee) { + } else { hw->fc = em_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); } @@ -2053,9 +2052,10 @@ em_check_for_link(struct em_hw *hw) * auto-negotiation time to complete, in case the cable was just plugged * in. The autoneg_failed flag does this. */ - else if((hw->media_type == em_media_type_fiber) && + else if((((hw->media_type == em_media_type_fiber) && + ((ctrl & E1000_CTRL_SWDPIN1) == signal)) || + (hw->media_type == em_media_type_internal_serdes)) && (!(status & E1000_STATUS_LU)) && - ((ctrl & E1000_CTRL_SWDPIN1) == signal) && (!(rxcw & E1000_RXCW_C))) { if(hw->autoneg_failed == 0) { hw->autoneg_failed = 1; @@ -2082,7 +2082,8 @@ em_check_for_link(struct em_hw *hw) * Device Control register in an attempt to auto-negotiate with our link * partner. */ - else if((hw->media_type == em_media_type_fiber) && + else if(((hw->media_type == em_media_type_fiber) || + (hw->media_type == em_media_type_internal_serdes)) && (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n"); @@ -4901,77 +4902,6 @@ em_config_dsp_after_link_change(struct em_hw *hw, return E1000_SUCCESS; } -/*************************************************************************** - * - * Workaround for the 82547 long TTL on noisy 100HD hubs. - * - * This function, specific to 82547 hardware only, needs to be called every - * second. It checks if a parallel detect fault has occurred. If a fault - * occurred, disable/enable the DSP reset mechanism up to 5 times (once per - * second). If link is established, stop the workaround and ensure the DSP - * reset is enabled. - * - * hw: Struct containing variables accessed by shared code - * - * returns: - E1000_ERR_PHY if fail to read/write the PHY - * E1000_SUCCESS in any other case - * - ****************************************************************************/ -int32_t -em_igp_ttl_workaround(struct em_hw *hw) -{ - int32_t ret_val; - uint16_t phy_data = 0; - uint16_t dsp_value = DSP_RESET_ENABLE; - - if(((hw->mac_type != em_82541) && (hw->mac_type != em_82547)) || - (!hw->ttl_wa_activation)) { - return E1000_SUCCESS; - } - - /* Check for link first */ - if((ret_val = em_read_phy_reg(hw, PHY_STATUS, &phy_data))) - return ret_val; - - if(phy_data & MII_SR_LINK_STATUS) { - /* If link is established during the workaround, the DSP mechanism must - * be enabled. */ - if(hw->dsp_reset_counter) { - hw->dsp_reset_counter = 0; - dsp_value = DSP_RESET_ENABLE; - } else - return E1000_SUCCESS; - } else { - if(hw->dsp_reset_counter == 0) { - /* Workaround not activated, check if it needs activation */ - if((ret_val = em_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data))) - return ret_val; - /* Activate the workaround if there was a parallel detect fault */ - if(phy_data & NWAY_ER_PAR_DETECT_FAULT) - hw->dsp_reset_counter++; - else - return E1000_SUCCESS; - } - - if(hw->dsp_reset_counter) { - /* After 5 times, stop the workaround */ - if(hw->dsp_reset_counter > E1000_MAX_DSP_RESETS) { - hw->dsp_reset_counter = 0; - dsp_value = DSP_RESET_ENABLE; - } else { - dsp_value = (hw->dsp_reset_counter & 1) ? DSP_RESET_DISABLE : - DSP_RESET_ENABLE; - hw->dsp_reset_counter++; - } - } - } - - if((ret_val = em_write_phy_reg(hw, IGP01E1000_PHY_DSP_RESET, dsp_value))) - return ret_val; - - return E1000_SUCCESS; -} - /***************************************************************************** * * This function sets the lplu state according to the active flag. When diff --git a/sys/dev/em/if_em_hw.h b/sys/dev/em/if_em_hw.h index d187e7b..d745012 100644 --- a/sys/dev/em/if_em_hw.h +++ b/sys/dev/em/if_em_hw.h @@ -329,7 +329,6 @@ void em_io_write(struct em_hw *hw, uint32_t port, uint32_t value); void em_write_reg_io(struct em_hw *hw, uint32_t offset, uint32_t value); int32_t em_config_dsp_after_link_change(struct em_hw *hw, boolean_t link_up); int32_t em_set_d3_lplu_state(struct em_hw *hw, boolean_t active); -int32_t em_igp_ttl_workaround(struct em_hw *hw); #define E1000_READ_REG_IO(a, reg) \ em_read_reg_io((a), E1000_##reg) @@ -1002,7 +1001,6 @@ struct em_hw { uint32_t ledctl_mode1; uint32_t ledctl_mode2; uint16_t phy_spd_default; - uint16_t dsp_reset_counter; uint16_t autoneg_advertised; uint16_t pci_cmd_word; uint16_t fc_high_water; @@ -1027,7 +1025,6 @@ struct em_hw { uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; boolean_t disable_polarity_correction; boolean_t speed_downgraded; - boolean_t ttl_wa_activation; em_dsp_config dsp_config_state; boolean_t get_link_status; boolean_t tbi_compatibility_en; @@ -2117,11 +2114,4 @@ struct em_hw { #define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds*/ #define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds*/ -#define TANAX_TTL_WA_RESET(hw) { \ - if((hw)->dsp_reset_counter) { \ - em_write_phy_reg((hw), IGP01E1000_PHY_DSP_RESET, 0x0000); \ - (hw)->dsp_reset_counter = 0; \ - } \ -} - #endif /* _EM_HW_H_ */ |