summaryrefslogtreecommitdiff
path: root/drivers/dahdi/wctdm24xxp/base.c
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-08-30 16:37:52 +0000
committerShaun Ruffell <sruffell@digium.com>2011-08-30 16:37:52 +0000
commitb4c7afd9bac6f0dd0cc5155274234c24bbc80fdc (patch)
tree6a99db709172e552929a668aa9ffd24b7b37e330 /drivers/dahdi/wctdm24xxp/base.c
parentfc4cfefb5ce51a783f56375da400f3063984facb (diff)
wctdm24xxp: Introduce bg_create/bg_join.
Create a generic facility to spawn tasks to run in parallel. There are interfaces already in the kernel for doing this, but they are not supported on the full range of kernels that DAHDI must support. This will be used to identify and configure FXS/FXO/B400M/VPM modules in parallel. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10159 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/wctdm24xxp/base.c')
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index 316d79d..fadce28 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -310,6 +310,101 @@ static inline __attribute_const__ int VPM_CMD_BYTE(int timeslot, int bit)
return ((((timeslot) & 0x3) * 3 + (bit)) * 7) + ((timeslot) >> 2);
}
+typedef int (*bg_work_func_t)(struct wctdm *wc, unsigned long data);
+
+struct bg {
+ struct workqueue_struct *wq;
+ struct work_struct work;
+ struct completion complete;
+ struct wctdm *wc;
+ bg_work_func_t fn;
+ unsigned long param;
+ int ret;
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+static void bg_work_func(void *data)
+{
+ struct bg *bg = data;
+#else
+static void bg_work_func(struct work_struct *work)
+{
+ struct bg *bg = container_of(work, struct bg, work);
+#endif
+ bg->ret = bg->fn(bg->wc, bg->param);
+ complete(&bg->complete);
+}
+
+/**
+ * bg_create - Call a function running in a background thread.
+ * @wc: The board structure passed to fn
+ * @fn: The function to run in it's own thread.
+ * @parma: An extra parameter to pass to the fn.
+ *
+ * Returns NULL if the thread could not be created, otherwise a pointer to be
+ * passed to bg_join in order to get the return value.
+ *
+ * The function 'fn' will be run in a new thread. The return value is the
+ * return from the bg_join function.
+ *
+ * This would probably be best served by concurrency managed workqueues before
+ * merging, but this will at least work on the older kernels tht DAHDI
+ * supports.
+ */
+static struct bg *
+bg_create(struct wctdm *wc, bg_work_func_t fn, unsigned long param)
+{
+ struct bg *bg;
+
+ bg = kzalloc(sizeof(*bg), GFP_KERNEL);
+ if (!bg)
+ return NULL;
+
+ bg->wq = create_singlethread_workqueue("wctdm_bg");
+ if (!bg->wq) {
+ kfree(bg);
+ return NULL;
+ }
+
+ init_completion(&bg->complete);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+ INIT_WORK(&bg->work, bg_work_func, bg);
+#else
+ INIT_WORK(&bg->work, bg_work_func);
+#endif
+
+ bg->wc = wc;
+ bg->fn = fn;
+ bg->param = param;
+
+ queue_work(bg->wq, &bg->work);
+
+ return bg;
+}
+
+/**
+ * bg_join - Wait for a background function to complete and get the result.
+ * @bg: Pointer returned from the bg_create call.
+ *
+ * Returns the result of the function passed to bg_create.
+ */
+static int bg_join(struct bg *bg)
+{
+ int ret = -ERESTARTSYS;
+
+ if (unlikely(!bg))
+ return -EINVAL;
+
+ while (ret)
+ ret = wait_for_completion_interruptible(&bg->complete);
+
+ ret = bg->ret;
+ destroy_workqueue(bg->wq);
+ kfree(bg);
+
+ return ret;
+}
+
static void
setchanconfig_from_state(struct vpmadt032 *vpm, int channel,
GpakChannelConfig_t *chanconfig)