aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2009-11-20 18:28:56 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-21 14:34:32 -0500
commit41cec6f1160c110bd69597c2a5611b46e8287801 (patch)
treec7d544f9648e9b758b110b4171e948d3f2c02b95 /drivers/net/e1000e
parenta708dd88a014a8fd78713adbd19bc61046eaac7f (diff)
e1000e: update Tx Unit hang detection message
The Tx unit hang detection code in e1000e detects other hangs caused by hardware components (e.g. Rx, DMA units), but it is not possible to detect exactly which component is hung so it has always assumed a Tx unit hang. When dumping a message to the system log because of a hang, this patch adds more data to help narrow the cause of the issue and makes the message non-Tx-specific. Because this new code reads PHY registers which can sleep, move it off to a workqueue. This and all previously existing work tasks in the driver are now cancelled when the driver is removed. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000e')
-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 /*