aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/e1000e/e1000.h1
-rw-r--r--drivers/net/e1000e/netdev.c46
2 files changed, 39 insertions, 8 deletions
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 5ac8675b0c58..c9fcef7f8462 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -364,6 +364,7 @@ struct e1000_adapter {
364 struct work_struct downshift_task; 364 struct work_struct downshift_task;
365 struct work_struct update_phy_task; 365 struct work_struct update_phy_task;
366 struct work_struct led_blink_task; 366 struct work_struct led_blink_task;
367 struct work_struct print_hang_task;
367}; 368};
368 369
369struct e1000_info { 370struct e1000_info {
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 39f01d998b4d..11a527484e18 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -544,15 +544,27 @@ static void e1000_put_txbuf(struct e1000_adapter *adapter,
544 buffer_info->time_stamp = 0; 544 buffer_info->time_stamp = 0;
545} 545}
546 546
547static void e1000_print_tx_hang(struct e1000_adapter *adapter) 547static void e1000_print_hw_hang(struct work_struct *work)
548{ 548{
549 struct e1000_adapter *adapter = container_of(work,
550 struct e1000_adapter,
551 print_hang_task);
549 struct e1000_ring *tx_ring = adapter->tx_ring; 552 struct e1000_ring *tx_ring = adapter->tx_ring;
550 unsigned int i = tx_ring->next_to_clean; 553 unsigned int i = tx_ring->next_to_clean;
551 unsigned int eop = tx_ring->buffer_info[i].next_to_watch; 554 unsigned int eop = tx_ring->buffer_info[i].next_to_watch;
552 struct e1000_tx_desc *eop_desc = E1000_TX_DESC(*tx_ring, eop); 555 struct e1000_tx_desc *eop_desc = E1000_TX_DESC(*tx_ring, eop);
556 struct e1000_hw *hw = &adapter->hw;
557 u16 phy_status, phy_1000t_status, phy_ext_status;
558 u16 pci_status;
559
560 e1e_rphy(hw, PHY_STATUS, &phy_status);
561 e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status);
562 e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status);
553 563
554 /* detected Tx unit hang */ 564 pci_read_config_word(adapter->pdev, PCI_STATUS, &pci_status);
555 e_err("Detected Tx Unit Hang:\n" 565
566 /* detected Hardware unit hang */
567 e_err("Detected Hardware Unit Hang:\n"
556 " TDH <%x>\n" 568 " TDH <%x>\n"
557 " TDT <%x>\n" 569 " TDT <%x>\n"
558 " next_to_use <%x>\n" 570 " next_to_use <%x>\n"
@@ -561,7 +573,12 @@ static void e1000_print_tx_hang(struct e1000_adapter *adapter)
561 " time_stamp <%lx>\n" 573 " time_stamp <%lx>\n"
562 " next_to_watch <%x>\n" 574 " next_to_watch <%x>\n"
563 " jiffies <%lx>\n" 575 " jiffies <%lx>\n"
564 " next_to_watch.status <%x>\n", 576 " next_to_watch.status <%x>\n"
577 "MAC Status <%x>\n"
578 "PHY Status <%x>\n"
579 "PHY 1000BASE-T Status <%x>\n"
580 "PHY Extended Status <%x>\n"
581 "PCI Status <%x>\n",
565 readl(adapter->hw.hw_addr + tx_ring->head), 582 readl(adapter->hw.hw_addr + tx_ring->head),
566 readl(adapter->hw.hw_addr + tx_ring->tail), 583 readl(adapter->hw.hw_addr + tx_ring->tail),
567 tx_ring->next_to_use, 584 tx_ring->next_to_use,
@@ -569,7 +586,12 @@ static void e1000_print_tx_hang(struct e1000_adapter *adapter)
569 tx_ring->buffer_info[eop].time_stamp, 586 tx_ring->buffer_info[eop].time_stamp,
570 eop, 587 eop,
571 jiffies, 588 jiffies,
572 eop_desc->upper.fields.status); 589 eop_desc->upper.fields.status,
590 er32(STATUS),
591 phy_status,
592 phy_1000t_status,
593 phy_ext_status,
594 pci_status);
573} 595}
574 596
575/** 597/**
@@ -643,14 +665,16 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
643 } 665 }
644 666
645 if (adapter->detect_tx_hung) { 667 if (adapter->detect_tx_hung) {
646 /* Detect a transmit hang in hardware, this serializes the 668 /*
647 * check with the clearing of time_stamp and movement of i */ 669 * Detect a transmit hang in hardware, this serializes the
670 * check with the clearing of time_stamp and movement of i
671 */
648 adapter->detect_tx_hung = 0; 672 adapter->detect_tx_hung = 0;
649 if (tx_ring->buffer_info[i].time_stamp && 673 if (tx_ring->buffer_info[i].time_stamp &&
650 time_after(jiffies, tx_ring->buffer_info[i].time_stamp 674 time_after(jiffies, tx_ring->buffer_info[i].time_stamp
651 + (adapter->tx_timeout_factor * HZ)) 675 + (adapter->tx_timeout_factor * HZ))
652 && !(er32(STATUS) & E1000_STATUS_TXOFF)) { 676 && !(er32(STATUS) & E1000_STATUS_TXOFF)) {
653 e1000_print_tx_hang(adapter); 677 schedule_work(&adapter->print_hang_task);
654 netif_stop_queue(netdev); 678 netif_stop_queue(netdev);
655 } 679 }
656 } 680 }
@@ -5118,6 +5142,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
5118 INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); 5142 INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
5119 INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround); 5143 INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
5120 INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task); 5144 INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
5145 INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang);
5121 5146
5122 /* Initialize link parameters. User can change them with ethtool */ 5147 /* Initialize link parameters. User can change them with ethtool */
5123 adapter->hw.mac.autoneg = 1; 5148 adapter->hw.mac.autoneg = 1;
@@ -5241,6 +5266,11 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
5241 del_timer_sync(&adapter->watchdog_timer); 5266 del_timer_sync(&adapter->watchdog_timer);
5242 del_timer_sync(&adapter->phy_info_timer); 5267 del_timer_sync(&adapter->phy_info_timer);
5243 5268
5269 cancel_work_sync(&adapter->reset_task);
5270 cancel_work_sync(&adapter->watchdog_task);
5271 cancel_work_sync(&adapter->downshift_task);
5272 cancel_work_sync(&adapter->update_phy_task);
5273 cancel_work_sync(&adapter->print_hang_task);
5244 flush_scheduled_work(); 5274 flush_scheduled_work();
5245 5275
5246 /* 5276 /*