diff options
Diffstat (limited to 'patches/collateral-evolutions')
-rw-r--r-- | patches/collateral-evolutions/network/75-cw1200-workqueues/cw1200_workqueues.patch | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/patches/collateral-evolutions/network/75-cw1200-workqueues/cw1200_workqueues.patch b/patches/collateral-evolutions/network/75-cw1200-workqueues/cw1200_workqueues.patch new file mode 100644 index 00000000..3bf31970 --- /dev/null +++ b/patches/collateral-evolutions/network/75-cw1200-workqueues/cw1200_workqueues.patch @@ -0,0 +1,133 @@ +diff --git a/drivers/net/wireless/cw1200/bh.c b/drivers/net/wireless/cw1200/bh.c +index c1ec2a4..5dcbb4e 100644 +--- a/drivers/net/wireless/cw1200/bh.c ++++ b/drivers/net/wireless/cw1200/bh.c +@@ -48,16 +48,22 @@ enum cw1200_bh_pm_state { + typedef int (*cw1200_wsm_handler)(struct cw1200_common *priv, + u8 *data, size_t size); + ++#ifndef CW1200_USE_COMPAT_KTHREAD + static void cw1200_bh_work(struct work_struct *work) + { + struct cw1200_common *priv = + container_of(work, struct cw1200_common, bh_work); + cw1200_bh(priv); + } ++#endif + + int cw1200_register_bh(struct cw1200_common *priv) + { + int err = 0; ++#ifdef CW1200_USE_COMPAT_KTHREAD ++ struct sched_param param = { .sched_priority = 1 }; ++ BUG_ON(priv->bh_thread); ++#else + /* Realtime workqueue */ + priv->bh_workqueue = alloc_workqueue("cw1200_bh", + WQ_MEM_RECLAIM | WQ_HIGHPRI +@@ -67,6 +73,7 @@ int cw1200_register_bh(struct cw1200_common *priv) + return -ENOMEM; + + INIT_WORK(&priv->bh_work, cw1200_bh_work); ++#endif + + pr_debug("[BH] register.\n"); + +@@ -81,20 +88,44 @@ int cw1200_register_bh(struct cw1200_common *priv) + init_waitqueue_head(&priv->bh_wq); + init_waitqueue_head(&priv->bh_evt_wq); + ++#ifdef CW1200_USE_COMPAT_KTHREAD ++ priv->bh_thread = kthread_create(&cw1200_bh, priv, "cw1200_bh"); ++ if (IS_ERR(priv->bh_thread)) { ++ err = PTR_ERR(priv->bh_thread); ++ priv->bh_thread = NULL; ++ } else { ++ WARN_ON(sched_setscheduler(priv->bh_thread, ++ SCHED_FIFO, ¶m)); ++ wake_up_process(priv->bh_thread); ++ } ++#else + err = !queue_work(priv->bh_workqueue, &priv->bh_work); + WARN_ON(err); ++#endif ++ + return err; + } + + void cw1200_unregister_bh(struct cw1200_common *priv) + { ++#ifdef CW1200_USE_COMPAT_KTHREAD ++ struct task_struct *thread = priv->bh_thread; ++ if (WARN_ON(!thread)) ++ return; ++#endif ++ + atomic_add(1, &priv->bh_term); + wake_up(&priv->bh_wq); + ++#ifdef CW1200_USE_COMPAT_KTHREAD ++ kthread_stop(thread); ++ priv->bh_thread = NULL; ++#else + flush_workqueue(priv->bh_workqueue); + + destroy_workqueue(priv->bh_workqueue); + priv->bh_workqueue = NULL; ++#endif + + pr_debug("[BH] unregistered.\n"); + } +@@ -614,6 +645,16 @@ static int cw1200_bh(void *arg) + pr_err("[BH] Fatal error, exiting.\n"); + priv->bh_error = 1; + /* TODO: schedule_work(recovery) */ ++#ifdef CW1200_USE_COMPAT_KTHREAD ++ for (;;) { ++ int status = wait_event_interruptible(priv->bh_wq, ({ ++ term = atomic_xchg(&priv->bh_term, 0); ++ (term); ++ })); ++ if (status || term) ++ break; ++ } ++#endif + } + return 0; + } +diff --git a/drivers/net/wireless/cw1200/cw1200.h b/drivers/net/wireless/cw1200/cw1200.h +index 1ad7d36..300dbbb 100644 +--- a/drivers/net/wireless/cw1200/cw1200.h ++++ b/drivers/net/wireless/cw1200/cw1200.h +@@ -23,12 +23,18 @@ + #include <linux/workqueue.h> + #include <net/mac80211.h> + ++#include <linux/version.h> ++ + #include "queue.h" + #include "wsm.h" + #include "scan.h" + #include "txrx.h" + #include "pm.h" + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)) ++#define CW1200_USE_COMPAT_KTHREAD ++#endif ++ + /* Forward declarations */ + struct hwbus_ops; + struct task_struct; +@@ -190,8 +196,12 @@ struct cw1200_common { + atomic_t bh_term; + atomic_t bh_suspend; + ++#ifdef CW1200_USE_COMPAT_KTHREAD ++ struct task_struct *bh_thread; ++#else + struct workqueue_struct *bh_workqueue; + struct work_struct bh_work; ++#endif + + int bh_error; + wait_queue_head_t bh_wq; |