mirror of
https://github.com/opnsense/src.git
synced 2026-04-22 06:39:32 -04:00
- 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
This commit is contained in:
parent
d1f42ac2ee
commit
3c2ef4e7e2
4 changed files with 48 additions and 105 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue