From 402616d12f9b6e87176636a3d8f83fbfe97a736f Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Wed, 24 Mar 2010 14:32:23 +0000 Subject: wcte12xp: t1xxp_maint can be called from interrupt context. Since t1xxp_maint can be called from interrupt context with the DAHDI_MAINT_LOOPSTOP cmd, push the processing of that command to a workqueue since it may sleep in the t1_getreg call. DAHDI-560. git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@8410 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- drivers/dahdi/wcte12xp/base.c | 47 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c index 1dcd4ae..b7f2c9d 100644 --- a/drivers/dahdi/wcte12xp/base.c +++ b/drivers/dahdi/wcte12xp/base.c @@ -1114,11 +1114,55 @@ static inline void t1_check_sigbits(struct t1 *wc) } } +struct maint_loopstop_work { + struct work_struct work; + struct t1 *wc; + struct dahdi_span *span; +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void t1xxp_maint_loopstop_work(void *data) +{ + struct maint_loopstop_work *w = data; +#else +static void t1xxp_maint_loopstop_work(struct work_struct *work) +{ + struct maint_loopstop_work *w = container_of(work, struct maint_loopstop_work, work); +#endif + t1xxp_clear_maint(w->span); + t1_setreg(w->wc, 0x21, 0x40); + kfree(w); +} + +static void t1xxp_maint_loopstop(struct t1 *wc, struct dahdi_span *span) +{ + struct maint_loopstop_work *work; + + work = kmalloc(sizeof(*work), GFP_ATOMIC); + if (!work) { + t1_info(wc, "Failed to allocate memory for DAHDI_MAINT_LOOPSTOP\n"); + return; + } + + work->span = span; + work->wc = wc; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&work->work, t1xxp_maint_loopstop_work, work); +#else + INIT_WORK(&work->work, t1xxp_maint_loopstop_work); +#endif + schedule_work(&work->work); +} + static int t1xxp_maint(struct dahdi_span *span, int cmd) { struct t1 *wc = span->pvt; int reg = 0; + if (DAHDI_MAINT_LOOPSTOP != cmd) + might_sleep(); + if (wc->spantype == TYPE_E1) { switch (cmd) { case DAHDI_MAINT_NONE: @@ -1177,8 +1221,7 @@ static int t1xxp_maint(struct dahdi_span *span, int cmd) t1_setreg(wc, 0x21, 0x60); break; case DAHDI_MAINT_LOOPSTOP: - t1xxp_clear_maint(span); - t1_setreg(wc, 0x21, 0x40); + t1xxp_maint_loopstop(wc, span); break; default: t1_info(wc, "Unknown T1 maint command: %d\n", cmd); -- cgit v1.2.3