summaryrefslogtreecommitdiffstats
path: root/sys/dev/em
diff options
context:
space:
mode:
authorpdeuskar <pdeuskar@FreeBSD.org>2003-11-14 18:02:25 +0000
committerpdeuskar <pdeuskar@FreeBSD.org>2003-11-14 18:02:25 +0000
commit4d342b5b2bb7f2ae7f947bed3b5d8f0869908c70 (patch)
treeffa5bce04b91c721e30ad7234bf9284a144eacb3 /sys/dev/em
parent48c9756047d8f925c4839f0cefa81d1bbfb25264 (diff)
downloadFreeBSD-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.c36
-rw-r--r--sys/dev/em/if_em.h1
-rw-r--r--sys/dev/em/if_em_hw.c106
-rw-r--r--sys/dev/em/if_em_hw.h10
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_ */
OpenPOWER on IntegriCloud