aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRon Mercer <ron.mercer@qlogic.com>2010-02-04 16:32:46 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-04 16:32:46 -0500
commit15c052fc7f4a1b3544602be8af77e31bba9261bf (patch)
tree07a0f4b0db1c04046fd5ec2fa41188ece18e8cd9 /drivers
parentf8f76db1db369f3a130ac3fd33e2eee5f1610d9c (diff)
qlge: Add watchdog timer.
Add periodic heartbeat register read to trigger the eeh recovery process. We see cases where an eeh error was injected and the slot was suspended. An asic access attempt is required to flush the recovery process, but without interrupts the process can stall. Adding this periodic register read causes the recovery process to begin. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/qlge/qlge.h1
-rw-r--r--drivers/net/qlge/qlge_main.c30
2 files changed, 31 insertions, 0 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index 780a38731bcc..ebfd17776b53 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -2145,6 +2145,7 @@ struct ql_adapter {
2145 struct completion ide_completion; 2145 struct completion ide_completion;
2146 struct nic_operations *nic_ops; 2146 struct nic_operations *nic_ops;
2147 u16 device_id; 2147 u16 device_id;
2148 struct timer_list timer;
2148 atomic_t lb_count; 2149 atomic_t lb_count;
2149}; 2150};
2150 2151
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 7e000295f359..87a40d168b36 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -4574,6 +4574,21 @@ static const struct net_device_ops qlge_netdev_ops = {
4574 .ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid, 4574 .ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid,
4575}; 4575};
4576 4576
4577static void ql_timer(unsigned long data)
4578{
4579 struct ql_adapter *qdev = (struct ql_adapter *)data;
4580 u32 var = 0;
4581
4582 var = ql_read32(qdev, STS);
4583 if (pci_channel_offline(qdev->pdev)) {
4584 QPRINTK(qdev, IFUP, ERR, "EEH STS = 0x%.08x.\n", var);
4585 return;
4586 }
4587
4588 qdev->timer.expires = jiffies + (5*HZ);
4589 add_timer(&qdev->timer);
4590}
4591
4577static int __devinit qlge_probe(struct pci_dev *pdev, 4592static int __devinit qlge_probe(struct pci_dev *pdev,
4578 const struct pci_device_id *pci_entry) 4593 const struct pci_device_id *pci_entry)
4579{ 4594{
@@ -4625,6 +4640,14 @@ static int __devinit qlge_probe(struct pci_dev *pdev,
4625 pci_disable_device(pdev); 4640 pci_disable_device(pdev);
4626 return err; 4641 return err;
4627 } 4642 }
4643 /* Start up the timer to trigger EEH if
4644 * the bus goes dead
4645 */
4646 init_timer_deferrable(&qdev->timer);
4647 qdev->timer.data = (unsigned long)qdev;
4648 qdev->timer.function = ql_timer;
4649 qdev->timer.expires = jiffies + (5*HZ);
4650 add_timer(&qdev->timer);
4628 ql_link_off(qdev); 4651 ql_link_off(qdev);
4629 ql_display_dev_info(ndev); 4652 ql_display_dev_info(ndev);
4630 atomic_set(&qdev->lb_count, 0); 4653 atomic_set(&qdev->lb_count, 0);
@@ -4645,6 +4668,8 @@ int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget)
4645static void __devexit qlge_remove(struct pci_dev *pdev) 4668static void __devexit qlge_remove(struct pci_dev *pdev)
4646{ 4669{
4647 struct net_device *ndev = pci_get_drvdata(pdev); 4670 struct net_device *ndev = pci_get_drvdata(pdev);
4671 struct ql_adapter *qdev = netdev_priv(ndev);
4672 del_timer_sync(&qdev->timer);
4648 unregister_netdev(ndev); 4673 unregister_netdev(ndev);
4649 ql_release_all(pdev); 4674 ql_release_all(pdev);
4650 pci_disable_device(pdev); 4675 pci_disable_device(pdev);
@@ -4757,6 +4782,8 @@ static void qlge_io_resume(struct pci_dev *pdev)
4757 QPRINTK(qdev, IFUP, ERR, 4782 QPRINTK(qdev, IFUP, ERR,
4758 "Device was not running prior to EEH.\n"); 4783 "Device was not running prior to EEH.\n");
4759 } 4784 }
4785 qdev->timer.expires = jiffies + (5*HZ);
4786 add_timer(&qdev->timer);
4760 netif_device_attach(ndev); 4787 netif_device_attach(ndev);
4761} 4788}
4762 4789
@@ -4773,6 +4800,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state)
4773 int err; 4800 int err;
4774 4801
4775 netif_device_detach(ndev); 4802 netif_device_detach(ndev);
4803 del_timer_sync(&qdev->timer);
4776 4804
4777 if (netif_running(ndev)) { 4805 if (netif_running(ndev)) {
4778 err = ql_adapter_down(qdev); 4806 err = ql_adapter_down(qdev);
@@ -4817,6 +4845,8 @@ static int qlge_resume(struct pci_dev *pdev)
4817 return err; 4845 return err;
4818 } 4846 }
4819 4847
4848 qdev->timer.expires = jiffies + (5*HZ);
4849 add_timer(&qdev->timer);
4820 netif_device_attach(ndev); 4850 netif_device_attach(ndev);
4821 4851
4822 return 0; 4852 return 0;