diff options
author | Amit Kumar Salecha <amit@qlogic.com> | 2009-08-13 03:03:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-13 19:33:03 -0400 |
commit | e424fa9d6a0add1a9b812b07e3607daaa5b9e53d (patch) | |
tree | 3c29efe8d877845647c32d60a9b20f3fa4950093 /drivers/net/netxen/netxen_nic_main.c | |
parent | 237057ad3fe5644fa471be474a160de2fc2e5870 (diff) |
netxen: remove netxen workqueue
o Remove private workqueue in the driver, move all
scheduled tasks to keventd workqueues. This makes
ports (interfaces) of same / different NIC boards
independent, in terms of their link watchdog and
reset tasks.
o Move quick checks for link status and temperature
in timer callback, schedule watchdog task only if
link status changed or temperature reached critical
threshold.
This also fixes deadlock when thermal panic occurs,
watchdog work was flushing workqueue that it was
sitting on.
Signed-off-by: Amit Kumar Salecha <amit@qlogic.com>
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 70c05c4c0cab..d24e1cb93a26 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -94,10 +94,6 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = { | |||
94 | 94 | ||
95 | MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); | 95 | MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); |
96 | 96 | ||
97 | static struct workqueue_struct *netxen_workq; | ||
98 | #define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp) | ||
99 | #define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq) | ||
100 | |||
101 | static void netxen_watchdog(unsigned long); | 97 | static void netxen_watchdog(unsigned long); |
102 | 98 | ||
103 | static uint32_t crb_cmd_producer[4] = { | 99 | static uint32_t crb_cmd_producer[4] = { |
@@ -880,7 +876,6 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | |||
880 | spin_unlock(&adapter->tx_clean_lock); | 876 | spin_unlock(&adapter->tx_clean_lock); |
881 | 877 | ||
882 | del_timer_sync(&adapter->watchdog_timer); | 878 | del_timer_sync(&adapter->watchdog_timer); |
883 | FLUSH_SCHEDULED_WORK(); | ||
884 | } | 879 | } |
885 | 880 | ||
886 | 881 | ||
@@ -1177,6 +1172,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) | |||
1177 | 1172 | ||
1178 | unregister_netdev(netdev); | 1173 | unregister_netdev(netdev); |
1179 | 1174 | ||
1175 | cancel_work_sync(&adapter->watchdog_task); | ||
1176 | cancel_work_sync(&adapter->tx_timeout_task); | ||
1177 | |||
1180 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { | 1178 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { |
1181 | netxen_nic_detach(adapter); | 1179 | netxen_nic_detach(adapter); |
1182 | } | 1180 | } |
@@ -1211,6 +1209,9 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) | |||
1211 | if (netif_running(netdev)) | 1209 | if (netif_running(netdev)) |
1212 | netxen_nic_down(adapter, netdev); | 1210 | netxen_nic_down(adapter, netdev); |
1213 | 1211 | ||
1212 | cancel_work_sync(&adapter->watchdog_task); | ||
1213 | cancel_work_sync(&adapter->tx_timeout_task); | ||
1214 | |||
1214 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) | 1215 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) |
1215 | netxen_nic_detach(adapter); | 1216 | netxen_nic_detach(adapter); |
1216 | 1217 | ||
@@ -1549,11 +1550,6 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) | |||
1549 | "%s: Device temperature %d degrees C exceeds" | 1550 | "%s: Device temperature %d degrees C exceeds" |
1550 | " maximum allowed. Hardware has been shut down.\n", | 1551 | " maximum allowed. Hardware has been shut down.\n", |
1551 | netdev->name, temp_val); | 1552 | netdev->name, temp_val); |
1552 | |||
1553 | netif_device_detach(netdev); | ||
1554 | netxen_nic_down(adapter, netdev); | ||
1555 | netxen_nic_detach(adapter); | ||
1556 | |||
1557 | rv = 1; | 1553 | rv = 1; |
1558 | } else if (temp_state == NX_TEMP_WARN) { | 1554 | } else if (temp_state == NX_TEMP_WARN) { |
1559 | if (adapter->temp == NX_TEMP_NORMAL) { | 1555 | if (adapter->temp == NX_TEMP_NORMAL) { |
@@ -1587,10 +1583,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup) | |||
1587 | netif_carrier_off(netdev); | 1583 | netif_carrier_off(netdev); |
1588 | netif_stop_queue(netdev); | 1584 | netif_stop_queue(netdev); |
1589 | } | 1585 | } |
1590 | 1586 | adapter->link_changed = !adapter->has_link_events; | |
1591 | if (!adapter->has_link_events) | ||
1592 | netxen_nic_set_link_parameters(adapter); | ||
1593 | |||
1594 | } else if (!adapter->ahw.linkup && linkup) { | 1587 | } else if (!adapter->ahw.linkup && linkup) { |
1595 | printk(KERN_INFO "%s: %s NIC Link is up\n", | 1588 | printk(KERN_INFO "%s: %s NIC Link is up\n", |
1596 | netxen_nic_driver_name, netdev->name); | 1589 | netxen_nic_driver_name, netdev->name); |
@@ -1599,9 +1592,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup) | |||
1599 | netif_carrier_on(netdev); | 1592 | netif_carrier_on(netdev); |
1600 | netif_wake_queue(netdev); | 1593 | netif_wake_queue(netdev); |
1601 | } | 1594 | } |
1602 | 1595 | adapter->link_changed = !adapter->has_link_events; | |
1603 | if (!adapter->has_link_events) | ||
1604 | netxen_nic_set_link_parameters(adapter); | ||
1605 | } | 1596 | } |
1606 | } | 1597 | } |
1607 | 1598 | ||
@@ -1628,11 +1619,36 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) | |||
1628 | netxen_advert_link_change(adapter, linkup); | 1619 | netxen_advert_link_change(adapter, linkup); |
1629 | } | 1620 | } |
1630 | 1621 | ||
1622 | static void netxen_nic_thermal_shutdown(struct netxen_adapter *adapter) | ||
1623 | { | ||
1624 | struct net_device *netdev = adapter->netdev; | ||
1625 | |||
1626 | netif_device_detach(netdev); | ||
1627 | netxen_nic_down(adapter, netdev); | ||
1628 | netxen_nic_detach(adapter); | ||
1629 | } | ||
1630 | |||
1631 | static void netxen_watchdog(unsigned long v) | 1631 | static void netxen_watchdog(unsigned long v) |
1632 | { | 1632 | { |
1633 | struct netxen_adapter *adapter = (struct netxen_adapter *)v; | 1633 | struct netxen_adapter *adapter = (struct netxen_adapter *)v; |
1634 | 1634 | ||
1635 | SCHEDULE_WORK(&adapter->watchdog_task); | 1635 | if (netxen_nic_check_temp(adapter)) |
1636 | goto do_sched; | ||
1637 | |||
1638 | if (!adapter->has_link_events) { | ||
1639 | netxen_nic_handle_phy_intr(adapter); | ||
1640 | |||
1641 | if (adapter->link_changed) | ||
1642 | goto do_sched; | ||
1643 | } | ||
1644 | |||
1645 | if (netif_running(adapter->netdev)) | ||
1646 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); | ||
1647 | |||
1648 | return; | ||
1649 | |||
1650 | do_sched: | ||
1651 | schedule_work(&adapter->watchdog_task); | ||
1636 | } | 1652 | } |
1637 | 1653 | ||
1638 | void netxen_watchdog_task(struct work_struct *work) | 1654 | void netxen_watchdog_task(struct work_struct *work) |
@@ -1640,11 +1656,13 @@ void netxen_watchdog_task(struct work_struct *work) | |||
1640 | struct netxen_adapter *adapter = | 1656 | struct netxen_adapter *adapter = |
1641 | container_of(work, struct netxen_adapter, watchdog_task); | 1657 | container_of(work, struct netxen_adapter, watchdog_task); |
1642 | 1658 | ||
1643 | if (netxen_nic_check_temp(adapter)) | 1659 | if (adapter->temp == NX_TEMP_PANIC) { |
1660 | netxen_nic_thermal_shutdown(adapter); | ||
1644 | return; | 1661 | return; |
1662 | } | ||
1645 | 1663 | ||
1646 | if (!adapter->has_link_events) | 1664 | if (adapter->link_changed) |
1647 | netxen_nic_handle_phy_intr(adapter); | 1665 | netxen_nic_set_link_parameters(adapter); |
1648 | 1666 | ||
1649 | if (netif_running(adapter->netdev)) | 1667 | if (netif_running(adapter->netdev)) |
1650 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); | 1668 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); |
@@ -1652,9 +1670,8 @@ void netxen_watchdog_task(struct work_struct *work) | |||
1652 | 1670 | ||
1653 | static void netxen_tx_timeout(struct net_device *netdev) | 1671 | static void netxen_tx_timeout(struct net_device *netdev) |
1654 | { | 1672 | { |
1655 | struct netxen_adapter *adapter = (struct netxen_adapter *) | 1673 | struct netxen_adapter *adapter = netdev_priv(netdev); |
1656 | netdev_priv(netdev); | 1674 | schedule_work(&adapter->tx_timeout_task); |
1657 | SCHEDULE_WORK(&adapter->tx_timeout_task); | ||
1658 | } | 1675 | } |
1659 | 1676 | ||
1660 | static void netxen_tx_timeout_task(struct work_struct *work) | 1677 | static void netxen_tx_timeout_task(struct work_struct *work) |
@@ -1811,9 +1828,6 @@ static int __init netxen_init_module(void) | |||
1811 | { | 1828 | { |
1812 | printk(KERN_INFO "%s\n", netxen_nic_driver_string); | 1829 | printk(KERN_INFO "%s\n", netxen_nic_driver_string); |
1813 | 1830 | ||
1814 | if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL) | ||
1815 | return -ENOMEM; | ||
1816 | |||
1817 | return pci_register_driver(&netxen_driver); | 1831 | return pci_register_driver(&netxen_driver); |
1818 | } | 1832 | } |
1819 | 1833 | ||
@@ -1822,7 +1836,6 @@ module_init(netxen_init_module); | |||
1822 | static void __exit netxen_exit_module(void) | 1836 | static void __exit netxen_exit_module(void) |
1823 | { | 1837 | { |
1824 | pci_unregister_driver(&netxen_driver); | 1838 | pci_unregister_driver(&netxen_driver); |
1825 | destroy_workqueue(netxen_workq); | ||
1826 | } | 1839 | } |
1827 | 1840 | ||
1828 | module_exit(netxen_exit_module); | 1841 | module_exit(netxen_exit_module); |