| .. | .. |
|---|
| 170 | 170 | t1_link_negotiated(adapter, port_id, link_ok, speed, duplex, fc); |
|---|
| 171 | 171 | } |
|---|
| 172 | 172 | |
|---|
| 173 | | -static int t1_pci_intr_handler(adapter_t *adapter) |
|---|
| 173 | +static bool t1_pci_intr_handler(adapter_t *adapter) |
|---|
| 174 | 174 | { |
|---|
| 175 | 175 | u32 pcix_cause; |
|---|
| 176 | 176 | |
|---|
| .. | .. |
|---|
| 179 | 179 | if (pcix_cause) { |
|---|
| 180 | 180 | pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, |
|---|
| 181 | 181 | pcix_cause); |
|---|
| 182 | | - t1_fatal_err(adapter); /* PCI errors are fatal */ |
|---|
| 182 | + /* PCI errors are fatal */ |
|---|
| 183 | + t1_interrupts_disable(adapter); |
|---|
| 184 | + adapter->pending_thread_intr |= F_PL_INTR_SGE_ERR; |
|---|
| 185 | + pr_alert("%s: PCI error encountered.\n", adapter->name); |
|---|
| 186 | + return true; |
|---|
| 183 | 187 | } |
|---|
| 184 | | - return 0; |
|---|
| 188 | + return false; |
|---|
| 185 | 189 | } |
|---|
| 186 | 190 | |
|---|
| 187 | 191 | #ifdef CONFIG_CHELSIO_T1_1G |
|---|
| .. | .. |
|---|
| 210 | 214 | /* |
|---|
| 211 | 215 | * Slow path interrupt handler for FPGAs. |
|---|
| 212 | 216 | */ |
|---|
| 213 | | -static int fpga_slow_intr(adapter_t *adapter) |
|---|
| 217 | +static irqreturn_t fpga_slow_intr(adapter_t *adapter) |
|---|
| 214 | 218 | { |
|---|
| 215 | 219 | u32 cause = readl(adapter->regs + A_PL_CAUSE); |
|---|
| 220 | + irqreturn_t ret = IRQ_NONE; |
|---|
| 216 | 221 | |
|---|
| 217 | 222 | cause &= ~F_PL_INTR_SGE_DATA; |
|---|
| 218 | | - if (cause & F_PL_INTR_SGE_ERR) |
|---|
| 219 | | - t1_sge_intr_error_handler(adapter->sge); |
|---|
| 223 | + if (cause & F_PL_INTR_SGE_ERR) { |
|---|
| 224 | + if (t1_sge_intr_error_handler(adapter->sge)) |
|---|
| 225 | + ret = IRQ_WAKE_THREAD; |
|---|
| 226 | + } |
|---|
| 220 | 227 | |
|---|
| 221 | 228 | if (cause & FPGA_PCIX_INTERRUPT_GMAC) |
|---|
| 222 | 229 | fpga_phy_intr_handler(adapter); |
|---|
| .. | .. |
|---|
| 231 | 238 | /* Clear TP interrupt */ |
|---|
| 232 | 239 | writel(tp_cause, adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE); |
|---|
| 233 | 240 | } |
|---|
| 234 | | - if (cause & FPGA_PCIX_INTERRUPT_PCIX) |
|---|
| 235 | | - t1_pci_intr_handler(adapter); |
|---|
| 241 | + if (cause & FPGA_PCIX_INTERRUPT_PCIX) { |
|---|
| 242 | + if (t1_pci_intr_handler(adapter)) |
|---|
| 243 | + ret = IRQ_WAKE_THREAD; |
|---|
| 244 | + } |
|---|
| 236 | 245 | |
|---|
| 237 | 246 | /* Clear the interrupts just processed. */ |
|---|
| 238 | 247 | if (cause) |
|---|
| 239 | 248 | writel(cause, adapter->regs + A_PL_CAUSE); |
|---|
| 240 | 249 | |
|---|
| 241 | | - return cause != 0; |
|---|
| 250 | + if (ret != IRQ_NONE) |
|---|
| 251 | + return ret; |
|---|
| 252 | + |
|---|
| 253 | + return cause == 0 ? IRQ_NONE : IRQ_HANDLED; |
|---|
| 242 | 254 | } |
|---|
| 243 | 255 | #endif |
|---|
| 244 | 256 | |
|---|
| .. | .. |
|---|
| 842 | 854 | /* |
|---|
| 843 | 855 | * Slow path interrupt handler for ASICs. |
|---|
| 844 | 856 | */ |
|---|
| 845 | | -static int asic_slow_intr(adapter_t *adapter) |
|---|
| 857 | +static irqreturn_t asic_slow_intr(adapter_t *adapter) |
|---|
| 846 | 858 | { |
|---|
| 847 | 859 | u32 cause = readl(adapter->regs + A_PL_CAUSE); |
|---|
| 860 | + irqreturn_t ret = IRQ_HANDLED; |
|---|
| 848 | 861 | |
|---|
| 849 | 862 | cause &= adapter->slow_intr_mask; |
|---|
| 850 | 863 | if (!cause) |
|---|
| 851 | | - return 0; |
|---|
| 852 | | - if (cause & F_PL_INTR_SGE_ERR) |
|---|
| 853 | | - t1_sge_intr_error_handler(adapter->sge); |
|---|
| 864 | + return IRQ_NONE; |
|---|
| 865 | + if (cause & F_PL_INTR_SGE_ERR) { |
|---|
| 866 | + if (t1_sge_intr_error_handler(adapter->sge)) |
|---|
| 867 | + ret = IRQ_WAKE_THREAD; |
|---|
| 868 | + } |
|---|
| 854 | 869 | if (cause & F_PL_INTR_TP) |
|---|
| 855 | 870 | t1_tp_intr_handler(adapter->tp); |
|---|
| 856 | 871 | if (cause & F_PL_INTR_ESPI) |
|---|
| 857 | 872 | t1_espi_intr_handler(adapter->espi); |
|---|
| 858 | | - if (cause & F_PL_INTR_PCIX) |
|---|
| 859 | | - t1_pci_intr_handler(adapter); |
|---|
| 860 | | - if (cause & F_PL_INTR_EXT) |
|---|
| 861 | | - t1_elmer0_ext_intr(adapter); |
|---|
| 873 | + if (cause & F_PL_INTR_PCIX) { |
|---|
| 874 | + if (t1_pci_intr_handler(adapter)) |
|---|
| 875 | + ret = IRQ_WAKE_THREAD; |
|---|
| 876 | + } |
|---|
| 877 | + if (cause & F_PL_INTR_EXT) { |
|---|
| 878 | + /* Wake the threaded interrupt to handle external interrupts as |
|---|
| 879 | + * we require a process context. We disable EXT interrupts in |
|---|
| 880 | + * the interim and let the thread reenable them when it's done. |
|---|
| 881 | + */ |
|---|
| 882 | + adapter->pending_thread_intr |= F_PL_INTR_EXT; |
|---|
| 883 | + adapter->slow_intr_mask &= ~F_PL_INTR_EXT; |
|---|
| 884 | + writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA, |
|---|
| 885 | + adapter->regs + A_PL_ENABLE); |
|---|
| 886 | + ret = IRQ_WAKE_THREAD; |
|---|
| 887 | + } |
|---|
| 862 | 888 | |
|---|
| 863 | 889 | /* Clear the interrupts just processed. */ |
|---|
| 864 | 890 | writel(cause, adapter->regs + A_PL_CAUSE); |
|---|
| 865 | 891 | readl(adapter->regs + A_PL_CAUSE); /* flush writes */ |
|---|
| 866 | | - return 1; |
|---|
| 892 | + return ret; |
|---|
| 867 | 893 | } |
|---|
| 868 | 894 | |
|---|
| 869 | | -int t1_slow_intr_handler(adapter_t *adapter) |
|---|
| 895 | +irqreturn_t t1_slow_intr_handler(adapter_t *adapter) |
|---|
| 870 | 896 | { |
|---|
| 871 | 897 | #ifdef CONFIG_CHELSIO_T1_1G |
|---|
| 872 | 898 | if (!t1_is_asic(adapter)) |
|---|