Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 171798
b: refs/heads/master
c: 41cec6f
h: refs/heads/master
v: v3
  • Loading branch information
Bruce Allan authored and David S. Miller committed Nov 21, 2009
1 parent 0399345 commit a62ec87
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a708dd88a014a8fd78713adbd19bc61046eaac7f
refs/heads/master: 41cec6f1160c110bd69597c2a5611b46e8287801
1 change: 1 addition & 0 deletions trunk/drivers/net/e1000e/e1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ struct e1000_adapter {
struct work_struct downshift_task;
struct work_struct update_phy_task;
struct work_struct led_blink_task;
struct work_struct print_hang_task;
};

struct e1000_info {
Expand Down
46 changes: 38 additions & 8 deletions trunk/drivers/net/e1000e/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,15 +544,27 @@ static void e1000_put_txbuf(struct e1000_adapter *adapter,
buffer_info->time_stamp = 0;
}

static void e1000_print_tx_hang(struct e1000_adapter *adapter)
static void e1000_print_hw_hang(struct work_struct *work)
{
struct e1000_adapter *adapter = container_of(work,
struct e1000_adapter,
print_hang_task);
struct e1000_ring *tx_ring = adapter->tx_ring;
unsigned int i = tx_ring->next_to_clean;
unsigned int eop = tx_ring->buffer_info[i].next_to_watch;
struct e1000_tx_desc *eop_desc = E1000_TX_DESC(*tx_ring, eop);
struct e1000_hw *hw = &adapter->hw;
u16 phy_status, phy_1000t_status, phy_ext_status;
u16 pci_status;

e1e_rphy(hw, PHY_STATUS, &phy_status);
e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status);
e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status);

/* detected Tx unit hang */
e_err("Detected Tx Unit Hang:\n"
pci_read_config_word(adapter->pdev, PCI_STATUS, &pci_status);

/* detected Hardware unit hang */
e_err("Detected Hardware Unit Hang:\n"
" TDH <%x>\n"
" TDT <%x>\n"
" next_to_use <%x>\n"
Expand All @@ -561,15 +573,25 @@ static void e1000_print_tx_hang(struct e1000_adapter *adapter)
" time_stamp <%lx>\n"
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
" next_to_watch.status <%x>\n",
" next_to_watch.status <%x>\n"
"MAC Status <%x>\n"
"PHY Status <%x>\n"
"PHY 1000BASE-T Status <%x>\n"
"PHY Extended Status <%x>\n"
"PCI Status <%x>\n",
readl(adapter->hw.hw_addr + tx_ring->head),
readl(adapter->hw.hw_addr + tx_ring->tail),
tx_ring->next_to_use,
tx_ring->next_to_clean,
tx_ring->buffer_info[eop].time_stamp,
eop,
jiffies,
eop_desc->upper.fields.status);
eop_desc->upper.fields.status,
er32(STATUS),
phy_status,
phy_1000t_status,
phy_ext_status,
pci_status);
}

/**
Expand Down Expand Up @@ -643,14 +665,16 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
}

if (adapter->detect_tx_hung) {
/* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i */
/*
* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i
*/
adapter->detect_tx_hung = 0;
if (tx_ring->buffer_info[i].time_stamp &&
time_after(jiffies, tx_ring->buffer_info[i].time_stamp
+ (adapter->tx_timeout_factor * HZ))
&& !(er32(STATUS) & E1000_STATUS_TXOFF)) {
e1000_print_tx_hang(adapter);
schedule_work(&adapter->print_hang_task);
netif_stop_queue(netdev);
}
}
Expand Down Expand Up @@ -5118,6 +5142,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang);

/* Initialize link parameters. User can change them with ethtool */
adapter->hw.mac.autoneg = 1;
Expand Down Expand Up @@ -5241,6 +5266,11 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_info_timer);

cancel_work_sync(&adapter->reset_task);
cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->downshift_task);
cancel_work_sync(&adapter->update_phy_task);
cancel_work_sync(&adapter->print_hang_task);
flush_scheduled_work();

/*
Expand Down

0 comments on commit a62ec87

Please sign in to comment.