diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
| -rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 105 |
1 files changed, 67 insertions, 38 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 3cd8cfcf627b..28f270f5ac78 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] = { |
| @@ -171,6 +167,8 @@ netxen_free_sds_rings(struct netxen_recv_context *recv_ctx) | |||
| 171 | { | 167 | { |
| 172 | if (recv_ctx->sds_rings != NULL) | 168 | if (recv_ctx->sds_rings != NULL) |
| 173 | kfree(recv_ctx->sds_rings); | 169 | kfree(recv_ctx->sds_rings); |
| 170 | |||
| 171 | recv_ctx->sds_rings = NULL; | ||
| 174 | } | 172 | } |
| 175 | 173 | ||
| 176 | static int | 174 | static int |
| @@ -193,6 +191,21 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) | |||
| 193 | } | 191 | } |
| 194 | 192 | ||
| 195 | static void | 193 | static void |
| 194 | netxen_napi_del(struct netxen_adapter *adapter) | ||
| 195 | { | ||
| 196 | int ring; | ||
| 197 | struct nx_host_sds_ring *sds_ring; | ||
| 198 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | ||
| 199 | |||
| 200 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
| 201 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
| 202 | netif_napi_del(&sds_ring->napi); | ||
| 203 | } | ||
| 204 | |||
| 205 | netxen_free_sds_rings(&adapter->recv_ctx); | ||
| 206 | } | ||
| 207 | |||
| 208 | static void | ||
| 196 | netxen_napi_enable(struct netxen_adapter *adapter) | 209 | netxen_napi_enable(struct netxen_adapter *adapter) |
| 197 | { | 210 | { |
| 198 | int ring; | 211 | int ring; |
| @@ -260,7 +273,7 @@ nx_update_dma_mask(struct netxen_adapter *adapter) | |||
| 260 | change = 0; | 273 | change = 0; |
| 261 | 274 | ||
| 262 | shift = NXRD32(adapter, CRB_DMA_SHIFT); | 275 | shift = NXRD32(adapter, CRB_DMA_SHIFT); |
| 263 | if (shift >= 32) | 276 | if (shift > 32) |
| 264 | return 0; | 277 | return 0; |
| 265 | 278 | ||
| 266 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && (shift > 9)) | 279 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && (shift > 9)) |
| @@ -272,7 +285,7 @@ nx_update_dma_mask(struct netxen_adapter *adapter) | |||
| 272 | old_mask = pdev->dma_mask; | 285 | old_mask = pdev->dma_mask; |
| 273 | old_cmask = pdev->dev.coherent_dma_mask; | 286 | old_cmask = pdev->dev.coherent_dma_mask; |
| 274 | 287 | ||
| 275 | mask = (1ULL<<(32+shift)) - 1; | 288 | mask = DMA_BIT_MASK(32+shift); |
| 276 | 289 | ||
| 277 | err = pci_set_dma_mask(pdev, mask); | 290 | err = pci_set_dma_mask(pdev, mask); |
| 278 | if (err) | 291 | if (err) |
| @@ -880,7 +893,6 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | |||
| 880 | spin_unlock(&adapter->tx_clean_lock); | 893 | spin_unlock(&adapter->tx_clean_lock); |
| 881 | 894 | ||
| 882 | del_timer_sync(&adapter->watchdog_timer); | 895 | del_timer_sync(&adapter->watchdog_timer); |
| 883 | FLUSH_SCHEDULED_WORK(); | ||
| 884 | } | 896 | } |
| 885 | 897 | ||
| 886 | 898 | ||
| @@ -894,10 +906,12 @@ netxen_nic_attach(struct netxen_adapter *adapter) | |||
| 894 | struct nx_host_tx_ring *tx_ring; | 906 | struct nx_host_tx_ring *tx_ring; |
| 895 | 907 | ||
| 896 | err = netxen_init_firmware(adapter); | 908 | err = netxen_init_firmware(adapter); |
| 897 | if (err != 0) { | 909 | if (err) |
| 898 | printk(KERN_ERR "Failed to init firmware\n"); | 910 | return err; |
| 899 | return -EIO; | 911 | |
| 900 | } | 912 | err = netxen_napi_add(adapter, netdev); |
| 913 | if (err) | ||
| 914 | return err; | ||
| 901 | 915 | ||
| 902 | if (adapter->fw_major < 4) | 916 | if (adapter->fw_major < 4) |
| 903 | adapter->max_rds_rings = 3; | 917 | adapter->max_rds_rings = 3; |
| @@ -961,6 +975,7 @@ netxen_nic_detach(struct netxen_adapter *adapter) | |||
| 961 | netxen_free_hw_resources(adapter); | 975 | netxen_free_hw_resources(adapter); |
| 962 | netxen_release_rx_buffers(adapter); | 976 | netxen_release_rx_buffers(adapter); |
| 963 | netxen_nic_free_irq(adapter); | 977 | netxen_nic_free_irq(adapter); |
| 978 | netxen_napi_del(adapter); | ||
| 964 | netxen_free_sw_resources(adapter); | 979 | netxen_free_sw_resources(adapter); |
| 965 | 980 | ||
| 966 | adapter->is_up = 0; | 981 | adapter->is_up = 0; |
| @@ -1105,9 +1120,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1105 | 1120 | ||
| 1106 | netdev->irq = adapter->msix_entries[0].vector; | 1121 | netdev->irq = adapter->msix_entries[0].vector; |
| 1107 | 1122 | ||
| 1108 | if (netxen_napi_add(adapter, netdev)) | ||
| 1109 | goto err_out_disable_msi; | ||
| 1110 | |||
| 1111 | init_timer(&adapter->watchdog_timer); | 1123 | init_timer(&adapter->watchdog_timer); |
| 1112 | adapter->watchdog_timer.function = &netxen_watchdog; | 1124 | adapter->watchdog_timer.function = &netxen_watchdog; |
| 1113 | adapter->watchdog_timer.data = (unsigned long)adapter; | 1125 | adapter->watchdog_timer.data = (unsigned long)adapter; |
| @@ -1177,6 +1189,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) | |||
| 1177 | 1189 | ||
| 1178 | unregister_netdev(netdev); | 1190 | unregister_netdev(netdev); |
| 1179 | 1191 | ||
| 1192 | cancel_work_sync(&adapter->watchdog_task); | ||
| 1193 | cancel_work_sync(&adapter->tx_timeout_task); | ||
| 1194 | |||
| 1180 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { | 1195 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { |
| 1181 | netxen_nic_detach(adapter); | 1196 | netxen_nic_detach(adapter); |
| 1182 | } | 1197 | } |
| @@ -1185,7 +1200,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) | |||
| 1185 | netxen_free_adapter_offload(adapter); | 1200 | netxen_free_adapter_offload(adapter); |
| 1186 | 1201 | ||
| 1187 | netxen_teardown_intr(adapter); | 1202 | netxen_teardown_intr(adapter); |
| 1188 | netxen_free_sds_rings(&adapter->recv_ctx); | ||
| 1189 | 1203 | ||
| 1190 | netxen_cleanup_pci_map(adapter); | 1204 | netxen_cleanup_pci_map(adapter); |
| 1191 | 1205 | ||
| @@ -1211,6 +1225,9 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 1211 | if (netif_running(netdev)) | 1225 | if (netif_running(netdev)) |
| 1212 | netxen_nic_down(adapter, netdev); | 1226 | netxen_nic_down(adapter, netdev); |
| 1213 | 1227 | ||
| 1228 | cancel_work_sync(&adapter->watchdog_task); | ||
| 1229 | cancel_work_sync(&adapter->tx_timeout_task); | ||
| 1230 | |||
| 1214 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) | 1231 | if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) |
| 1215 | netxen_nic_detach(adapter); | 1232 | netxen_nic_detach(adapter); |
| 1216 | 1233 | ||
| @@ -1549,11 +1566,6 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) | |||
| 1549 | "%s: Device temperature %d degrees C exceeds" | 1566 | "%s: Device temperature %d degrees C exceeds" |
| 1550 | " maximum allowed. Hardware has been shut down.\n", | 1567 | " maximum allowed. Hardware has been shut down.\n", |
| 1551 | netdev->name, temp_val); | 1568 | 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; | 1569 | rv = 1; |
| 1558 | } else if (temp_state == NX_TEMP_WARN) { | 1570 | } else if (temp_state == NX_TEMP_WARN) { |
| 1559 | if (adapter->temp == NX_TEMP_NORMAL) { | 1571 | if (adapter->temp == NX_TEMP_NORMAL) { |
| @@ -1587,10 +1599,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup) | |||
| 1587 | netif_carrier_off(netdev); | 1599 | netif_carrier_off(netdev); |
| 1588 | netif_stop_queue(netdev); | 1600 | netif_stop_queue(netdev); |
| 1589 | } | 1601 | } |
| 1590 | 1602 | 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) { | 1603 | } else if (!adapter->ahw.linkup && linkup) { |
| 1595 | printk(KERN_INFO "%s: %s NIC Link is up\n", | 1604 | printk(KERN_INFO "%s: %s NIC Link is up\n", |
| 1596 | netxen_nic_driver_name, netdev->name); | 1605 | netxen_nic_driver_name, netdev->name); |
| @@ -1599,9 +1608,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup) | |||
| 1599 | netif_carrier_on(netdev); | 1608 | netif_carrier_on(netdev); |
| 1600 | netif_wake_queue(netdev); | 1609 | netif_wake_queue(netdev); |
| 1601 | } | 1610 | } |
| 1602 | 1611 | adapter->link_changed = !adapter->has_link_events; | |
| 1603 | if (!adapter->has_link_events) | ||
| 1604 | netxen_nic_set_link_parameters(adapter); | ||
| 1605 | } | 1612 | } |
| 1606 | } | 1613 | } |
| 1607 | 1614 | ||
| @@ -1628,11 +1635,36 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) | |||
| 1628 | netxen_advert_link_change(adapter, linkup); | 1635 | netxen_advert_link_change(adapter, linkup); |
| 1629 | } | 1636 | } |
| 1630 | 1637 | ||
| 1638 | static void netxen_nic_thermal_shutdown(struct netxen_adapter *adapter) | ||
| 1639 | { | ||
| 1640 | struct net_device *netdev = adapter->netdev; | ||
| 1641 | |||
| 1642 | netif_device_detach(netdev); | ||
| 1643 | netxen_nic_down(adapter, netdev); | ||
| 1644 | netxen_nic_detach(adapter); | ||
| 1645 | } | ||
| 1646 | |||
| 1631 | static void netxen_watchdog(unsigned long v) | 1647 | static void netxen_watchdog(unsigned long v) |
| 1632 | { | 1648 | { |
| 1633 | struct netxen_adapter *adapter = (struct netxen_adapter *)v; | 1649 | struct netxen_adapter *adapter = (struct netxen_adapter *)v; |
| 1634 | 1650 | ||
| 1635 | SCHEDULE_WORK(&adapter->watchdog_task); | 1651 | if (netxen_nic_check_temp(adapter)) |
| 1652 | goto do_sched; | ||
| 1653 | |||
| 1654 | if (!adapter->has_link_events) { | ||
| 1655 | netxen_nic_handle_phy_intr(adapter); | ||
| 1656 | |||
| 1657 | if (adapter->link_changed) | ||
| 1658 | goto do_sched; | ||
| 1659 | } | ||
| 1660 | |||
| 1661 | if (netif_running(adapter->netdev)) | ||
| 1662 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); | ||
| 1663 | |||
| 1664 | return; | ||
| 1665 | |||
| 1666 | do_sched: | ||
| 1667 | schedule_work(&adapter->watchdog_task); | ||
| 1636 | } | 1668 | } |
| 1637 | 1669 | ||
| 1638 | void netxen_watchdog_task(struct work_struct *work) | 1670 | void netxen_watchdog_task(struct work_struct *work) |
| @@ -1640,11 +1672,13 @@ void netxen_watchdog_task(struct work_struct *work) | |||
| 1640 | struct netxen_adapter *adapter = | 1672 | struct netxen_adapter *adapter = |
| 1641 | container_of(work, struct netxen_adapter, watchdog_task); | 1673 | container_of(work, struct netxen_adapter, watchdog_task); |
| 1642 | 1674 | ||
| 1643 | if (netxen_nic_check_temp(adapter)) | 1675 | if (adapter->temp == NX_TEMP_PANIC) { |
| 1676 | netxen_nic_thermal_shutdown(adapter); | ||
| 1644 | return; | 1677 | return; |
| 1678 | } | ||
| 1645 | 1679 | ||
| 1646 | if (!adapter->has_link_events) | 1680 | if (adapter->link_changed) |
| 1647 | netxen_nic_handle_phy_intr(adapter); | 1681 | netxen_nic_set_link_parameters(adapter); |
| 1648 | 1682 | ||
| 1649 | if (netif_running(adapter->netdev)) | 1683 | if (netif_running(adapter->netdev)) |
| 1650 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); | 1684 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); |
| @@ -1652,9 +1686,8 @@ void netxen_watchdog_task(struct work_struct *work) | |||
| 1652 | 1686 | ||
| 1653 | static void netxen_tx_timeout(struct net_device *netdev) | 1687 | static void netxen_tx_timeout(struct net_device *netdev) |
| 1654 | { | 1688 | { |
| 1655 | struct netxen_adapter *adapter = (struct netxen_adapter *) | 1689 | struct netxen_adapter *adapter = netdev_priv(netdev); |
| 1656 | netdev_priv(netdev); | 1690 | schedule_work(&adapter->tx_timeout_task); |
| 1657 | SCHEDULE_WORK(&adapter->tx_timeout_task); | ||
| 1658 | } | 1691 | } |
| 1659 | 1692 | ||
| 1660 | static void netxen_tx_timeout_task(struct work_struct *work) | 1693 | static void netxen_tx_timeout_task(struct work_struct *work) |
| @@ -1811,9 +1844,6 @@ static int __init netxen_init_module(void) | |||
| 1811 | { | 1844 | { |
| 1812 | printk(KERN_INFO "%s\n", netxen_nic_driver_string); | 1845 | printk(KERN_INFO "%s\n", netxen_nic_driver_string); |
| 1813 | 1846 | ||
| 1814 | if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL) | ||
| 1815 | return -ENOMEM; | ||
| 1816 | |||
| 1817 | return pci_register_driver(&netxen_driver); | 1847 | return pci_register_driver(&netxen_driver); |
| 1818 | } | 1848 | } |
| 1819 | 1849 | ||
| @@ -1822,7 +1852,6 @@ module_init(netxen_init_module); | |||
| 1822 | static void __exit netxen_exit_module(void) | 1852 | static void __exit netxen_exit_module(void) |
| 1823 | { | 1853 | { |
| 1824 | pci_unregister_driver(&netxen_driver); | 1854 | pci_unregister_driver(&netxen_driver); |
| 1825 | destroy_workqueue(netxen_workq); | ||
| 1826 | } | 1855 | } |
| 1827 | 1856 | ||
| 1828 | module_exit(netxen_exit_module); | 1857 | module_exit(netxen_exit_module); |
