#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
#include <linux/skbuff.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
#include <net/dst.h>
#include <net/genetlink.h>
#define SDIO_DEVICE_ID_MARVELL_8688WLAN 0x9104
#endif
+struct compat_threaded_irq {
+ unsigned int irq;
+ irq_handler_t handler;
+ irq_handler_t thread_fn;
+ void *dev_id;
+ char wq_name[64];
+ struct workqueue_struct *wq;
+ struct work_struct work;
+};
+
/*
* kmemleak was introduced on 2.6.31, since older kernels do not have
* we simply ignore its tuning.
extern int genl_register_family_with_ops(struct genl_family *family,
struct genl_ops *ops, size_t n_ops);
+
+/* Backport threaded IRQ support */
+
+static inline
+void compat_irq_work(struct work_struct *work)
+{
+ struct compat_threaded_irq *comp = container_of(work, struct compat_threaded_irq, work);
+ comp->thread_fn(comp->irq, comp->dev_id);
+}
+
+static inline
+irqreturn_t compat_irq_dispatcher(int irq, void *dev_id)
+{
+ struct compat_threaded_irq *comp = dev_id;
+ irqreturn_t res;
+
+ res = comp->handler(irq, comp->dev_id);
+ if (res == IRQ_WAKE_THREAD) {
+ queue_work(comp->wq, &comp->work);
+ res = IRQ_HANDLED;
+ }
+
+ return res;
+}
+
+static inline
+int compat_request_threaded_irq(struct compat_threaded_irq *comp,
+ unsigned int irq,
+ irq_handler_t handler,
+ irq_handler_t thread_fn,
+ unsigned long flags,
+ const char *name,
+ void *dev_id)
+{
+ comp->irq = irq;
+ comp->handler = handler;
+ comp->thread_fn = thread_fn;
+ comp->dev_id = dev_id;
+ INIT_WORK(&comp->work, compat_irq_work);
+
+ if (!comp->wq) {
+ snprintf(comp->wq_name, sizeof(comp->wq_name),
+ "compirq/%u-%s", irq, name);
+ comp->wq = create_singlethread_workqueue(comp->wq_name);
+ if (!comp->wq) {
+ printk(KERN_ERR "Failed to create compat-threaded-IRQ workqueue %s\n",
+ comp->wq_name);
+ return -ENOMEM;
+ }
+ }
+ return request_irq(irq, compat_irq_dispatcher, flags, name, comp);
+}
+
+static inline
+void compat_free_threaded_irq(struct compat_threaded_irq *comp)
+{
+ free_irq(comp->irq, comp);
+}
+
+static inline
+void compat_destroy_threaded_irq(struct compat_threaded_irq *comp)
+{
+ if (comp->wq)
+ destroy_workqueue(comp->wq);
+ comp->wq = NULL;
+}
+
+static inline
+void compat_synchronize_threaded_irq(struct compat_threaded_irq *comp)
+{
+ synchronize_irq(comp->irq);
+ cancel_work_sync(&comp->work);
+}
+
+
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) */
#endif /* LINUX_26_31_COMPAT_H */
--- /dev/null
+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 2009-09-23 10:17:44.852134031 -0700
++++ b/drivers/net/wireless/b43/main.c 2009-09-23 10:21:45.887734082 -0700
+@@ -3908,8 +3908,13 @@ redo:
+ if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ 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;
+@@ -3948,9 +3953,17 @@ static int b43_wireless_core_start(struc
+ goto out;
+ }
+ } else {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+ err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
+ b43_interrupt_thread_handler,
+ IRQF_SHARED, KBUILD_MODNAME, dev);
++#else
++ err = compat_request_threaded_irq(&dev->irq_compat,
++ 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);
+ goto out;
+@@ -4656,6 +4669,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->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 2009-09-23 10:17:59.383718279 -0700
++++ b/drivers/net/wireless/b43/b43.h 2009-09-23 10:22:17.127771634 -0700
+@@ -822,6 +822,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
+ };
+
+ static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)