[svn-commits] sruffell: linux/trunk r8410 - /linux/trunk/drivers/dahdi/wcte12xp/base.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Mar 24 09:32:27 CDT 2010


Author: sruffell
Date: Wed Mar 24 09:32:23 2010
New Revision: 8410

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=8410
Log:
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.

Modified:
    linux/trunk/drivers/dahdi/wcte12xp/base.c

Modified: linux/trunk/drivers/dahdi/wcte12xp/base.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/wcte12xp/base.c?view=diff&rev=8410&r1=8409&r2=8410
==============================================================================
--- linux/trunk/drivers/dahdi/wcte12xp/base.c (original)
+++ linux/trunk/drivers/dahdi/wcte12xp/base.c Wed Mar 24 09:32:23 2010
@@ -1114,10 +1114,54 @@
 	}
 }
 
+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) {
@@ -1177,8 +1221,7 @@
 			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);




More information about the svn-commits mailing list