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

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Mar 24 10:39:08 CDT 2010


Author: sruffell
Date: Wed Mar 24 10:39:05 2010
New Revision: 8415

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=8415
Log:
wcte12xp: t1xxp_maint is also called with interrupts disabled from dahdi_ioctl

So just push all the maintenance mode processing off to the workqueue.

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=8415&r1=8414&r2=8415
==============================================================================
--- linux/trunk/drivers/dahdi/wcte12xp/base.c (original)
+++ linux/trunk/drivers/dahdi/wcte12xp/base.c Wed Mar 24 10:39:05 2010
@@ -1114,54 +1114,28 @@
 	}
 }
 
-struct maint_loopstop_work {
+struct maint_work_struct {
 	struct work_struct work;
 	struct t1 *wc;
+	int cmd;
 	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;
+static void t1xxp_maint_work(void *data)
+{
+	struct maint_work_struct *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);
+	struct maint_work_struct *w = container_of(work,
+					struct maint_work_struct, 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;
+
+	struct t1 *wc = w->wc;
+	struct dahdi_span *span = w->span;
 	int reg = 0;
-
-	if (DAHDI_MAINT_LOOPSTOP != cmd)
-		might_sleep();
+	int cmd = w->cmd;
 
 	if (wc->spantype == TYPE_E1) {
 		switch (cmd) {
@@ -1173,7 +1147,7 @@
 			t1xxp_clear_maint(span);
 			reg = t1_getreg(wc, LIM0);
 			if (reg < 0)
-				return -EIO;
+				goto cleanup;
 			t1_setreg(wc, LIM0, reg | LIM0_LL);
 			break;
 		case DAHDI_MAINT_REMOTELOOP:
@@ -1181,10 +1155,10 @@
 		case DAHDI_MAINT_LOOPDOWN:
 		case DAHDI_MAINT_LOOPSTOP:
 			t1_info(wc, "Only local loop supported in E1 mode\n");
-			return -ENOSYS;
+			goto cleanup;
 		default:
 			t1_info(wc, "Unknown E1 maint command: %d\n", cmd);
-			return -ENOSYS;
+			goto cleanup;
 		}
 	} else {
 		switch (cmd) {
@@ -1195,21 +1169,21 @@
 			t1xxp_clear_maint(span);
  			reg = t1_getreg(wc, LIM0);
 			if (reg < 0)
-				return -EIO;
+				goto cleanup;
 			t1_setreg(wc, LIM0, reg | LIM0_LL);
 			break;
  		case DAHDI_MAINT_NETWORKLINELOOP:
 			t1xxp_clear_maint(span);
  			reg = t1_getreg(wc, LIM1);
 			if (reg < 0)
-				return -EIO;
+				goto cleanup;
 			t1_setreg(wc, LIM1, reg | LIM1_RL);
  			break;
  		case DAHDI_MAINT_NETWORKPAYLOADLOOP:
 			t1xxp_clear_maint(span);
  			reg = t1_getreg(wc, LIM1);
 			if (reg < 0)
-				return -EIO;
+				goto cleanup;
 			t1_setreg(wc, LIM1, reg | (LIM1_RL | LIM1_JATT));
 			break;
 		case DAHDI_MAINT_LOOPUP:
@@ -1221,7 +1195,49 @@
 			t1_setreg(wc, 0x21, 0x60);
 			break;
 		case DAHDI_MAINT_LOOPSTOP:
-			t1xxp_maint_loopstop(wc, span);
+			t1xxp_clear_maint(w->span);
+			t1_setreg(w->wc, 0x21, 0x40);
+			break;
+		default:
+			t1_info(wc, "Unknown T1 maint command: %d\n", cmd);
+			return;
+		}
+	}
+
+cleanup:
+	kfree(w);
+	return;
+}
+
+static int t1xxp_maint(struct dahdi_span *span, int cmd)
+{
+	struct maint_work_struct *work;
+	struct t1 *wc = span->pvt;
+
+	if (wc->spantype == TYPE_E1) {
+		switch (cmd) {
+		case DAHDI_MAINT_NONE:
+		case DAHDI_MAINT_LOCALLOOP:
+			break;
+		case DAHDI_MAINT_REMOTELOOP:
+		case DAHDI_MAINT_LOOPUP:
+		case DAHDI_MAINT_LOOPDOWN:
+		case DAHDI_MAINT_LOOPSTOP:
+			t1_info(wc, "Only local loop supported in E1 mode\n");
+			return -ENOSYS;
+		default:
+			t1_info(wc, "Unknown E1 maint command: %d\n", cmd);
+			return -ENOSYS;
+		}
+	} else {
+		switch (cmd) {
+		case DAHDI_MAINT_NONE:
+		case DAHDI_MAINT_LOCALLOOP:
+		case DAHDI_MAINT_NETWORKLINELOOP:
+		case DAHDI_MAINT_NETWORKPAYLOADLOOP:
+		case DAHDI_MAINT_LOOPUP:
+		case DAHDI_MAINT_LOOPDOWN:
+		case DAHDI_MAINT_LOOPSTOP:
 			break;
 		default:
 			t1_info(wc, "Unknown T1 maint command: %d\n", cmd);
@@ -1229,6 +1245,23 @@
 		}
 	}
 
+	work = kmalloc(sizeof(*work), GFP_ATOMIC);
+	if (!work) {
+		t1_info(wc, "Failed to allocate memory for "
+			"DAHDI_MAINT_LOOPSTOP\n");
+		return -ENOMEM;
+	}
+
+	work->span = span;
+	work->wc = wc;
+	work->cmd = cmd;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+	INIT_WORK(&work->work, t1xxp_maint_work, work);
+#else
+	INIT_WORK(&work->work, t1xxp_maint_work);
+#endif
+	schedule_work(&work->work);
 	return 0;
 }
 




More information about the svn-commits mailing list