| The 2.6.31 kernel has threaded IRQ support and b43 is the first |
| wireless driver that makes use of it. To support threaded IRSs |
| on older kernels we built our own struct compat_threaded_irq |
| to queue_work() onto it as the kernel thread be running the |
| thread in process context as well. |
| |
| --- a/drivers/net/wireless/b43/main.c |
| +++ b/drivers/net/wireless/b43/main.c |
| @@ -4244,8 +4244,13 @@ redo: |
| if (b43_bus_host_is_sdio(dev->dev)) { |
| b43_sdio_free_irq(dev); |
| } else { |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + compat_synchronize_threaded_irq(&dev->irq_compat); |
| + compat_free_threaded_irq(&dev->irq_compat); |
| +#else |
| synchronize_irq(dev->dev->irq); |
| free_irq(dev->dev->irq, dev); |
| +#endif |
| } |
| mutex_lock(&wl->mutex); |
| dev = wl->current_dev; |
| @@ -4291,9 +4296,17 @@ static int b43_wireless_core_start(struc |
| goto out; |
| } |
| } else { |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + err = compat_request_threaded_irq(&dev->irq_compat, |
| + dev->dev->irq, |
| + b43_interrupt_handler, |
| + b43_interrupt_thread_handler, |
| + IRQF_SHARED, KBUILD_MODNAME, dev); |
| +#else |
| err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, |
| b43_interrupt_thread_handler, |
| IRQF_SHARED, KBUILD_MODNAME, dev); |
| +#endif |
| if (err) { |
| b43err(dev->wl, "Cannot request IRQ-%d\n", |
| dev->dev->irq); |
| @@ -5116,6 +5129,10 @@ static int b43_setup_bands(struct b43_wl |
| |
| static void b43_wireless_core_detach(struct b43_wldev *dev) |
| { |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + if (dev->dev->sdev->bus->bustype != SSB_BUSTYPE_SDIO) |
| + compat_destroy_threaded_irq(&dev->irq_compat); |
| +#endif |
| /* We release firmware that late to not be required to re-request |
| * is all the time when we reinit the core. */ |
| b43_release_firmware(dev); |
| --- a/drivers/net/wireless/b43/b43.h |
| +++ b/drivers/net/wireless/b43/b43.h |
| @@ -870,6 +870,9 @@ struct b43_wldev { |
| unsigned int tx_count; |
| unsigned int rx_count; |
| #endif |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + struct compat_threaded_irq irq_compat; |
| +#endif |
| }; |
| |
| /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */ |
| --- a/drivers/net/wireless/iwlwifi/pcie/internal.h |
| +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h |
| @@ -311,6 +311,9 @@ struct iwl_trans_pcie { |
| |
| /*protect hw register */ |
| spinlock_t reg_lock; |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + struct compat_threaded_irq irq_compat; |
| +#endif |
| }; |
| |
| /** |
| --- a/drivers/net/wireless/iwlwifi/pcie/trans.c |
| +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c |
| @@ -760,12 +760,21 @@ void iwl_trans_pcie_free(struct iwl_tran |
| { |
| struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + compat_synchronize_threaded_irq(&trans_pcie->irq_compat); |
| +#else |
| synchronize_irq(trans_pcie->pci_dev->irq); |
| +#endif |
| |
| iwl_pcie_tx_free(trans); |
| iwl_pcie_rx_free(trans); |
| |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + compat_free_threaded_irq(&trans_pcie->irq_compat); |
| + compat_destroy_threaded_irq(&trans_pcie->irq_compat); |
| +#else |
| free_irq(trans_pcie->pci_dev->irq, trans); |
| +#endif |
| iwl_pcie_free_ict(trans); |
| |
| pci_disable_msi(trans_pcie->pci_dev); |
| @@ -1553,9 +1562,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(s |
| if (iwl_pcie_alloc_ict(trans)) |
| goto out_free_cmd_pool; |
| |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + if (compat_request_threaded_irq(&trans_pcie->irq_compat, |
| + pdev->irq, iwl_pcie_isr_ict, |
| + iwl_pcie_irq_handler, |
| + IRQF_SHARED, DRV_NAME, trans)) { |
| +#else |
| if (request_threaded_irq(pdev->irq, iwl_pcie_isr_ict, |
| iwl_pcie_irq_handler, |
| IRQF_SHARED, DRV_NAME, trans)) { |
| +#endif |
| IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq); |
| goto out_free_ict; |
| } |
| --- a/drivers/net/wireless/ti/wlcore/main.c |
| +++ b/drivers/net/wireless/ti/wlcore/main.c |
| @@ -5995,14 +5995,25 @@ static void wlcore_nvs_cb(const struct f |
| wl->platform_quirks = pdata->platform_quirks; |
| wl->if_ops = pdev_data->if_ops; |
| |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) |
| + irqflags = IRQF_TRIGGER_RISING; |
| +#else |
| if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) |
| irqflags = IRQF_TRIGGER_RISING; |
| else |
| irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; |
| +#endif |
| |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + ret = compat_request_threaded_irq(&wl->irq_compat, wl->irq, |
| + wl12xx_hardirq, wlcore_irq, |
| + irqflags, |
| + pdev->name, wl); |
| +#else |
| ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq, |
| irqflags, |
| pdev->name, wl); |
| +#endif |
| if (ret < 0) { |
| wl1271_error("request_irq() failed: %d", ret); |
| goto out_free_nvs; |
| @@ -6077,7 +6088,11 @@ out_unreg: |
| wl1271_unregister_hw(wl); |
| |
| out_irq: |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + compat_free_threaded_irq(&wl->irq_compat); |
| +#else |
| free_irq(wl->irq, wl); |
| +#endif |
| |
| out_free_nvs: |
| kfree(wl->nvs); |
| @@ -6123,7 +6138,12 @@ int wlcore_remove(struct platform_device |
| disable_irq_wake(wl->irq); |
| } |
| wl1271_unregister_hw(wl); |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + compat_free_threaded_irq(&wl->irq_compat); |
| + compat_destroy_threaded_irq(&wl->irq_compat); |
| +#else |
| free_irq(wl->irq, wl); |
| +#endif |
| wlcore_free_hw(wl); |
| |
| return 0; |
| --- a/drivers/net/wireless/ti/wlcore/wlcore.h |
| +++ b/drivers/net/wireless/ti/wlcore/wlcore.h |
| @@ -175,7 +175,9 @@ struct wl1271 { |
| bool initialized; |
| struct ieee80211_hw *hw; |
| bool mac80211_registered; |
| - |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
| + struct compat_threaded_irq irq_compat; |
| +#endif |
| struct device *dev; |
| struct platform_device *pdev; |
| |