Only reset the phy when it is absolutely required.
This should fix the issues with long *init* times when you do ifconfig em0 alias. MFC after: 3 days
This commit is contained in:
parent
a9c2bfa8e9
commit
b81490427d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=125673
@ -51,7 +51,7 @@ struct adapter *em_adapter_list = NULL;
|
||||
* Driver version
|
||||
*********************************************************************/
|
||||
|
||||
char em_driver_version[] = "1.7.19";
|
||||
char em_driver_version[] = "1.7.25";
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
@ -539,7 +539,8 @@ em_detach(device_t dev)
|
||||
ether_ifdetach(&adapter->interface_data.ac_if);
|
||||
#endif
|
||||
em_free_pci_resources(adapter);
|
||||
|
||||
bus_generic_detach(dev);
|
||||
|
||||
/* Free Transmit Descriptor ring */
|
||||
if (adapter->tx_desc_base) {
|
||||
em_dma_free(adapter, &adapter->txdma);
|
||||
@ -764,7 +765,8 @@ em_watchdog(struct ifnet *ifp)
|
||||
return;
|
||||
}
|
||||
|
||||
printf("em%d: watchdog timeout -- resetting\n", adapter->unit);
|
||||
if (em_check_for_link(&adapter->hw))
|
||||
printf("em%d: watchdog timeout -- resetting\n", adapter->unit);
|
||||
|
||||
ifp->if_flags &= ~IFF_RUNNING;
|
||||
|
||||
@ -857,6 +859,9 @@ em_init_locked(struct adapter * adapter)
|
||||
#endif /* DEVICE_POLLING */
|
||||
em_enable_intr(adapter);
|
||||
|
||||
/* Don't reset the phy next time init gets called */
|
||||
adapter->hw.phy_reset_disable = TRUE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1098,6 +1103,11 @@ em_media_change(struct ifnet *ifp)
|
||||
printf("em%d: Unsupported media type\n", adapter->unit);
|
||||
}
|
||||
|
||||
/* As the speed/duplex settings my have changed we need to
|
||||
* reset the PHY.
|
||||
*/
|
||||
adapter->hw.phy_reset_disable = FALSE;
|
||||
|
||||
em_init(adapter);
|
||||
|
||||
return(0);
|
||||
@ -1516,7 +1526,7 @@ em_set_multi(struct adapter * adapter)
|
||||
reg_rctl |= E1000_RCTL_MPE;
|
||||
E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
|
||||
} else
|
||||
em_mc_addr_list_update(&adapter->hw, mta, mcnt, 0);
|
||||
em_mc_addr_list_update(&adapter->hw, mta, mcnt, 0, 1);
|
||||
|
||||
if (adapter->hw.mac_type == em_82542_rev2_0) {
|
||||
reg_rctl = E1000_READ_REG(&adapter->hw, RCTL);
|
||||
@ -2952,13 +2962,13 @@ em_pci_clear_mwi(struct em_hw *hw)
|
||||
}
|
||||
|
||||
uint32_t
|
||||
em_io_read(struct em_hw *hw, uint32_t port)
|
||||
em_io_read(struct em_hw *hw, unsigned long port)
|
||||
{
|
||||
return(inl(port));
|
||||
}
|
||||
|
||||
void
|
||||
em_io_write(struct em_hw *hw, uint32_t port, uint32_t value)
|
||||
em_io_write(struct em_hw *hw, unsigned long port, uint32_t value)
|
||||
{
|
||||
outl(port, value);
|
||||
return;
|
||||
@ -3136,6 +3146,15 @@ static void
|
||||
em_print_debug_info(struct adapter *adapter)
|
||||
{
|
||||
int unit = adapter->unit;
|
||||
uint8_t *hw_addr = adapter->hw.hw_addr;
|
||||
|
||||
printf("em%d: Adapter hardware address = %p \n", unit, hw_addr);
|
||||
printf("em%d:tx_int_delay = %d, tx_abs_int_delay = %d\n", unit,
|
||||
E1000_READ_REG(&adapter->hw, TIDV),
|
||||
E1000_READ_REG(&adapter->hw, TADV));
|
||||
printf("em%d:rx_int_delay = %d, rx_abs_int_delay = %d\n", unit,
|
||||
E1000_READ_REG(&adapter->hw, RDTR),
|
||||
E1000_READ_REG(&adapter->hw, RADV));
|
||||
|
||||
#ifdef DBG_STATS
|
||||
printf("em%d: Packets not Avail = %ld\n", unit,
|
||||
|
@ -104,8 +104,14 @@ em_set_phy_type(struct em_hw *hw)
|
||||
hw->phy_type = em_phy_m88;
|
||||
break;
|
||||
case IGP01E1000_I_PHY_ID:
|
||||
hw->phy_type = em_phy_igp;
|
||||
break;
|
||||
if(hw->mac_type == em_82541 ||
|
||||
hw->mac_type == em_82541_rev_2 ||
|
||||
hw->mac_type == em_82547 ||
|
||||
hw->mac_type == em_82547_rev_2) {
|
||||
hw->phy_type = em_phy_igp;
|
||||
break;
|
||||
}
|
||||
/* Fall Through */
|
||||
default:
|
||||
/* Should never have loaded on this device */
|
||||
hw->phy_type = em_phy_undefined;
|
||||
@ -156,7 +162,6 @@ em_phy_init_script(struct em_hw *hw)
|
||||
|
||||
em_write_phy_reg(hw, 0x0000, 0x3300);
|
||||
|
||||
|
||||
if(hw->mac_type == em_82547) {
|
||||
uint16_t fused, fine, coarse;
|
||||
|
||||
@ -1493,8 +1498,8 @@ em_phy_force_speed_duplex(struct em_hw *hw)
|
||||
if(mii_status_reg & MII_SR_LINK_STATUS) break;
|
||||
msec_delay(100);
|
||||
}
|
||||
if(i == 0) { /* We didn't get link */
|
||||
/* Reset the DSP and wait again for link. */
|
||||
if((i == 0) && (hw->phy_type == em_phy_m88)) {
|
||||
/* We didn't get link. Reset the DSP and wait again for link. */
|
||||
if((ret_val = em_phy_reset_dsp(hw))) {
|
||||
DEBUGOUT("Error Resetting PHY DSP\n");
|
||||
return ret_val;
|
||||
@ -1541,6 +1546,25 @@ em_phy_force_speed_duplex(struct em_hw *hw)
|
||||
phy_data)))
|
||||
return ret_val;
|
||||
|
||||
/* Polarity reversal workaround for forced 10F/10H links. */
|
||||
if(hw->mac_type <= em_82544 &&
|
||||
(hw->forced_speed_duplex == em_10_full ||
|
||||
hw->forced_speed_duplex == em_10_half)) {
|
||||
if((ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
|
||||
0x0019)))
|
||||
return ret_val;
|
||||
if((ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
|
||||
0x8F0F)))
|
||||
return ret_val;
|
||||
/* IEEE requirement is 150ms */
|
||||
msec_delay(200);
|
||||
if((ret_val = em_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
|
||||
0x0019)))
|
||||
return ret_val;
|
||||
if((ret_val = em_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
|
||||
0x8F00)))
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
@ -1924,7 +1948,6 @@ em_check_for_link(struct em_hw *hw)
|
||||
uint32_t signal = 0;
|
||||
int32_t ret_val;
|
||||
uint16_t phy_data;
|
||||
uint16_t lp_capability;
|
||||
|
||||
DEBUGFUNC("em_check_for_link");
|
||||
|
||||
@ -2004,24 +2027,17 @@ em_check_for_link(struct em_hw *hw)
|
||||
|
||||
/* At this point we know that we are on copper and we have
|
||||
* auto-negotiated link. These are conditions for checking the link
|
||||
* parter capability register. We use the link partner capability to
|
||||
* determine if TBI Compatibility needs to be turned on or off. If
|
||||
* the link partner advertises any speed in addition to Gigabit, then
|
||||
* we assume that they are GMII-based, and TBI compatibility is not
|
||||
* needed. If no other speeds are advertised, we assume the link
|
||||
* partner is TBI-based, and we turn on TBI Compatibility.
|
||||
* partner capability register. We use the link speed to determine if
|
||||
* TBI compatibility needs to be turned on or off. If the link is not
|
||||
* at gigabit speed, then TBI compatibility is not needed. If we are
|
||||
* at gigabit speed, we turn on TBI compatibility.
|
||||
*/
|
||||
if(hw->tbi_compatibility_en) {
|
||||
if((ret_val = em_read_phy_reg(hw, PHY_LP_ABILITY,
|
||||
&lp_capability)))
|
||||
return ret_val;
|
||||
if(lp_capability & (NWAY_LPAR_10T_HD_CAPS |
|
||||
NWAY_LPAR_10T_FD_CAPS |
|
||||
NWAY_LPAR_100TX_HD_CAPS |
|
||||
NWAY_LPAR_100TX_FD_CAPS |
|
||||
NWAY_LPAR_100T4_CAPS)) {
|
||||
/* If our link partner advertises anything in addition to
|
||||
* gigabit, we do not need to enable TBI compatibility.
|
||||
if(hw->tbi_compatibility_en) {
|
||||
uint16_t speed, duplex;
|
||||
em_get_speed_and_duplex(hw, &speed, &duplex);
|
||||
if(speed != SPEED_1000) {
|
||||
/* If link speed is not set to gigabit speed, we do not need
|
||||
* to enable TBI compatibility.
|
||||
*/
|
||||
if(hw->tbi_compatibility_on) {
|
||||
/* If we previously were in the mode, turn it off. */
|
||||
@ -2089,6 +2105,29 @@ em_check_for_link(struct em_hw *hw)
|
||||
DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
|
||||
E1000_WRITE_REG(hw, TXCW, hw->txcw);
|
||||
E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
|
||||
|
||||
hw->serdes_link_down = FALSE;
|
||||
}
|
||||
/* If we force link for non-auto-negotiation switch, check link status
|
||||
* based on MAC synchronization for internal serdes media type.
|
||||
*/
|
||||
else if((hw->media_type == em_media_type_internal_serdes) &&
|
||||
!(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
|
||||
/* SYNCH bit and IV bit are sticky. */
|
||||
usec_delay(10);
|
||||
if(E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
|
||||
if(!(rxcw & E1000_RXCW_IV)) {
|
||||
hw->serdes_link_down = FALSE;
|
||||
DEBUGOUT("SERDES: Link is up.\n");
|
||||
}
|
||||
} else {
|
||||
hw->serdes_link_down = TRUE;
|
||||
DEBUGOUT("SERDES: Link is down.\n");
|
||||
}
|
||||
}
|
||||
if((hw->media_type == em_media_type_internal_serdes) &&
|
||||
(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
|
||||
hw->serdes_link_down = !(E1000_STATUS_LU & E1000_READ_REG(hw, STATUS));
|
||||
}
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
@ -2489,8 +2528,8 @@ em_write_phy_reg_ex(struct em_hw *hw,
|
||||
E1000_WRITE_REG(hw, MDIC, mdic);
|
||||
|
||||
/* Poll the ready bit to see if the MDI read completed */
|
||||
for(i = 0; i < 64; i++) {
|
||||
usec_delay(50);
|
||||
for(i = 0; i < 640; i++) {
|
||||
usec_delay(5);
|
||||
mdic = E1000_READ_REG(hw, MDIC);
|
||||
if(mdic & E1000_MDIC_READY) break;
|
||||
}
|
||||
@ -3506,10 +3545,12 @@ em_write_eeprom(struct em_hw *hw,
|
||||
if (em_acquire_eeprom(hw) != E1000_SUCCESS)
|
||||
return -E1000_ERR_EEPROM;
|
||||
|
||||
if(eeprom->type == em_eeprom_microwire)
|
||||
if(eeprom->type == em_eeprom_microwire) {
|
||||
status = em_write_eeprom_microwire(hw, offset, words, data);
|
||||
else
|
||||
} else {
|
||||
status = em_write_eeprom_spi(hw, offset, words, data);
|
||||
msec_delay(10);
|
||||
}
|
||||
|
||||
/* Done with writing */
|
||||
em_release_eeprom(hw);
|
||||
@ -3727,12 +3768,9 @@ em_read_mac_addr(struct em_hw * hw)
|
||||
hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
|
||||
}
|
||||
if(((hw->mac_type == em_82546) || (hw->mac_type == em_82546_rev_3)) &&
|
||||
(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
|
||||
if(hw->perm_mac_addr[5] & 0x01)
|
||||
hw->perm_mac_addr[5] &= ~(0x01);
|
||||
else
|
||||
hw->perm_mac_addr[5] |= 0x01;
|
||||
}
|
||||
(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
|
||||
hw->perm_mac_addr[5] ^= 0x01;
|
||||
|
||||
for(i = 0; i < NODE_ADDRESS_SIZE; i++)
|
||||
hw->mac_addr[i] = hw->perm_mac_addr[i];
|
||||
return E1000_SUCCESS;
|
||||
@ -3751,22 +3789,13 @@ void
|
||||
em_init_rx_addrs(struct em_hw *hw)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t addr_low;
|
||||
uint32_t addr_high;
|
||||
|
||||
DEBUGFUNC("em_init_rx_addrs");
|
||||
|
||||
/* Setup the receive address. */
|
||||
DEBUGOUT("Programming MAC Address into RAR[0]\n");
|
||||
addr_low = (hw->mac_addr[0] |
|
||||
(hw->mac_addr[1] << 8) |
|
||||
(hw->mac_addr[2] << 16) | (hw->mac_addr[3] << 24));
|
||||
|
||||
addr_high = (hw->mac_addr[4] |
|
||||
(hw->mac_addr[5] << 8) | E1000_RAH_AV);
|
||||
|
||||
E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low);
|
||||
E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high);
|
||||
em_rar_set(hw, hw->mac_addr, 0);
|
||||
|
||||
/* Zero out the other 15 receive addresses. */
|
||||
DEBUGOUT("Clearing RAR[1-15]\n");
|
||||
@ -3783,6 +3812,7 @@ em_init_rx_addrs(struct em_hw *hw)
|
||||
* mc_addr_list - the list of new multicast addresses
|
||||
* mc_addr_count - number of addresses
|
||||
* pad - number of bytes between addresses in the list
|
||||
* rar_used_count - offset where to start adding mc addresses into the RAR's
|
||||
*
|
||||
* The given list replaces any existing list. Clears the last 15 receive
|
||||
* address registers and the multicast table. Uses receive address registers
|
||||
@ -3793,11 +3823,11 @@ void
|
||||
em_mc_addr_list_update(struct em_hw *hw,
|
||||
uint8_t *mc_addr_list,
|
||||
uint32_t mc_addr_count,
|
||||
uint32_t pad)
|
||||
uint32_t pad,
|
||||
uint32_t rar_used_count)
|
||||
{
|
||||
uint32_t hash_value;
|
||||
uint32_t i;
|
||||
uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
|
||||
|
||||
DEBUGFUNC("em_mc_addr_list_update");
|
||||
|
||||
@ -4531,8 +4561,8 @@ uint32_t
|
||||
em_read_reg_io(struct em_hw *hw,
|
||||
uint32_t offset)
|
||||
{
|
||||
uint32_t io_addr = hw->io_base;
|
||||
uint32_t io_data = hw->io_base + 4;
|
||||
unsigned long io_addr = hw->io_base;
|
||||
unsigned long io_data = hw->io_base + 4;
|
||||
|
||||
em_io_write(hw, io_addr, offset);
|
||||
return em_io_read(hw, io_data);
|
||||
@ -4551,8 +4581,8 @@ em_write_reg_io(struct em_hw *hw,
|
||||
uint32_t offset,
|
||||
uint32_t value)
|
||||
{
|
||||
uint32_t io_addr = hw->io_base;
|
||||
uint32_t io_data = hw->io_base + 4;
|
||||
unsigned long io_addr = hw->io_base;
|
||||
unsigned long io_data = hw->io_base + 4;
|
||||
|
||||
em_io_write(hw, io_addr, offset);
|
||||
em_io_write(hw, io_data, value);
|
||||
|
@ -41,6 +41,9 @@
|
||||
|
||||
#include <dev/em/if_em_osdep.h>
|
||||
|
||||
#ifndef NO_VERSION_CONTROL
|
||||
#ident "@(#)$RCSfile: if_em_hw.h,v $$Revision: 1.37 $$Date: 2003/12/20 00:14:51 $"
|
||||
#endif
|
||||
|
||||
/* Forward declarations of structures used by the shared code */
|
||||
struct em_hw;
|
||||
@ -297,7 +300,7 @@ int32_t em_read_mac_addr(struct em_hw * hw);
|
||||
|
||||
/* Filters (multicast, vlan, receive) */
|
||||
void em_init_rx_addrs(struct em_hw *hw);
|
||||
void em_mc_addr_list_update(struct em_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad);
|
||||
void em_mc_addr_list_update(struct em_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
|
||||
uint32_t em_hash_mc_addr(struct em_hw *hw, uint8_t * mc_addr);
|
||||
void em_mta_set(struct em_hw *hw, uint32_t hash_value);
|
||||
void em_rar_set(struct em_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
|
||||
@ -323,9 +326,9 @@ void em_pci_clear_mwi(struct em_hw *hw);
|
||||
void em_read_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t * value);
|
||||
void em_write_pci_cfg(struct em_hw *hw, uint32_t reg, uint16_t * value);
|
||||
/* Port I/O is only supported on 82544 and newer */
|
||||
uint32_t em_io_read(struct em_hw *hw, uint32_t port);
|
||||
uint32_t em_io_read(struct em_hw *hw, unsigned long port);
|
||||
uint32_t em_read_reg_io(struct em_hw *hw, uint32_t offset);
|
||||
void em_io_write(struct em_hw *hw, uint32_t port, uint32_t value);
|
||||
void em_io_write(struct em_hw *hw, unsigned long 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);
|
||||
@ -984,7 +987,7 @@ struct em_hw {
|
||||
em_ms_type master_slave;
|
||||
em_ms_type original_master_slave;
|
||||
em_ffe_config ffe_config_state;
|
||||
uint32_t io_base;
|
||||
unsigned long io_base;
|
||||
uint32_t phy_id;
|
||||
uint32_t phy_revision;
|
||||
uint32_t phy_addr;
|
||||
@ -1027,6 +1030,7 @@ struct em_hw {
|
||||
boolean_t speed_downgraded;
|
||||
em_dsp_config dsp_config_state;
|
||||
boolean_t get_link_status;
|
||||
boolean_t serdes_link_down;
|
||||
boolean_t tbi_compatibility_en;
|
||||
boolean_t tbi_compatibility_on;
|
||||
boolean_t phy_reset_disable;
|
||||
@ -1316,6 +1320,7 @@ struct em_hw {
|
||||
#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */
|
||||
#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
|
||||
#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
|
||||
#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
|
||||
|
||||
/* Receive Descriptor */
|
||||
#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */
|
||||
|
Loading…
Reference in New Issue
Block a user