patch-pre2.0.6 linux/drivers/isdn/isdn_net.c

Next file: linux/drivers/isdn/isdn_ppp.c
Previous file: linux/drivers/isdn/isdn_common.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file pre2.0.5/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.5 1996/04/20 16:28:38 fritz Exp $
+/* $Id: isdn_net.c,v 1.11 1996/05/18 01:36:59 fritz Exp $
  *
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
@@ -21,6 +21,25 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_net.c,v $
+ * Revision 1.11  1996/05/18 01:36:59  fritz
+ * Added spelling corrections and some minor changes
+ * to stay in sync with kernel.
+ *
+ * Revision 1.10  1996/05/17 03:49:01  fritz
+ * Some cleanup.
+ *
+ * Revision 1.9  1996/05/06 11:34:57  hipp
+ * fixed a few bugs
+ *
+ * Revision 1.8  1996/04/30 21:04:40  fritz
+ * Test commit
+ *
+ * Revision 1.7  1996/04/30 11:10:42  fritz
+ * Added Michael's ippp-bind patch.
+ *
+ * Revision 1.6  1996/04/30 09:34:35  fritz
+ * Removed compatibility-macros.
+ *
  * Revision 1.5  1996/04/20 16:28:38  fritz
  * Made more parameters of the dial statemachine user-configurable and
  * added hangup after dial for more reliability using callback.
@@ -55,9 +74,7 @@
  *
  */
 
-#ifndef STANDALONE
 #include <linux/config.h>
-#endif
 #define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/isdn.h>
@@ -79,7 +96,9 @@
 static int isdn_net_start_xmit(struct sk_buff *, struct device *);
 static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
  
-char *isdn_net_revision = "$Revision: 1.5 $";
+extern void dev_purge_queues(struct device *dev);	/* move this to net/core/dev.c */
+
+char *isdn_net_revision = "$Revision: 1.11 $";
 
  /*
   * Code for raw-networking over ISDN
@@ -143,6 +162,32 @@
 }
 
 /*
+ * unbind a net-interface (resets interface after an error)
+ */
+static void
+isdn_net_unbind_channel(isdn_net_local * lp)
+{
+	ulong flags;
+
+	save_flags(flags);
+	cli();
+        if (lp->first_skb) {
+                dev_kfree_skb(lp->first_skb,FREE_WRITE);
+                lp->first_skb = NULL;
+        }
+	dev_purge_queues(&lp->netdev->dev);
+	lp->dialstate = 0;
+	dev->rx_netdev[isdn_dc2minor(lp->isdn_device,lp->isdn_channel)] = NULL;
+	dev->st_netdev[isdn_dc2minor(lp->isdn_device,lp->isdn_channel)] = NULL;
+	isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
+	lp->flags &= ~ISDN_NET_CONNECTED;
+	lp->isdn_device = -1;
+	lp->isdn_channel = -1;
+
+        restore_flags(flags);
+}
+
+/*
  * Perform auto-hangup and cps-calculation for net-interfaces.
  *
  * auto-hangup:
@@ -232,6 +277,8 @@
 				/* Either D-Channel-hangup or error during dialout */
 				if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
 					lp->flags &= ~ISDN_NET_CONNECTED;
+					if(lp->first_skb)
+						dev_kfree_skb(lp->first_skb,FREE_WRITE);
 					isdn_free_channel(lp->isdn_device, lp->isdn_channel,
                                                           ISDN_USAGE_NET);
 #ifdef CONFIG_ISDN_PPP
@@ -541,6 +588,7 @@
                 dev_kfree_skb(lp->first_skb,FREE_WRITE);
                 lp->first_skb = NULL;
         }
+	dev_purge_queues(d);
 	if (lp->flags & ISDN_NET_CONNECTED) {
 		printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
 		lp->dialstate = 0;
@@ -695,8 +743,10 @@
 
 	/* For the other encaps the header has already been built */
 #ifdef CONFIG_ISDN_PPP
-	if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
-		return (isdn_ppp_xmit(skb, ndev));
+	if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
+		ndev->tbusy = ret = isdn_ppp_xmit(skb, ndev);
+		return ret;
+	}
 #endif		
 	/* Reset hangup-timeout */
 	lp->huptimer = 0;
@@ -755,7 +805,6 @@
 {
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 
-
 	if (ndev->tbusy) {
 		if (jiffies - ndev->trans_start < 20)
 			return 1;
@@ -795,6 +844,8 @@
                                                "isdn_net_start_xmit: No channel for %s\n",
                                                ndev->name);
 					restore_flags(flags);
+		/* we probably should drop the skb here and return 0 to omit
+		   'socket destroy delayed' messages */
 					return 1;
 				}
                                 /* Log packet, which triggered dialing */
@@ -805,15 +856,18 @@
 				/* Connect interface with channel */
 				isdn_net_bind_channel(lp, chi);
 #ifdef CONFIG_ISDN_PPP
-				if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+				if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
+					/* no 'first_skb' handling for syncPPP */
 					if (isdn_ppp_bind(lp) < 0) {
-						lp->dialstate = 0;
-						isdn_free_channel(lp->isdn_device,
-                                                                  lp->isdn_channel,
-                                                                  ISDN_USAGE_NET);
+						lp->first_skb = skb;	/* net_unbind will free skb */
+						isdn_net_unbind_channel(lp);
                                                 restore_flags(flags);
-						return 1;
+						return 0;	/* STN (skb to nirvana) ;) */
 					}
+	                                isdn_net_dial();	/* Initiate dialing */
+					restore_flags(flags);
+					return 1;	/* let upper layer requeue skb packet */
+				}
 #endif
                                 /* remember first skb to speed up arp
                                  * when using encap ETHER
@@ -1630,9 +1684,7 @@
 #ifdef CONFIG_ISDN_PPP
 						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
 							if (isdn_ppp_bind(lp) < 0) {
-								isdn_free_channel(p->local.isdn_device, p->local.isdn_channel,
-									     ISDN_USAGE_NET);
-								lp->dialstate = 0;
+								isdn_net_unbind_channel(lp);
 								restore_flags(flags);
 								return 0;
 							}
@@ -1647,15 +1699,6 @@
 				} else {
 					printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,
 					       eaz);
-#if 0
-/* why is this a CONFIG_ISDN_PPP feature ??? */
-#ifdef CONFIG_ISDN_PPP
-					if (p->local.isdn_device != -1) {
-						isdn_free_channel(p->local.isdn_device, p->local.isdn_channel,
-							 ISDN_USAGE_NET);
-					}
-#endif
-#endif
 					/* if this interface is dialing, it does it probably on a different
 					   device, so free this device */
 					if ((p->local.dialstate == 4) || (p->local.dialstate == 12))
@@ -1669,6 +1712,7 @@
 					p->local.isdn_device = di;
 					p->local.isdn_channel = ch;
 					p->local.ppp_minor = -1;
+					p->local.pppbind = -1;
 					p->local.flags |= ISDN_NET_CONNECTED;
 					p->local.dialstate = 7;
 					p->local.dtimer = 0;
@@ -1679,9 +1723,7 @@
 #ifdef CONFIG_ISDN_PPP
 					if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
 						if (isdn_ppp_bind(lp) < 0) {
-							isdn_free_channel(p->local.isdn_device, p->local.isdn_channel,
-							 ISDN_USAGE_NET);
-							lp->dialstate = 0;
+							isdn_net_unbind_channel(lp);
 							restore_flags(flags);
 							return 0;
 						}
@@ -1745,9 +1787,9 @@
 #ifdef CONFIG_ISDN_PPP
 			if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
 				if (isdn_ppp_bind(lp) < 0) {
-					lp->dialstate = 0;
-					isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
-					return 1;
+					isdn_net_unbind_channel(lp);
+					restore_flags(flags);
+					return -EAGAIN;
 				}
 #endif
 			/* Initiate dialing */
@@ -1841,6 +1883,7 @@
 	netdev->local.pre_channel = -1;
 	netdev->local.exclusive = -1;
 	netdev->local.ppp_minor = -1;
+	netdev->local.pppbind = -1;
 	netdev->local.l2_proto = ISDN_PROTO_L2_X75I;
 	netdev->local.l3_proto = ISDN_PROTO_L3_TRANS;
 	netdev->local.slavedelay = 10 * HZ;
@@ -1987,6 +2030,7 @@
                 p->local.cbdelay     = cfg->cbdelay;
                 p->local.dialmax     = cfg->dialmax;
 		p->local.slavedelay  = cfg->slavedelay * HZ;
+		p->local.pppbind     = cfg->pppbind;
 		if (cfg->secure)
 			p->local.flags |= ISDN_NET_SECURE;
 		else
@@ -2062,14 +2106,16 @@
 		cfg->l3_proto = p->local.l3_proto;
 		cfg->p_encap = p->local.p_encap;
 		cfg->secure = (p->local.flags & ISDN_NET_SECURE) ? 1 : 0;
-		cfg->callback = (p->local.flags & ISDN_NET_CALLBACK) ? 1 : 0;
-		cfg->callback = (p->local.flags & ISDN_NET_CBOUT) ? 2 : 0;
+		cfg->callback = 0;
+                if (p->local.flags & ISDN_NET_CALLBACK)
+                        cfg->callback = (p->local.flags & ISDN_NET_CBOUT)?2:1;
 		cfg->cbhup = (p->local.flags & ISDN_NET_CBHUP) ? 1 : 0;
 		cfg->chargehup = (p->local.hupflags & 4) ? 1 : 0;
 		cfg->ihup = (p->local.hupflags & 8) ? 1 : 0;
                 cfg->cbdelay = p->local.cbdelay;
                 cfg->dialmax = p->local.dialmax;
 		cfg->slavedelay = p->local.slavedelay / HZ;
+		cfg->pppbind = p->local.pppbind;
 		if (p->local.slave)
 			strcpy(cfg->slave, ((isdn_net_local *) p->local.slave->priv)->name);
 		else
@@ -2287,7 +2333,7 @@
 	restore_flags(flags);
 
 #ifdef CONFIG_ISDN_PPP
-	isdn_ppp_free_mpqueue(p);
+	isdn_ppp_free_mpqueue(p);	/* still necessary? */
 #endif
 	kfree(p);
 
@@ -2341,6 +2387,26 @@
 	restore_flags(flags);
 	return 0;
 }
+
+/* 
+ * helper function to flush device queues
+ * the better place would be net/core/dev.c
+ */
+void dev_purge_queues(struct device *dev)
+{
+	int i;
+	for(i=0;i<DEV_NUMBUFFS;i++) {
+		struct sk_buff *skb;
+		while((skb=skb_dequeue(&dev->buffs[i])))
+			if(skb->free)
+				kfree_skb(skb,FREE_WRITE);
+        }
+	
+}
+
+
+
+
 
 
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this