netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH][ATM]: [lec] put back pressure on network stack
@ 2004-02-25 23:51 chas williams (contractor)
  2004-02-26 20:02 ` David S. Miller
  0 siblings, 1 reply; 5+ messages in thread
From: chas williams (contractor) @ 2004-02-25 23:51 UTC (permalink / raw)
  To: davem; +Cc: netdev

the lane client doesnt put back pressure on the network
stack when one of the transmit vcc's is full.  this can
yield spurious results with certain network performance
tests.

please apply to 2.6 --thanks

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1643  -> 1.1644 
#	       net/atm/lec.h	1.7     -> 1.8    
#	       net/atm/lec.c	1.37    -> 1.38   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/02/25	chas@relax.cmf.nrl.navy.mil	1.1644
# [ATM]: [lec] put back pressure on network stack
# --------------------------------------------
#
diff -Nru a/net/atm/lec.c b/net/atm/lec.c
--- a/net/atm/lec.c	Wed Feb 25 15:16:38 2004
+++ b/net/atm/lec.c	Wed Feb 25 15:16:38 2004
@@ -67,7 +67,7 @@
                                single destination while waiting for SVC */
 
 static int lec_open(struct net_device *dev);
-static int lec_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int lec_close(struct net_device *dev);
 static struct net_device_stats *lec_get_stats(struct net_device *dev);
 static void lec_init(struct net_device *dev);
@@ -211,26 +211,34 @@
 static __inline__ void
 lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
 {
-	if (atm_may_send(vcc, skb->len)) {
-		atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
-	        ATM_SKB(skb)->vcc = vcc;
-	        ATM_SKB(skb)->atm_options = vcc->atm_options;
-		priv->stats.tx_packets++;
-		priv->stats.tx_bytes += skb->len;
-		vcc->send(vcc, skb);
-	} else {
+	ATM_SKB(skb)->vcc = vcc;
+	ATM_SKB(skb)->atm_options = vcc->atm_options;
+
+	atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
+	if (vcc->send(vcc, skb) < 0) {
 		priv->stats.tx_dropped++;
-		dev_kfree_skb(skb);
+		return;
 	}
+
+	priv->stats.tx_packets++;
+	priv->stats.tx_bytes += skb->len;
+}
+
+static void
+lec_tx_timeout(struct net_device *dev)
+{
+	printk(KERN_INFO "%s: tx timeout\n", dev->name);
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
 }
 
 static int 
-lec_send_packet(struct sk_buff *skb, struct net_device *dev)
+lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
         struct sk_buff *skb2;
         struct lec_priv *priv = (struct lec_priv *)dev->priv;
         struct lecdatahdr_8023 *lec_h;
-        struct atm_vcc *send_vcc;
+        struct atm_vcc *vcc;
 	struct lec_arp_table *entry;
         unsigned char *dst;
 	int min_frame_size;
@@ -243,7 +251,7 @@
         int i=0;
 #endif /* DUMP_PACKETS >0 */
         
-        DPRINTK("Lec_send_packet called\n");  
+        DPRINTK("lec_start_xmit called\n");  
         if (!priv->lecd) {
                 printk("%s:No lecd attached\n",dev->name);
                 priv->stats.tx_errors++;
@@ -262,7 +270,7 @@
         /* Make sure we have room for lec_id */
         if (skb_headroom(skb) < 2) {
 
-                DPRINTK("lec_send_packet: reallocating skb\n");
+                DPRINTK("lec_start_xmit: reallocating skb\n");
                 skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
                 kfree_skb(skb);
                 if (skb2 == NULL) return 0;
@@ -337,18 +345,18 @@
         }
 #endif
         entry = NULL;
-        send_vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
-        DPRINTK("%s:send_vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
-                send_vcc, send_vcc?send_vcc->flags:0, entry);
-        if (!send_vcc || !test_bit(ATM_VF_READY,&send_vcc->flags)) {    
+        vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
+        DPRINTK("%s:vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
+                vcc, vcc?vcc->flags:0, entry);
+        if (!vcc || !test_bit(ATM_VF_READY,&vcc->flags)) {    
                 if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
-                        DPRINTK("%s:lec_send_packet: queuing packet, ", dev->name);
+                        DPRINTK("%s:lec_start_xmit: queuing packet, ", dev->name);
                         DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
                                 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
                                 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
                         skb_queue_tail(&entry->tx_wait, skb);
                 } else {
-                        DPRINTK("%s:lec_send_packet: tx queue full or no arp entry, dropping, ", dev->name);
+                        DPRINTK("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", dev->name);
                         DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
                                 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
                                 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
@@ -360,7 +368,7 @@
                 
 #if DUMP_PACKETS > 0                    
         printk("%s:sending to vpi:%d vci:%d\n", dev->name,
-               send_vcc->vpi, send_vcc->vci);       
+               vcc->vpi, vcc->vci);       
 #endif /* DUMP_PACKETS > 0 */
                 
         while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
@@ -368,15 +376,28 @@
                 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
                         lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
                         lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
-		lec_send(send_vcc, skb2, priv);
+		lec_send(vcc, skb2, priv);
         }
 
-	lec_send(send_vcc, skb, priv);
+	lec_send(vcc, skb, priv);
 
-#if 0
-        /* Should we wait for card's device driver to notify us? */
-        dev->tbusy=0;
-#endif        
+	if (!atm_may_send(vcc, 0)) {
+		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
+
+		vpriv->xoff = 1;
+		netif_stop_queue(dev);
+
+		/*
+		 * vcc->pop() might have occurred in between, making
+		 * the vcc usuable again.  Since xmit is serialized,
+		 * this is the only situation we have to re-test.
+		 */
+
+		if (atm_may_send(vcc, 0))
+			netif_wake_queue(dev);
+	}
+
+	dev->trans_start = jiffies;
         return 0;
 }
 
@@ -635,7 +656,8 @@
         dev->change_mtu = lec_change_mtu;
         dev->open = lec_open;
         dev->stop = lec_close;
-        dev->hard_start_xmit = lec_send_packet;
+        dev->hard_start_xmit = lec_start_xmit;
+	dev->tx_timeout = lec_tx_timeout;
 
         dev->get_stats = lec_get_stats;
         dev->set_multicast_list = lec_set_multicast_list;
@@ -731,9 +753,30 @@
         }
 }
 
+void
+lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+	struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
+	struct net_device *dev = skb->dev;
+
+	if (vpriv == NULL) {
+		printk("lec_pop(): vpriv = NULL!?!?!?\n");
+		return;
+	}
+
+	vpriv->old_pop(vcc, skb);
+
+	if (vpriv->xoff && atm_may_send(vcc, 0)) {
+		vpriv->xoff = 0;
+		if (netif_running(dev) && netif_queue_stopped(dev))
+			netif_wake_queue(dev);
+	}
+}
+
 int 
 lec_vcc_attach(struct atm_vcc *vcc, void *arg)
 {
+	struct lec_vcc_priv *vpriv;
         int bytes_left;
         struct atmlec_ioc ioc_data;
 
@@ -746,6 +789,12 @@
         if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || 
             !dev_lec[ioc_data.dev_num])
                 return -EINVAL;
+	if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
+		return -ENOMEM;
+	vpriv->xoff = 0;
+	vpriv->old_pop = vcc->pop;
+	LEC_VCC_PRIV(vcc) = vpriv;
+	vcc->pop = lec_pop;
         lec_vcc_added(dev_lec[ioc_data.dev_num]->priv, 
                       &ioc_data, vcc, vcc->push);
         vcc->push = lec_push;
@@ -1363,22 +1412,21 @@
 lec_arp_clear_vccs(struct lec_arp_table *entry)
 {
         if (entry->vcc) {
-                entry->vcc->push = entry->old_push;
-#if 0 /* August 6, 1998 */
-                set_bit(ATM_VF_RELEASED,&entry->vcc->flags);
-		clear_bit(ATM_VF_READY,&entry->vcc->flags);
-                entry->vcc->push(entry->vcc, NULL);
-#endif
-		vcc_release_async(entry->vcc, -EPIPE);
-                entry->vcc = NULL;
+		struct atm_vcc *vcc = entry->vcc;
+		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
+		struct net_device *dev = (struct net_device*) vcc->proto_data;
+
+                vcc->pop = vpriv->old_pop;
+		if (vpriv->xoff)
+			netif_wake_queue(dev);
+		kfree(vpriv);
+		LEC_VCC_PRIV(vcc) = NULL;
+                vcc->push = entry->old_push;
+		vcc_release_async(vcc, -EPIPE);
+                vcc = NULL;
         }
         if (entry->recv_vcc) {
                 entry->recv_vcc->push = entry->old_recv_push;
-#if 0
-                set_bit(ATM_VF_RELEASED,&entry->recv_vcc->flags);
-		clear_bit(ATM_VF_READY,&entry->recv_vcc->flags);
-                entry->recv_vcc->push(entry->recv_vcc, NULL);
-#endif
 		vcc_release_async(entry->recv_vcc, -EPIPE);
                 entry->recv_vcc = NULL;
         }        
@@ -2320,11 +2368,20 @@
         unsigned char mac_addr[] = {
                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
         struct lec_arp_table *to_add;
+	struct lec_vcc_priv *vpriv;
   
+	if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
+		return -ENOMEM;
+	vpriv->xoff = 0;
+	vpriv->old_pop = vcc->pop;
+	LEC_VCC_PRIV(vcc) = vpriv;
+        vcc->pop = lec_pop;
         lec_arp_get(priv);
         to_add = make_entry(priv, mac_addr);
         if (!to_add) {
                 lec_arp_put(priv);
+		vcc->pop = vpriv->old_pop;
+		kfree(vpriv);
                 return -ENOMEM;
         }
         memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
diff -Nru a/net/atm/lec.h b/net/atm/lec.h
--- a/net/atm/lec.h	Wed Feb 25 15:16:38 2004
+++ b/net/atm/lec.h	Wed Feb 25 15:16:38 2004
@@ -139,6 +139,13 @@
         int is_trdev;      /* Device type, 0 = Ethernet, 1 = TokenRing */
 };
 
+struct lec_vcc_priv {
+	void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
+	int xoff;
+};
+
+#define LEC_VCC_PRIV(vcc)	((struct lec_vcc_priv *)((vcc)->user_back))
+
 int lecd_attach(struct atm_vcc *vcc, int arg);
 int lec_vcc_attach(struct atm_vcc *vcc, void *arg);
 int lec_mcast_attach(struct atm_vcc *vcc, int arg);

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH][ATM]: [lec] put back pressure on network stack
@ 2004-02-25 23:54 chas williams (contractor)
  2004-02-26 20:10 ` David S. Miller
  0 siblings, 1 reply; 5+ messages in thread
From: chas williams (contractor) @ 2004-02-25 23:54 UTC (permalink / raw)
  To: davem; +Cc: netdev

backport of similar patch for 2.6.  

please apply to 2.4 -- thanks

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1355  -> 1.1356 
#	       net/atm/lec.h	1.6     -> 1.7    
#	       net/atm/lec.c	1.22    -> 1.23   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/02/25	chas@relax.cmf.nrl.navy.mil	1.1356
# [ATM]: [lec] put back pressure on network stack
# --------------------------------------------
#
diff -Nru a/net/atm/lec.c b/net/atm/lec.c
--- a/net/atm/lec.c	Wed Feb 25 15:40:52 2004
+++ b/net/atm/lec.c	Wed Feb 25 15:40:52 2004
@@ -67,7 +67,7 @@
                                single destination while waiting for SVC */
 
 static int lec_open(struct net_device *dev);
-static int lec_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int lec_close(struct net_device *dev);
 static struct net_device_stats *lec_get_stats(struct net_device *dev);
 static void lec_init(struct net_device *dev);
@@ -211,26 +211,34 @@
 static __inline__ void
 lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
 {
-	if (atm_may_send(vcc, skb->len)) {
-		atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
-	        ATM_SKB(skb)->vcc = vcc;
-	        ATM_SKB(skb)->atm_options = vcc->atm_options;
-		priv->stats.tx_packets++;
-		priv->stats.tx_bytes += skb->len;
-		vcc->send(vcc, skb);
-	} else {
+	ATM_SKB(skb)->vcc = vcc;
+	ATM_SKB(skb)->atm_options = vcc->atm_options;
+
+	atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
+	if (vcc->send(vcc, skb) < 0) {
 		priv->stats.tx_dropped++;
-		dev_kfree_skb(skb);
+		return;
 	}
+
+	priv->stats.tx_packets++;
+	priv->stats.tx_bytes += skb->len;
+}
+
+static void
+lec_tx_timeout(struct net_device *dev)
+{
+	printk(KERN_INFO "%s: tx timeout\n", dev->name);
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
 }
 
 static int 
-lec_send_packet(struct sk_buff *skb, struct net_device *dev)
+lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
         struct sk_buff *skb2;
         struct lec_priv *priv = (struct lec_priv *)dev->priv;
         struct lecdatahdr_8023 *lec_h;
-        struct atm_vcc *send_vcc;
+        struct atm_vcc *vcc;
 	struct lec_arp_table *entry;
         unsigned char *dst;
 	int min_frame_size;
@@ -243,7 +251,7 @@
         int i=0;
 #endif /* DUMP_PACKETS >0 */
         
-        DPRINTK("Lec_send_packet called\n");  
+        DPRINTK("lec_start_xmit called\n");  
         if (!priv->lecd) {
                 printk("%s:No lecd attached\n",dev->name);
                 priv->stats.tx_errors++;
@@ -262,7 +270,7 @@
         /* Make sure we have room for lec_id */
         if (skb_headroom(skb) < 2) {
 
-                DPRINTK("lec_send_packet: reallocating skb\n");
+                DPRINTK("lec_start_xmit: reallocating skb\n");
                 skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
                 kfree_skb(skb);
                 if (skb2 == NULL) return 0;
@@ -337,18 +345,18 @@
         }
 #endif
         entry = NULL;
-        send_vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
-        DPRINTK("%s:send_vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
-                send_vcc, send_vcc?send_vcc->flags:0, entry);
-        if (!send_vcc || !test_bit(ATM_VF_READY,&send_vcc->flags)) {    
+        vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
+        DPRINTK("%s:vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
+                vcc, vcc?vcc->flags:0, entry);
+        if (!vcc || !test_bit(ATM_VF_READY,&vcc->flags)) {    
                 if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
-                        DPRINTK("%s:lec_send_packet: queuing packet, ", dev->name);
+                        DPRINTK("%s:lec_start_xmit: queuing packet, ", dev->name);
                         DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
                                 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
                                 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
                         skb_queue_tail(&entry->tx_wait, skb);
                 } else {
-                        DPRINTK("%s:lec_send_packet: tx queue full or no arp entry, dropping, ", dev->name);
+                        DPRINTK("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", dev->name);
                         DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
                                 lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
                                 lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
@@ -360,7 +368,7 @@
                 
 #if DUMP_PACKETS > 0                    
         printk("%s:sending to vpi:%d vci:%d\n", dev->name,
-               send_vcc->vpi, send_vcc->vci);       
+               vcc->vpi, vcc->vci);       
 #endif /* DUMP_PACKETS > 0 */
                 
         while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
@@ -368,14 +376,28 @@
                 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
                         lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
                         lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
-                lec_send(send_vcc, skb2, priv);
+                lec_send(vcc, skb2, priv);
         }
 
-        lec_send(send_vcc, skb, priv);
-#if 0
-        /* Should we wait for card's device driver to notify us? */
-        dev->tbusy=0;
-#endif        
+        lec_send(vcc, skb, priv);
+
+	if (!atm_may_send(vcc, 0)) {
+		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
+
+		vpriv->xoff = 1;
+		netif_stop_queue(dev);
+
+		/*
+		 * vcc->pop() might have occurred in between, making
+		 * the vcc usuable again.  Since xmit is serialized,
+		 * this is the only situation we have to re-test.
+		 */
+
+		if (atm_may_send(vcc, 0))
+			netif_wake_queue(dev);
+	}
+
+	dev->trans_start = jiffies;
         return 0;
 }
 
@@ -634,7 +656,8 @@
         dev->change_mtu = lec_change_mtu;
         dev->open = lec_open;
         dev->stop = lec_close;
-        dev->hard_start_xmit = lec_send_packet;
+        dev->hard_start_xmit = lec_start_xmit;
+	dev->tx_timeout = lec_tx_timeout;
 
         dev->get_stats = lec_get_stats;
         dev->set_multicast_list = lec_set_multicast_list;
@@ -729,9 +752,30 @@
         }
 }
 
+void
+lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+	struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
+	struct net_device *dev = skb->dev;
+
+	if (vpriv == NULL) {
+		printk("lec_pop(): vpriv = NULL!?!?!?\n");
+		return;
+	}
+
+	vpriv->old_pop(vcc, skb);
+
+	if (vpriv->xoff && atm_may_send(vcc, 0)) {
+		vpriv->xoff = 0;
+		if (netif_running(dev) && netif_queue_stopped(dev))
+			netif_wake_queue(dev);
+	}
+}
+
 int 
 lec_vcc_attach(struct atm_vcc *vcc, void *arg)
 {
+	struct lec_vcc_priv *vpriv;
         int bytes_left;
         struct atmlec_ioc ioc_data;
 
@@ -744,6 +788,12 @@
         if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || 
             !dev_lec[ioc_data.dev_num])
                 return -EINVAL;
+	if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
+		return -ENOMEM;
+	vpriv->xoff = 0;
+	vpriv->old_pop = vcc->pop;
+	LEC_VCC_PRIV(vcc) = vpriv;
+	vcc->pop = lec_pop;
         lec_vcc_added(dev_lec[ioc_data.dev_num]->priv, 
                       &ioc_data, vcc, vcc->push);
         vcc->push = lec_push;
@@ -1080,22 +1130,21 @@
 lec_arp_clear_vccs(struct lec_arp_table *entry)
 {
         if (entry->vcc) {
-                entry->vcc->push = entry->old_push;
-#if 0 /* August 6, 1998 */
-                set_bit(ATM_VF_RELEASED,&entry->vcc->flags);
-		clear_bit(ATM_VF_READY,&entry->vcc->flags);
-                entry->vcc->push(entry->vcc, NULL);
-#endif
-		vcc_release_async(entry->vcc, -EPIPE);
-                entry->vcc = NULL;
+		struct atm_vcc *vcc = entry->vcc;
+		struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
+		struct net_device *dev = (struct net_device*) vcc->proto_data;
+
+                vcc->pop = vpriv->old_pop;
+		if (vpriv->xoff)
+			netif_wake_queue(dev);
+		kfree(vpriv);
+		LEC_VCC_PRIV(vcc) = NULL;
+                vcc->push = entry->old_push;
+		vcc_release_async(vcc, -EPIPE);
+                vcc = NULL;
         }
         if (entry->recv_vcc) {
                 entry->recv_vcc->push = entry->old_recv_push;
-#if 0
-                set_bit(ATM_VF_RELEASED,&entry->recv_vcc->flags);
-		clear_bit(ATM_VF_READY,&entry->recv_vcc->flags);
-                entry->recv_vcc->push(entry->recv_vcc, NULL);
-#endif
 		vcc_release_async(entry->recv_vcc, -EPIPE);
                 entry->recv_vcc = NULL;
         }        
@@ -2037,11 +2086,20 @@
         unsigned char mac_addr[] = {
                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
         struct lec_arp_table *to_add;
+	struct lec_vcc_priv *vpriv;
   
+	if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
+		return -ENOMEM;
+	vpriv->xoff = 0;
+	vpriv->old_pop = vcc->pop;
+	LEC_VCC_PRIV(vcc) = vpriv;
+        vcc->pop = lec_pop;
         lec_arp_get(priv);
         to_add = make_entry(priv, mac_addr);
         if (!to_add) {
                 lec_arp_put(priv);
+		vcc->pop = vpriv->old_pop;
+		kfree(vpriv);
                 return -ENOMEM;
         }
         memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
diff -Nru a/net/atm/lec.h b/net/atm/lec.h
--- a/net/atm/lec.h	Wed Feb 25 15:40:52 2004
+++ b/net/atm/lec.h	Wed Feb 25 15:40:52 2004
@@ -147,6 +147,13 @@
         int is_trdev;      /* Device type, 0 = Ethernet, 1 = TokenRing */
 };
 
+struct lec_vcc_priv {
+	void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
+	int xoff;
+};
+
+#define LEC_VCC_PRIV(vcc)	((struct lec_vcc_priv *)((vcc)->user_back))
+
 int lecd_attach(struct atm_vcc *vcc, int arg);
 int lec_vcc_attach(struct atm_vcc *vcc, void *arg);
 int lec_mcast_attach(struct atm_vcc *vcc, int arg);

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH][ATM]: [lec] put back pressure on network stack
  2004-02-25 23:51 chas williams (contractor)
@ 2004-02-26 20:02 ` David S. Miller
  0 siblings, 0 replies; 5+ messages in thread
From: David S. Miller @ 2004-02-26 20:02 UTC (permalink / raw)
  To: chas3; +Cc: chas, netdev

On Wed, 25 Feb 2004 18:51:21 -0500
"chas williams (contractor)" <chas@cmf.nrl.navy.mil> wrote:

> the lane client doesnt put back pressure on the network
> stack when one of the transmit vcc's is full.  this can
> yield spurious results with certain network performance
> tests.
> 
> please apply to 2.6 --thanks

Applied, thanks Chas.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH][ATM]: [lec] put back pressure on network stack
  2004-02-25 23:54 [PATCH][ATM]: [lec] put back pressure on network stack chas williams (contractor)
@ 2004-02-26 20:10 ` David S. Miller
  2004-02-26 20:12   ` chas williams (contractor)
  0 siblings, 1 reply; 5+ messages in thread
From: David S. Miller @ 2004-02-26 20:10 UTC (permalink / raw)
  To: chas3; +Cc: chas, netdev

On Wed, 25 Feb 2004 18:54:09 -0500
"chas williams (contractor)" <chas@cmf.nrl.navy.mil> wrote:

> backport of similar patch for 2.6.  
> 
> please apply to 2.4 -- thanks
 ...
> # [ATM]: [lec] put back pressure on network stack

This conflicts with a previous patch you sent me in this group entitled:

[ATM]: [lec] send queued packets immediately after path switch

So it fully rejected when I tried to apply this one, it looks to me
like the changes this is trying to add are already in there as a result
of the previous change.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH][ATM]: [lec] put back pressure on network stack
  2004-02-26 20:10 ` David S. Miller
@ 2004-02-26 20:12   ` chas williams (contractor)
  0 siblings, 0 replies; 5+ messages in thread
From: chas williams (contractor) @ 2004-02-26 20:12 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev

i probably managed to combine two patches again.  i will get it
sorted out.

In message <20040226121036.7472a38a.davem@redhat.com>,"David S. Miller" writes:
>This conflicts with a previous patch you sent me in this group entitled:
>
>[ATM]: [lec] send queued packets immediately after path switch
>
>So it fully rejected when I tried to apply this one, it looks to me
>like the changes this is trying to add are already in there as a result
>of the previous change.
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2004-02-26 20:12 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-25 23:54 [PATCH][ATM]: [lec] put back pressure on network stack chas williams (contractor)
2004-02-26 20:10 ` David S. Miller
2004-02-26 20:12   ` chas williams (contractor)
  -- strict thread matches above, loose matches on Subject: below --
2004-02-25 23:51 chas williams (contractor)
2004-02-26 20:02 ` David S. Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).