.. | .. |
---|
211 | 211 | t1_interrupts_clear(adapter); |
---|
212 | 212 | |
---|
213 | 213 | adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev); |
---|
214 | | - err = request_threaded_irq(adapter->pdev->irq, t1_interrupt, |
---|
215 | | - t1_interrupt_thread, |
---|
216 | | - adapter->params.has_msi ? 0 : IRQF_SHARED, |
---|
217 | | - adapter->name, adapter); |
---|
| 214 | + err = request_irq(adapter->pdev->irq, t1_interrupt, |
---|
| 215 | + adapter->params.has_msi ? 0 : IRQF_SHARED, |
---|
| 216 | + adapter->name, adapter); |
---|
218 | 217 | if (err) { |
---|
219 | 218 | if (adapter->params.has_msi) |
---|
220 | 219 | pci_disable_msi(adapter->pdev); |
---|
.. | .. |
---|
917 | 916 | spin_unlock(&adapter->work_lock); |
---|
918 | 917 | } |
---|
919 | 918 | |
---|
| 919 | +/* |
---|
| 920 | + * Processes elmer0 external interrupts in process context. |
---|
| 921 | + */ |
---|
| 922 | +static void ext_intr_task(struct work_struct *work) |
---|
| 923 | +{ |
---|
| 924 | + struct adapter *adapter = |
---|
| 925 | + container_of(work, struct adapter, ext_intr_handler_task); |
---|
| 926 | + |
---|
| 927 | + t1_elmer0_ext_intr_handler(adapter); |
---|
| 928 | + |
---|
| 929 | + /* Now reenable external interrupts */ |
---|
| 930 | + spin_lock_irq(&adapter->async_lock); |
---|
| 931 | + adapter->slow_intr_mask |= F_PL_INTR_EXT; |
---|
| 932 | + writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE); |
---|
| 933 | + writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA, |
---|
| 934 | + adapter->regs + A_PL_ENABLE); |
---|
| 935 | + spin_unlock_irq(&adapter->async_lock); |
---|
| 936 | +} |
---|
| 937 | + |
---|
| 938 | +/* |
---|
| 939 | + * Interrupt-context handler for elmer0 external interrupts. |
---|
| 940 | + */ |
---|
| 941 | +void t1_elmer0_ext_intr(struct adapter *adapter) |
---|
| 942 | +{ |
---|
| 943 | + /* |
---|
| 944 | + * Schedule a task to handle external interrupts as we require |
---|
| 945 | + * a process context. We disable EXT interrupts in the interim |
---|
| 946 | + * and let the task reenable them when it's done. |
---|
| 947 | + */ |
---|
| 948 | + adapter->slow_intr_mask &= ~F_PL_INTR_EXT; |
---|
| 949 | + writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA, |
---|
| 950 | + adapter->regs + A_PL_ENABLE); |
---|
| 951 | + schedule_work(&adapter->ext_intr_handler_task); |
---|
| 952 | +} |
---|
| 953 | + |
---|
| 954 | +void t1_fatal_err(struct adapter *adapter) |
---|
| 955 | +{ |
---|
| 956 | + if (adapter->flags & FULL_INIT_DONE) { |
---|
| 957 | + t1_sge_stop(adapter->sge); |
---|
| 958 | + t1_interrupts_disable(adapter); |
---|
| 959 | + } |
---|
| 960 | + pr_alert("%s: encountered fatal error, operation suspended\n", |
---|
| 961 | + adapter->name); |
---|
| 962 | +} |
---|
| 963 | + |
---|
920 | 964 | static const struct net_device_ops cxgb_netdev_ops = { |
---|
921 | 965 | .ndo_open = cxgb_open, |
---|
922 | 966 | .ndo_stop = cxgb_close, |
---|
.. | .. |
---|
1018 | 1062 | spin_lock_init(&adapter->async_lock); |
---|
1019 | 1063 | spin_lock_init(&adapter->mac_lock); |
---|
1020 | 1064 | |
---|
| 1065 | + INIT_WORK(&adapter->ext_intr_handler_task, |
---|
| 1066 | + ext_intr_task); |
---|
1021 | 1067 | INIT_DELAYED_WORK(&adapter->stats_update_task, |
---|
1022 | 1068 | mac_stats_task); |
---|
1023 | 1069 | |
---|