Skip to content

Commit

Permalink
qlge: Add watchdog timer.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ron Mercer authored and David S. Miller committed Feb 4, 2010
1 parent f8f76db commit 15c052f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/qlge/qlge.h
Original file line number Diff line number Diff line change
Expand Up @@ -2145,6 +2145,7 @@ struct ql_adapter {
struct completion ide_completion;
struct nic_operations *nic_ops;
u16 device_id;
struct timer_list timer;
atomic_t lb_count;
};

Expand Down
30 changes: 30 additions & 0 deletions drivers/net/qlge/qlge_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4574,6 +4574,21 @@ static const struct net_device_ops qlge_netdev_ops = {
.ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid,
};

static void ql_timer(unsigned long data)
{
struct ql_adapter *qdev = (struct ql_adapter *)data;
u32 var = 0;

var = ql_read32(qdev, STS);
if (pci_channel_offline(qdev->pdev)) {
QPRINTK(qdev, IFUP, ERR, "EEH STS = 0x%.08x.\n", var);
return;
}

qdev->timer.expires = jiffies + (5*HZ);
add_timer(&qdev->timer);
}

static int __devinit qlge_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_entry)
{
Expand Down Expand Up @@ -4625,6 +4640,14 @@ static int __devinit qlge_probe(struct pci_dev *pdev,
pci_disable_device(pdev);
return err;
}
/* Start up the timer to trigger EEH if
* the bus goes dead
*/
init_timer_deferrable(&qdev->timer);
qdev->timer.data = (unsigned long)qdev;
qdev->timer.function = ql_timer;
qdev->timer.expires = jiffies + (5*HZ);
add_timer(&qdev->timer);
ql_link_off(qdev);
ql_display_dev_info(ndev);
atomic_set(&qdev->lb_count, 0);
Expand All @@ -4645,6 +4668,8 @@ int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget)
static void __devexit qlge_remove(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
struct ql_adapter *qdev = netdev_priv(ndev);
del_timer_sync(&qdev->timer);
unregister_netdev(ndev);
ql_release_all(pdev);
pci_disable_device(pdev);
Expand Down Expand Up @@ -4757,6 +4782,8 @@ static void qlge_io_resume(struct pci_dev *pdev)
QPRINTK(qdev, IFUP, ERR,
"Device was not running prior to EEH.\n");
}
qdev->timer.expires = jiffies + (5*HZ);
add_timer(&qdev->timer);
netif_device_attach(ndev);
}

Expand All @@ -4773,6 +4800,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state)
int err;

netif_device_detach(ndev);
del_timer_sync(&qdev->timer);

if (netif_running(ndev)) {
err = ql_adapter_down(qdev);
Expand Down Expand Up @@ -4817,6 +4845,8 @@ static int qlge_resume(struct pci_dev *pdev)
return err;
}

qdev->timer.expires = jiffies + (5*HZ);
add_timer(&qdev->timer);
netif_device_attach(ndev);

return 0;
Expand Down

0 comments on commit 15c052f

Please sign in to comment.