patch-2.2.14 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
- Lines: 403
- Date:
Tue Jan 4 10:12:16 2000
- Orig file:
v2.2.13/linux/drivers/isdn/isdn_net.c
- Orig date:
Tue Jan 4 11:10:35 2000
diff -u --recursive --new-file v2.2.13/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.92 1999/09/13 23:25:17 he Exp $
+/* $Id: isdn_net.c,v 1.95 1999/10/27 21:21:17 detabc Exp $
* Linux ISDN subsystem, network interfaces and related functions (linklevel).
*
@@ -21,6 +21,24 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_net.c,v $
+ * Revision 1.95 1999/10/27 21:21:17 detabc
+ * Added support for building logically-bind-group's per interface.
+ * usefull for outgoing call's with more then one isdn-card.
+ *
+ * Switchable support to dont reset the hangup-timeout for
+ * receive frames. Most part's of the timru-rules for receiving frames
+ * are now obsolete. If the input- or forwarding-firewall deny
+ * the frame, the line will be not hold open.
+ *
+ * Revision 1.94 1999/10/02 11:07:02 he
+ * Changed tbusy logic in indn_net.c
+ *
+ * Revision 1.93 1999/09/23 22:22:41 detabc
+ * added tcp-keepalive-detect with local response (ipv4 only)
+ * added host-only-interface support
+ * (source ipaddr == interface ipaddr) (ipv4 only)
+ * ok with kernel 2.3.18 and 2.2.12
+ *
* Revision 1.92 1999/09/13 23:25:17 he
* serialized xmitting frames from isdn_ppp and BSENT statcallb
*
@@ -375,6 +393,49 @@
#endif
+#ifndef ISDN_NEW_TBUSY
+#define ISDN_NEW_TBUSY
+#endif
+#ifdef ISDN_NEW_TBUSY
+/*
+ * Outline of new tbusy handling:
+ *
+ * Old method, roughly spoken, consisted of setting tbusy when entering
+ * isdn_net_start_xmit() and at several other locations and clearing
+ * it from isdn_net_start_xmit() thread when sending was successful.
+ *
+ * With 2.3.x multithreaded network core, to prevent problems, tbusy should
+ * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
+ * condition is detected. Other threads (in particular isdn_net_stat_callb())
+ * are only allowed to clear tbusy.
+ *
+ * -HE
+ */
+
+/*
+ * Tell upper layers that the network device is ready to xmit more frames.
+ */
+static void __inline__ isdn_net_dev_xon(struct device * dev)
+{
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+}
+
+static void __inline__ isdn_net_lp_xon(isdn_net_local * lp)
+{
+ lp->netdev->dev.tbusy = 0;
+ if(lp->master) lp->master->tbusy = 0;
+ mark_bh(NET_BH);
+}
+
+/*
+ * Ask upper layers to temporarily cease passing us more xmit frames.
+ */
+static void __inline__ isdn_net_dev_xoff(struct device * dev)
+{
+ dev->tbusy = 1;
+}
+#endif
/* Prototypes */
@@ -382,7 +443,7 @@
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.92 $";
+char *isdn_net_revision = "$Revision: 1.95 $";
/*
* Code for raw-networking over ISDN
@@ -424,7 +485,11 @@
save_flags(flags);
cli(); /* Avoid glitch on writes to CMD regs */
dev->interrupt = 0;
+#ifdef ISDN_NEW_TBUSY
+ isdn_net_dev_xon(dev);
+#else
dev->tbusy = 0;
+#endif
#ifdef CONFIG_ISDN_X25
if( cprot && cprot -> pops && dops )
cprot -> pops -> restart ( cprot, dev, dops );
@@ -638,13 +703,19 @@
mdev = &lp->netdev->dev;
if (!isdn_net_send_skb(mdev, lp, lp->sav_skb)) {
lp->sav_skb = NULL;
+#ifndef ISDN_NEW_TBUSY
mark_bh(NET_BH);
+#endif
} else {
return 1;
}
}
+#ifdef ISDN_NEW_TBUSY
+ isdn_net_lp_xon(lp);
+#else
if (test_and_clear_bit(0, (void *) &(p->dev.tbusy)))
mark_bh(NET_BH);
+#endif
}
return 1;
case ISDN_STAT_DCONN:
@@ -727,7 +798,6 @@
lp->dialstarted = 0;
lp->dialwait_timer = 0;
- /* Immediately send first skb to speed up arp */
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
isdn_ppp_wakeup_daemon(lp);
@@ -738,11 +808,15 @@
if( pops->connect_ind)
pops->connect_ind(cprot);
#endif /* CONFIG_ISDN_X25 */
+ /* Immediately send first skb to speed up arp */
if (lp->first_skb) {
if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
lp->first_skb = NULL;
}
+#ifdef ISDN_NEW_TBUSY
+ if(! lp->first_skb) isdn_net_lp_xon(lp);
+#else
else {
/*
* dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb).
@@ -751,6 +825,7 @@
lp->netdev->dev.tbusy = 0;
mark_bh(NET_BH);
}
+#endif /* ISDN_NEW_TBUSY */
return 1;
}
break;
@@ -1185,6 +1260,7 @@
break;
}
printk(KERN_INFO "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
+
p[12], p[13], p[14], p[15],
p[16], p[17], p[18], p[19],
addinfo);
@@ -1203,8 +1279,12 @@
* standard send-routine, else send directly.
*
* Return: 0 on success, !0 on failure.
+ */
+#ifndef ISDN_NEW_TBUSY
+/*
* Side-effects: ndev->tbusy is cleared on success.
*/
+#endif
int
isdn_net_send_skb(struct device *ndev, isdn_net_local * lp,
struct sk_buff *skb)
@@ -1215,13 +1295,17 @@
ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
if (ret == len) {
lp->transcount += len;
+#ifndef ISDN_NEW_TBUSY
clear_bit(0, (void *) &(ndev->tbusy));
+#endif
return 0;
}
if (ret < 0) {
dev_kfree_skb(skb);
lp->stats.tx_errors++;
+#ifndef ISDN_NEW_TBUSY
clear_bit(0, (void *) &(ndev->tbusy));
+#endif
return 0;
}
return 1;
@@ -1267,7 +1351,11 @@
if (lp->srobin == ndev)
ret = isdn_net_send_skb(ndev, lp, skb);
else
+#ifdef ISDN_NEW_TBUSY
+ ret = isdn_net_start_xmit(skb, lp->srobin);
+#else
ret = ndev->tbusy = isdn_net_start_xmit(skb, lp->srobin);
+#endif
lp->srobin = (slp->slave) ? slp->slave : ndev;
slp = (isdn_net_local *) (lp->srobin->priv);
if (!((slp->flags & ISDN_NET_CONNECTED) && (slp->dialstate == 0)))
@@ -1327,8 +1415,13 @@
if (!lp->dialstate)
lp->stats.tx_errors++;
ndev->trans_start = jiffies;
+#ifdef ISDN_NEW_TBUSY
+ isdn_net_dev_xon(ndev);
+#endif
}
+#ifndef ISDN_NEW_TBUSY
ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */
+#endif
#ifdef CONFIG_ISDN_X25
/* At this point hard_start_xmit() passes control to the encapsulation
protocol (if present).
@@ -1342,7 +1435,11 @@
when a dl_establish request is received from the upper layer.
*/
if( cprot ) {
- return cprot -> pops -> encap_and_xmit ( cprot , skb);
+ int ret = cprot -> pops -> encap_and_xmit ( cprot , skb);
+#ifdef ISDN_NEW_TBUSY
+ if(ret) isdn_net_dev_xoff(ndev);
+#endif
+ return ret;
} else
#endif
/* auto-dialing xmit function */
@@ -1361,7 +1458,9 @@
if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
dev_kfree_skb(skb);
+#ifndef ISDN_NEW_TBUSY
ndev->tbusy = 0;
+#endif
return 0;
}
if (lp->phone[1]) {
@@ -1377,7 +1476,9 @@
if(jiffies < lp->dialwait_timer) {
isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
dev_kfree_skb(skb);
+#ifndef ISDN_NEW_TBUSY
ndev->tbusy = 0;
+#endif
restore_flags(flags);
return 0;
} else
@@ -1386,22 +1487,28 @@
/* Grab a free ISDN-Channel */
if (((chi =
- isdn_get_free_channel(ISDN_USAGE_NET,
- lp->l2_proto,
- lp->l3_proto,
- lp->pre_device,
- lp->pre_channel)) < 0) &&
+ isdn_get_free_channel(
+ ISDN_USAGE_NET,
+ lp->l2_proto,
+ lp->l3_proto,
+ lp->pre_device,
+ lp->pre_channel)
+ ) < 0) &&
((chi =
- isdn_get_free_channel(ISDN_USAGE_NET,
- lp->l2_proto,
- lp->l3_proto,
- lp->pre_device,
- lp->pre_channel^1)) < 0)) {
+ isdn_get_free_channel(
+ ISDN_USAGE_NET,
+ lp->l2_proto,
+ lp->l3_proto,
+ lp->pre_device,
+ lp->pre_channel^1)
+ ) < 0)) {
restore_flags(flags);
isdn_net_unreachable(ndev, skb,
"No channel");
dev_kfree_skb(skb);
+#ifndef ISDN_NEW_TBUSY
ndev->tbusy = 0;
+#endif
return 0;
}
/* Log packet, which triggered dialing */
@@ -1421,6 +1528,9 @@
}
restore_flags(flags);
isdn_net_dial(); /* Initiate dialing */
+#ifdef ISDN_NEW_TBUSY
+ isdn_net_dev_xoff(ndev);
+#endif
return 1; /* let upper layer requeue skb packet */
}
#endif
@@ -1434,7 +1544,9 @@
}
lp->first_skb = skb;
/* Initiate dialing */
+#ifndef ISDN_NEW_TBUSY
ndev->tbusy = 0;
+#endif
restore_flags(flags);
isdn_net_dial();
return 0;
@@ -1442,21 +1554,37 @@
isdn_net_unreachable(ndev, skb,
"No phone number");
dev_kfree_skb(skb);
+#ifndef ISDN_NEW_TBUSY
ndev->tbusy = 0;
+#endif
return 0;
}
} else {
- /* Connection is established, try sending */
+ /* Device is connected to an ISDN channel */
ndev->trans_start = jiffies;
if (!lp->dialstate) {
+ /* ISDN connection is established, try sending */
+ int ret;
if (lp->first_skb) {
- if (isdn_net_xmit(ndev, lp, lp->first_skb))
+ if (isdn_net_xmit(ndev, lp, lp->first_skb)){
+#ifdef ISDN_NEW_TBUSY
+ isdn_net_dev_xoff(ndev);
+#endif
return 1;
+}
lp->first_skb = NULL;
}
- return (isdn_net_xmit(ndev, lp, skb));
+ ret = (isdn_net_xmit(ndev, lp, skb));
+#ifdef ISDN_NEW_TBUSY
+ if(ret) isdn_net_dev_xoff(ndev);
+#endif
+ return ret;
} else
+#ifdef ISDN_NEW_TBUSY
+ isdn_net_dev_xoff(ndev);
+#else
ndev->tbusy = 1;
+#endif
}
}
return 1;
@@ -2068,7 +2196,6 @@
isdn_net_phone *n;
ulong flags;
char nr[32];
-
/* Search name in netdev-chain */
save_flags(flags);
cli();
@@ -2280,10 +2407,15 @@
lp->name, nr, eaz);
if (lp->phone[1]) {
/* Grab a free ISDN-Channel */
- if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
+ if ((chi =
+ isdn_get_free_channel(
+ ISDN_USAGE_NET,
+ lp->l2_proto,
lp->l3_proto,
- lp->pre_device,
- lp->pre_channel)) < 0) {
+ lp->pre_device,
+ lp->pre_channel)
+ ) < 0) {
+
printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
restore_flags(flags);
return 0;
@@ -2390,10 +2522,14 @@
cli();
/* Grab a free ISDN-Channel */
- if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
- lp->l3_proto,
- lp->pre_device,
- lp->pre_channel)) < 0) {
+ if ((chi =
+ isdn_get_free_channel(
+ ISDN_USAGE_NET,
+ lp->l2_proto,
+ lp->l3_proto,
+ lp->pre_device,
+ lp->pre_channel)
+ ) < 0) {
printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
restore_flags(flags);
return -EAGAIN;
@@ -3153,4 +3289,3 @@
restore_flags(flags);
return 0;
}
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)