static void
e1000_watchdog(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
struct net_device *netdev = adapter->;netdev;
struct e1000_desc_ring *txdr = &adapter->;tx_ring;
unsigned int i;
uint32_t link;
e1000_check_for_link(&adapter->;hw);
if((adapter->;hw.media_type == e1000_media_type_internal_serdes) &&
!(E1000_READ_REG(&adapter->;hw, TXCW) & E1000_TXCW_ANE))
link = !adapter->;hw.serdes_link_down;
else
link = E1000_READ_REG(&adapter->;hw, STATUS) & E1000_STATUS_LU;
if(link) {
if(!netif_carrier_ok(netdev)) {
e1000_get_speed_and_duplex(&adapter->;hw,
&adapter->;link_speed,
&adapter->;link_duplex);
DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s\n",
adapter->;link_speed,
adapter->;link_duplex == FULL_DUPLEX ?
"Full Duplex" : "Half Duplex");
netif_carrier_on(netdev);
netif_wake_queue(netdev);
mod_timer(&adapter->;phy_info_timer, jiffies + 2 * HZ);
adapter->;smartspeed = 0;
}
} else {
if(netif_carrier_ok(netdev)) {
adapter->;link_speed = 0;
adapter->;link_duplex = 0;
DPRINTK(LINK, INFO, "NIC Link is Down\n");
netif_carrier_off(netdev);
netif_stop_queue(netdev);
mod_timer(&adapter->;phy_info_timer, jiffies + 2 * HZ);
}
e1000_smartspeed(adapter);
}
e1000_update_stats(adapter);
adapter->;hw.tx_packet_delta = adapter->;stats.tpt - adapter->;tpt_old;
adapter->;tpt_old = adapter->;stats.tpt;
adapter->;hw.collision_delta = adapter->;stats.colc - adapter->;colc_old;
adapter->;colc_old = adapter->;stats.colc;
adapter->;gorcl = adapter->;stats.gorcl - adapter->;gorcl_old;
adapter->;gorcl_old = adapter->;stats.gorcl;
adapter->;gotcl = adapter->;stats.gotcl - adapter->;gotcl_old;
adapter->;gotcl_old = adapter->;stats.gotcl;
e1000_update_adaptive(&adapter->;hw);
if(!netif_carrier_ok(netdev)) {
if(E1000_DESC_UNUSED(txdr) + 1 < txdr->;count) {
/* We've lost link, so the controller stops DMA,
* but we've got queued Tx work that's never going
* to get done, so reset controller to flush Tx.
* (Do the reset outside of interrupt context). */
schedule_work(&adapter->;tx_timeout_task);
}
}
/* Dynamic mode for Interrupt Throttle Rate (ITR) */
if(adapter->;hw.mac_type >;= e1000_82540 && adapter->;itr == 1) {
/* Symmetric Tx/Rx gets a reduced ITR=2000; Total
* asymmetrical Tx or Rx gets ITR=8000; everyone
* else is between 2000-8000. */
uint32_t goc = (adapter->;gotcl + adapter->;gorcl) / 10000;
uint32_t dif = (adapter->;gotcl >; adapter->;gorcl ?
adapter->;gotcl - adapter->;gorcl :
adapter->;gorcl - adapter->;gotcl) / 10000;
uint32_t itr = goc >; 0 ? (dif * 6000 / goc + 2000) : 8000;
E1000_WRITE_REG(&adapter->;hw, ITR, 1000000000 / (itr * 256));
}
/* Cause software interrupt to ensure rx ring is cleaned */
E1000_WRITE_REG(&adapter->;hw, ICS, E1000_ICS_RXDMT0);
/* Early detection of hung controller */
i = txdr->;next_to_clean;
if(txdr->;buffer_info[i].dma &&
time_after(jiffies, txdr->;buffer_info[i].time_stamp + HZ) &&
!(E1000_READ_REG(&adapter->;hw, STATUS) & E1000_STATUS_TXOFF))
netif_stop_queue(netdev);
/* Reset the timer */
mod_timer(&adapter->;watchdog_timer, jiffies + 2 * HZ);
}