Netdev List
 help / color / mirror / Atom feed
* [PATCH 2/5] s390: qeth driver fixes
From: Frank Pavlic @ 2006-05-24  7:51 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev


From: Ursula Braun <braunu@de.ibm.com>
From: Frank Pavlic <fpavlic@de.ibm.com>

	- correct checking of sscanf-%n value in qeth_string_to_ipaddr().
	- don't use netif_stop_queue outside the hard_start_xmit routine. 
	  Rather use netif_tx_disable.
	- don't call qeth_netdev_init on a recovery.

Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>
---

 drivers/s390/net/qeth.h      |    2 +-
 drivers/s390/net/qeth_main.c |   22 +++++++++++-----------
 2 files changed, 12 insertions(+), 12 deletions(-)

ef153db1ac07db7ec4eba2ec29237c58944b5c7b
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 4df0fcd..65e2b1b 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -1099,7 +1099,7 @@ qeth_string_to_ipaddr4(const char *buf, 
 
 	rc = sscanf(buf, "%d.%d.%d.%d%n", 
 		    &in[0], &in[1], &in[2], &in[3], &count);
-	if (rc != 4  || count) 
+	if (rc != 4  || count<=0)
 		return -EINVAL;
 	for (count = 0; count < 4; count++) {
 		if (in[count] > 255)
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index cb14642..0f6648f 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -3817,7 +3817,7 @@ qeth_stop(struct net_device *dev)
 
 	card = (struct qeth_card *) dev->priv;
 
-	netif_stop_queue(dev);
+	netif_tx_disable(dev);
 	card->dev->flags &= ~IFF_UP;
 	if (card->state == CARD_STATE_UP)
 		card->state = CARD_STATE_SOFTSETUP;
@@ -6359,12 +6359,9 @@ qeth_netdev_init(struct net_device *dev)
 	dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
 	dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
 #endif
-	dev->hard_header = card->orig_hard_header;
 	if (qeth_get_netdev_flags(card) & IFF_NOARP) {
 		dev->rebuild_header = NULL;
 		dev->hard_header = NULL;
-		if (card->options.fake_ll)
-			dev->hard_header = qeth_fake_header;
 		dev->header_cache_update = NULL;
 		dev->hard_header_cache = NULL;
 	}
@@ -6477,6 +6474,9 @@ retry:
 	/*network device will be recovered*/
 	if (card->dev) {
 		card->dev->hard_header = card->orig_hard_header;
+		if (card->options.fake_ll && 
+		    (qeth_get_netdev_flags(card) & IFF_NOARP))
+			card->dev->hard_header = qeth_fake_header;
 		return 0;
 	}
 	/* at first set_online allocate netdev */
@@ -7031,7 +7031,7 @@ qeth_softsetup_ipv6(struct qeth_card *ca
 
 	QETH_DBF_TEXT(trace,3,"softipv6");
 
-	netif_stop_queue(card->dev);
+	netif_tx_disable(card->dev);
 	rc = qeth_send_startlan(card, QETH_PROT_IPV6);
 	if (rc) {
 		PRINT_ERR("IPv6 startlan failed on %s\n",
@@ -7352,7 +7352,8 @@ qeth_set_large_send(struct qeth_card *ca
 		card->options.large_send = type;
 		return 0;
 	}
-	netif_stop_queue(card->dev);
+	if (card->state == CARD_STATE_UP)
+		netif_tx_disable(card->dev);
 	card->options.large_send = type;
 	switch (card->options.large_send) {
 	case QETH_LARGE_SEND_EDDP:
@@ -7374,7 +7375,8 @@ qeth_set_large_send(struct qeth_card *ca
 		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
 		break;
 	}
-	netif_wake_queue(card->dev);
+	if (card->state == CARD_STATE_UP)
+		netif_wake_queue(card->dev);
 	return rc;
 }
 
@@ -7427,7 +7429,7 @@ qeth_softsetup_card(struct qeth_card *ca
 	if ((rc = qeth_setrouting_v6(card)))
 		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
 out:
-	netif_stop_queue(card->dev);
+	netif_tx_disable(card->dev);
 	return 0;
 }
 
@@ -7736,10 +7738,8 @@ static int
 qeth_register_netdev(struct qeth_card *card)
 {
 	QETH_DBF_TEXT(setup, 3, "regnetd");
-	if (card->dev->reg_state != NETREG_UNINITIALIZED) {
-		qeth_netdev_init(card->dev);
+	if (card->dev->reg_state != NETREG_UNINITIALIZED) 
 		return 0;
-	}
 	/* sysfs magic */
 	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
 	return register_netdev(card->dev);
-- 
1.2.4


^ permalink raw reply related

* [PATCH 3/5] s390: qeth driver fixes
From: Frank Pavlic @ 2006-05-24  7:51 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev


From: Ursula Braun <braunu@de.ibm.com>
From: Frank Blaschka <Frank.Blaschka@de.ibm.com>
From: Frank Pavlic <fpavlic@de.ibm.com>

        - fix fake_ll during initial device bringup. fake_ll was 
	  not active after first start of the device. 
	  Problem only occured when qeth was built without IPV6 support.
        - avoid skb usage after invocation of qeth_flush_buffers, 
	  because skb might already be freed. 
        - remove yet another useless netif_wake_queue in
	  qeth_softsetup_ipv6 since this function is only called
	  when device is going online. In this case card->state will
	  never be in state UP. So let the net_device queue down .

Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>

---

 drivers/s390/net/qeth_main.c |   23 +++++++++++++----------
 1 files changed, 13 insertions(+), 10 deletions(-)

e32bb8db95c84a0af8c5688b92ed6691982e4f9c
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 0f6648f..9dbb5be 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -3798,11 +3798,11 @@ qeth_open(struct net_device *dev)
 		QETH_DBF_TEXT(trace,4,"nomacadr");
 		return -EPERM;
 	}
-	card->dev->flags |= IFF_UP;
-	netif_start_queue(dev);
 	card->data.state = CH_STATE_UP;
 	card->state = CARD_STATE_UP;
-
+	card->dev->flags |= IFF_UP;
+	netif_start_queue(dev);
+	
 	if (!card->lan_online && netif_carrier_ok(dev))
 		netif_carrier_off(dev);
 	return 0;
@@ -3958,7 +3958,7 @@ qeth_prepare_skb(struct qeth_card *card,
 #endif
 	*hdr = (struct qeth_hdr *)
 		qeth_push_skb(card, skb, sizeof(struct qeth_hdr));
-	if (hdr == NULL)
+	if (*hdr == NULL)
 		return -EINVAL;
 	return 0;
 }
@@ -4416,6 +4416,8 @@ qeth_send_packet(struct qeth_card *card,
 	enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
 	struct qeth_eddp_context *ctx = NULL;
 	int tx_bytes = skb->len;
+	unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
+	unsigned short tso_size = skb_shinfo(skb)->tso_size;
 	int rc;
 
 	QETH_DBF_TEXT(trace, 6, "sendpkt");
@@ -4498,16 +4500,16 @@ qeth_send_packet(struct qeth_card *card,
 		card->stats.tx_packets++;
 		card->stats.tx_bytes += tx_bytes;
 #ifdef CONFIG_QETH_PERF_STATS
-		if (skb_shinfo(skb)->tso_size &&
+		if (tso_size &&
 		   !(large_send == QETH_LARGE_SEND_NO)) {
-			card->perf_stats.large_send_bytes += skb->len;
+			card->perf_stats.large_send_bytes += tx_bytes;
 			card->perf_stats.large_send_cnt++;
 		}
- 		if (skb_shinfo(skb)->nr_frags > 0){
+ 		if (nr_frags > 0){
 			card->perf_stats.sg_skbs_sent++;
 			/* nr_frags + skb->data */
 			card->perf_stats.sg_frags_sent +=
-				skb_shinfo(skb)->nr_frags + 1;
+				nr_frags + 1;
 		}
 #endif /* CONFIG_QETH_PERF_STATS */
 	}
@@ -6370,6 +6372,9 @@ qeth_netdev_init(struct net_device *dev)
 	if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
 		card->dev->dev_id = card->info.unique_id & 0xffff;
 #endif
+	if (card->options.fake_ll && 
+		(qeth_get_netdev_flags(card) & IFF_NOARP))
+			dev->hard_header = qeth_fake_header;
 	dev->hard_header_parse = NULL;
 	dev->set_mac_address = qeth_layer2_set_mac_address;
 	dev->flags |= qeth_get_netdev_flags(card);
@@ -7031,14 +7036,12 @@ qeth_softsetup_ipv6(struct qeth_card *ca
 
 	QETH_DBF_TEXT(trace,3,"softipv6");
 
-	netif_tx_disable(card->dev);
 	rc = qeth_send_startlan(card, QETH_PROT_IPV6);
 	if (rc) {
 		PRINT_ERR("IPv6 startlan failed on %s\n",
 			  QETH_CARD_IFNAME(card));
 		return rc;
 	}
-	netif_wake_queue(card->dev);
 	rc = qeth_query_ipassists(card,QETH_PROT_IPV6);
 	if (rc) {
 		PRINT_ERR("IPv6 query ipassist failed on %s\n",
-- 
1.2.4


^ permalink raw reply related

* [PATCH 4/5] s390: lcs driver bug fixes and improvements [1/2]
From: Frank Pavlic @ 2006-05-24  7:51 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev



From: Klaus Wacker <kdwacker@de.ibm.com>

	Several problems occured with lcs device driver:
	 - device not operational anymore after cable pull/plug-in.
       	 - unpredictable results occured, e.g. kernel panic
	   using cards of type QD8F.
	 - STOPLAN and delete multicast address command
           were not proper recognized by OSA card under heavy network workload.
       	 - channel/device error checks missing in interrupt handler.
	To fix all problems at once recovery of lcs devices has been improved.
	missing error checks in lcs interrupt handler has been added.
	Once a hardware problem occurs lcs will recover the device now properly.

Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>
---

 drivers/s390/net/lcs.c |  341 ++++++++++++++++++++++++------------------------
 1 files changed, 171 insertions(+), 170 deletions(-)

c9db4a2d4c97370d5a65ef0654342052c80ed7a2
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index e65da92..c915bb5 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -68,6 +68,7 @@ static void lcs_tasklet(unsigned long);
 static void lcs_start_kernel_thread(struct lcs_card *card);
 static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *);
 static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *);
+static int lcs_recovery(void *ptr);
 
 /**
  * Debug Facility Stuff
@@ -429,12 +430,6 @@ lcs_setup_card(struct lcs_card *card)
 	card->tx_buffer = NULL;
 	card->tx_emitted = 0;
 
-	/* Initialize kernel thread task used for LGW commands. */
-	INIT_WORK(&card->kernel_thread_starter,
-		  (void *)lcs_start_kernel_thread,card);
-	card->thread_start_mask = 0;
-	card->thread_allowed_mask = 0;
-	card->thread_running_mask = 0;
 	init_waitqueue_head(&card->wait_q);
 	spin_lock_init(&card->lock);
 	spin_lock_init(&card->ipm_lock);
@@ -675,8 +670,9 @@ lcs_ready_buffer(struct lcs_channel *cha
 	int index, rc;
 
 	LCS_DBF_TEXT(5, trace, "rdybuff");
-	BUG_ON(buffer->state != BUF_STATE_LOCKED &&
-		buffer->state != BUF_STATE_PROCESSED);
+	if (buffer->state != BUF_STATE_LOCKED &&
+	    buffer->state != BUF_STATE_PROCESSED)
+		BUG();
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
 	buffer->state = BUF_STATE_READY;
 	index = buffer - channel->iob;
@@ -700,7 +696,8 @@ __lcs_processed_buffer(struct lcs_channe
 	int index, prev, next;
 
 	LCS_DBF_TEXT(5, trace, "prcsbuff");
-	BUG_ON(buffer->state != BUF_STATE_READY);
+	if (buffer->state != BUF_STATE_READY)
+		BUG();
 	buffer->state = BUF_STATE_PROCESSED;
 	index = buffer - channel->iob;
 	prev = (index - 1) & (LCS_NUM_BUFFS - 1);
@@ -732,8 +729,9 @@ lcs_release_buffer(struct lcs_channel *c
 	unsigned long flags;
 
 	LCS_DBF_TEXT(5, trace, "relbuff");
-	BUG_ON(buffer->state != BUF_STATE_LOCKED &&
-		buffer->state != BUF_STATE_PROCESSED);
+	if (buffer->state != BUF_STATE_LOCKED &&
+	    buffer->state != BUF_STATE_PROCESSED)
+		BUG();
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
 	buffer->state = BUF_STATE_EMPTY;
 	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
@@ -1147,8 +1145,6 @@ list_modified:
 		list_add_tail(&ipm->list, &card->ipm_list);
 	}
 	spin_unlock_irqrestore(&card->ipm_lock, flags);
-	if (card->state == DEV_STATE_UP)
-		netif_wake_queue(card->dev);
 }
 
 /**
@@ -1231,17 +1227,17 @@ lcs_set_mc_addresses(struct lcs_card *ca
 		if (ipm != NULL)
 			continue;	/* Address already in list. */
 		ipm = (struct lcs_ipm_list *)
-			kmalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
+			kzalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
 		if (ipm == NULL) {
 			PRINT_INFO("Not enough memory to add "
 				   "new multicast entry!\n");
 			break;
 		}
-		memset(ipm, 0, sizeof(struct lcs_ipm_list));
 		memcpy(&ipm->ipm.mac_addr, buf, LCS_MAC_LENGTH);
 		ipm->ipm.ip_addr = im4->multiaddr;
 		ipm->ipm_state = LCS_IPM_STATE_SET_REQUIRED;
 		spin_lock_irqsave(&card->ipm_lock, flags);
+		LCS_DBF_HEX(2,trace,&ipm->ipm.ip_addr,4);
 		list_add(&ipm->list, &card->ipm_list);
 		spin_unlock_irqrestore(&card->ipm_lock, flags);
 	}
@@ -1269,7 +1265,15 @@ lcs_register_mc_addresses(void *data)
 	read_unlock(&in4_dev->mc_list_lock);
 	in_dev_put(in4_dev);
 
+	netif_carrier_off(card->dev);
+	netif_tx_disable(card->dev);
+	wait_event(card->write.wait_q,
+			(card->write.state != CH_STATE_RUNNING));
 	lcs_fix_multicast_list(card);
+	if (card->state == DEV_STATE_UP) {
+		netif_carrier_on(card->dev);
+		netif_wake_queue(card->dev);
+	}
 out:
 	lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD);
 	return 0;
@@ -1318,6 +1322,53 @@ lcs_check_irb_error(struct ccw_device *c
 	return PTR_ERR(irb);
 }
 
+static int
+lcs_get_problem(struct ccw_device *cdev, struct irb *irb)
+{
+	int dstat, cstat;
+	char *sense;
+
+	sense = (char *) irb->ecw;
+	cstat = irb->scsw.cstat;
+	dstat = irb->scsw.dstat;
+
+	if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
+		     SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
+		     SCHN_STAT_PROT_CHECK   | SCHN_STAT_PROG_CHECK)) {
+		LCS_DBF_TEXT(2, trace, "CGENCHK");
+		return 1;
+	}
+	if (dstat & DEV_STAT_UNIT_CHECK) {
+		if (sense[LCS_SENSE_BYTE_1] &
+		    LCS_SENSE_RESETTING_EVENT) {
+			LCS_DBF_TEXT(2, trace, "REVIND");
+			return 1;
+		}
+		if (sense[LCS_SENSE_BYTE_0] &
+		    LCS_SENSE_CMD_REJECT) {
+			LCS_DBF_TEXT(2, trace, "CMDREJ");
+			return 0;
+		}
+		if ((!sense[LCS_SENSE_BYTE_0]) &&
+		    (!sense[LCS_SENSE_BYTE_1]) &&
+		    (!sense[LCS_SENSE_BYTE_2]) &&
+		    (!sense[LCS_SENSE_BYTE_3])) {
+			LCS_DBF_TEXT(2, trace, "ZEROSEN");
+			return 0;
+		}
+		LCS_DBF_TEXT(2, trace, "DGENCHK");
+		return 1;
+	}
+	return 0;
+}
+
+void
+lcs_schedule_recovery(struct lcs_card *card)
+{
+	LCS_DBF_TEXT(2, trace, "startrec");
+	if (!lcs_set_thread_start_bit(card, LCS_RECOVERY_THREAD))
+		schedule_work(&card->kernel_thread_starter);
+}
 
 /**
  * IRQ Handler for LCS channels
@@ -1327,7 +1378,8 @@ lcs_irq(struct ccw_device *cdev, unsigne
 {
 	struct lcs_card *card;
 	struct lcs_channel *channel;
-	int index;
+	int rc, index;
+	int cstat, dstat;
 
 	if (lcs_check_irb_error(cdev, irb))
 		return;
@@ -1338,10 +1390,23 @@ lcs_irq(struct ccw_device *cdev, unsigne
 	else
 		channel = &card->write;
 
+	cstat = irb->scsw.cstat;
+	dstat = irb->scsw.dstat;
 	LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
 	LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.cstat, irb->scsw.dstat);
 	LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.fctl, irb->scsw.actl);
 
+	/* Check for channel and device errors presented */
+	rc = lcs_get_problem(cdev, irb);
+	if (rc || (dstat & DEV_STAT_UNIT_EXCEP)) {
+		PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n", 
+			    cdev->dev.bus_id, dstat, cstat);
+		if (rc) {
+			lcs_schedule_recovery(card);
+			wake_up(&card->wait_q);
+			return;
+		}
+	}
 	/* How far in the ccw chain have we processed? */
 	if ((channel->state != CH_STATE_INIT) &&
 	    (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
@@ -1367,7 +1432,6 @@ lcs_irq(struct ccw_device *cdev, unsigne
 	else if (irb->scsw.actl & SCSW_ACTL_SUSPENDED)
 		/* CCW execution stopped on a suspend bit. */
 		channel->state = CH_STATE_SUSPENDED;
-
 	if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
 		if (irb->scsw.cc != 0) {
 			ccw_device_halt(channel->ccwdev, (addr_t) channel);
@@ -1376,7 +1440,6 @@ lcs_irq(struct ccw_device *cdev, unsigne
 		/* The channel has been stopped by halt_IO. */
 		channel->state = CH_STATE_HALTED;
 	}
-
 	if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
 		channel->state = CH_STATE_CLEARED;
 	}
@@ -1452,7 +1515,7 @@ lcs_txbuffer_cb(struct lcs_channel *chan
 	lcs_release_buffer(channel, buffer);
 	card = (struct lcs_card *)
 		((char *) channel - offsetof(struct lcs_card, write));
-	if (netif_queue_stopped(card->dev))
+	if (netif_queue_stopped(card->dev) && netif_carrier_ok(card->dev))
 		netif_wake_queue(card->dev);
 	spin_lock(&card->lock);
 	card->tx_emitted--;
@@ -1488,6 +1551,10 @@ __lcs_start_xmit(struct lcs_card *card, 
 		card->stats.tx_carrier_errors++;
 		return 0;
 	}
+	if (skb->protocol == htons(ETH_P_IPV6)) {
+		dev_kfree_skb(skb);
+		return 0;
+	}
 	netif_stop_queue(card->dev);
 	spin_lock(&card->lock);
 	if (card->tx_buffer != NULL &&
@@ -1633,30 +1700,6 @@ lcs_detect(struct lcs_card *card)
 }
 
 /**
- * reset card
- */
-static int
-lcs_resetcard(struct lcs_card *card)
-{
-	int retries;
-
-	LCS_DBF_TEXT(2, trace, "rescard");
-	for (retries = 0; retries < 10; retries++) {
-		if (lcs_detect(card) == 0) {
-			netif_wake_queue(card->dev);
-			card->state = DEV_STATE_UP;
-			PRINT_INFO("LCS device %s successfully restarted!\n",
-				   card->dev->name);
-			return 0;
-		}
-		msleep(3000);
-	}
-	PRINT_ERR("Error in Reseting LCS card!\n");
-	return -EIO;
-}
-
-
-/**
  * LCS Stop card
  */
 static int
@@ -1680,126 +1723,18 @@ lcs_stopcard(struct lcs_card *card)
 }
 
 /**
- * LGW initiated commands
- */
-static int
-lcs_lgw_startlan_thread(void *data)
-{
-	struct lcs_card *card;
-
-	card = (struct lcs_card *) data;
-	daemonize("lgwstpln");
-
-	if (!lcs_do_run_thread(card, LCS_STARTLAN_THREAD))
-		return 0;
-	LCS_DBF_TEXT(4, trace, "lgwstpln");
-	if (card->dev)
-		netif_stop_queue(card->dev);
-	if (lcs_startlan(card) == 0) {
-		netif_wake_queue(card->dev);
-		card->state = DEV_STATE_UP;
-		PRINT_INFO("LCS Startlan for device %s succeeded!\n",
-			   card->dev->name);
-
-	} else
-		PRINT_ERR("LCS Startlan for device %s failed!\n",
-			  card->dev->name);
-	lcs_clear_thread_running_bit(card, LCS_STARTLAN_THREAD);
-	return 0;
-}
-
-/**
- * Send startup command initiated by Lan Gateway
- */
-static int
-lcs_lgw_startup_thread(void *data)
-{
-	int rc;
-
-	struct lcs_card *card;
-
-	card = (struct lcs_card *) data;
-	daemonize("lgwstaln");
-
-	if (!lcs_do_run_thread(card, LCS_STARTUP_THREAD))
-		return 0;
-	LCS_DBF_TEXT(4, trace, "lgwstaln");
-	if (card->dev)
-		netif_stop_queue(card->dev);
-	rc = lcs_send_startup(card, LCS_INITIATOR_LGW);
-	if (rc != 0) {
-		PRINT_ERR("Startup for LCS device %s initiated " \
-			  "by LGW failed!\nReseting card ...\n",
-			  card->dev->name);
-		/* do a card reset */
-		rc = lcs_resetcard(card);
-		if (rc == 0)
-			goto Done;
-	}
-	rc = lcs_startlan(card);
-	if (rc == 0) {
-		netif_wake_queue(card->dev);
-		card->state = DEV_STATE_UP;
-	}
-Done:
-	if (rc == 0)
-		PRINT_INFO("LCS Startup for device %s succeeded!\n",
-			   card->dev->name);
-	else
-		PRINT_ERR("LCS Startup for device %s failed!\n",
-			  card->dev->name);
-	lcs_clear_thread_running_bit(card, LCS_STARTUP_THREAD);
-	return 0;
-}
-
-
-/**
- * send stoplan command initiated by Lan Gateway
- */
-static int
-lcs_lgw_stoplan_thread(void *data)
-{
-	struct lcs_card *card;
-	int rc;
-
-	card = (struct lcs_card *) data;
-	daemonize("lgwstop");
-
-	if (!lcs_do_run_thread(card, LCS_STOPLAN_THREAD))
-		return 0;
-	LCS_DBF_TEXT(4, trace, "lgwstop");
-	if (card->dev)
-		netif_stop_queue(card->dev);
-	if (lcs_send_stoplan(card, LCS_INITIATOR_LGW) == 0)
-		PRINT_INFO("Stoplan for %s initiated by LGW succeeded!\n",
-			   card->dev->name);
-	else
-		PRINT_ERR("Stoplan %s initiated by LGW failed!\n",
-			  card->dev->name);
-	/*Try to reset the card, stop it on failure */
-        rc = lcs_resetcard(card);
-        if (rc != 0)
-                rc = lcs_stopcard(card);
-	lcs_clear_thread_running_bit(card, LCS_STOPLAN_THREAD);
-        return rc;
-}
-
-/**
  * Kernel Thread helper functions for LGW initiated commands
  */
 static void
 lcs_start_kernel_thread(struct lcs_card *card)
 {
 	LCS_DBF_TEXT(5, trace, "krnthrd");
-	if (lcs_do_start_thread(card, LCS_STARTUP_THREAD))
-		kernel_thread(lcs_lgw_startup_thread, (void *) card, SIGCHLD);
-	if (lcs_do_start_thread(card, LCS_STARTLAN_THREAD))
-		kernel_thread(lcs_lgw_startlan_thread, (void *) card, SIGCHLD);
-	if (lcs_do_start_thread(card, LCS_STOPLAN_THREAD))
-		kernel_thread(lcs_lgw_stoplan_thread, (void *) card, SIGCHLD);
+	if (lcs_do_start_thread(card, LCS_RECOVERY_THREAD))
+		kernel_thread(lcs_recovery, (void *) card, SIGCHLD);
 #ifdef CONFIG_IP_MULTICAST
 	if (lcs_do_start_thread(card, LCS_SET_MC_THREAD))
-		kernel_thread(lcs_register_mc_addresses, (void *) card, SIGCHLD);
+		kernel_thread(lcs_register_mc_addresses, 
+				(void *) card, SIGCHLD);
 #endif
 }
 
@@ -1813,19 +1748,14 @@ lcs_get_control(struct lcs_card *card, s
 	if (cmd->initiator == LCS_INITIATOR_LGW) {
 		switch(cmd->cmd_code) {
 		case LCS_CMD_STARTUP:
-			if (!lcs_set_thread_start_bit(card,
-						      LCS_STARTUP_THREAD))
-				schedule_work(&card->kernel_thread_starter);
-			break;
 		case LCS_CMD_STARTLAN:
-			if (!lcs_set_thread_start_bit(card,
-						      LCS_STARTLAN_THREAD))
-				schedule_work(&card->kernel_thread_starter);
+			lcs_schedule_recovery(card);
 			break;
 		case LCS_CMD_STOPLAN:
-			if (!lcs_set_thread_start_bit(card,
-						      LCS_STOPLAN_THREAD))
-				schedule_work(&card->kernel_thread_starter);
+			PRINT_WARN("Stoplan for %s initiated by LGW.\n",
+					card->dev->name);
+			if (card->dev)
+				netif_carrier_off(card->dev);
 			break;
 		default:
 			PRINT_INFO("UNRECOGNIZED LGW COMMAND\n");
@@ -1941,8 +1871,11 @@ lcs_stop_device(struct net_device *dev)
 
 	LCS_DBF_TEXT(2, trace, "stopdev");
 	card   = (struct lcs_card *) dev->priv;
-	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+	netif_tx_disable(dev);
 	dev->flags &= ~IFF_UP;
+	wait_event(card->write.wait_q,
+		(card->write.state != CH_STATE_RUNNING));
 	rc = lcs_stopcard(card);
 	if (rc)
 		PRINT_ERR("Try it again!\n ");
@@ -1968,6 +1901,7 @@ lcs_open_device(struct net_device *dev)
 
 	} else {
 		dev->flags |= IFF_UP;
+		netif_carrier_on(dev);
 		netif_wake_queue(dev);
 		card->state = DEV_STATE_UP;
 	}
@@ -2059,10 +1993,31 @@ lcs_timeout_store (struct device *dev, s
 
 DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store);
 
+static ssize_t
+lcs_dev_recover_store(struct device *dev, struct device_attribute *attr, 
+		      const char *buf, size_t count)
+{
+	struct lcs_card *card = dev->driver_data;
+	char *tmp;
+	int i;
+
+	if (!card)
+		return -EINVAL;
+	if (card->state != DEV_STATE_UP)
+		return -EPERM;
+	i = simple_strtoul(buf, &tmp, 16);
+	if (i == 1)
+		lcs_schedule_recovery(card);
+	return count;
+}
+
+static DEVICE_ATTR(recover, 0200, NULL, lcs_dev_recover_store);
+
 static struct attribute * lcs_attrs[] = {
 	&dev_attr_portno.attr,
 	&dev_attr_type.attr,
 	&dev_attr_lancmd_timeout.attr,
+	&dev_attr_recover.attr,
 	NULL,
 };
 
@@ -2099,6 +2054,12 @@ lcs_probe_device(struct ccwgroup_device 
 	ccwgdev->dev.driver_data = card;
 	ccwgdev->cdev[0]->handler = lcs_irq;
 	ccwgdev->cdev[1]->handler = lcs_irq;
+	card->gdev = ccwgdev;
+	INIT_WORK(&card->kernel_thread_starter,
+		  (void *) lcs_start_kernel_thread, card);
+	card->thread_start_mask = 0;
+	card->thread_allowed_mask = 0;
+	card->thread_running_mask = 0;
         return 0;
 }
 
@@ -2200,6 +2161,7 @@ netdev_out:
 	if (recover_state == DEV_STATE_RECOVER) {
 		lcs_set_multicast_list(card->dev);
 		card->dev->flags |= IFF_UP;
+		netif_carrier_on(card->dev);
 		netif_wake_queue(card->dev);
 		card->state = DEV_STATE_UP;
 	} else {
@@ -2229,7 +2191,7 @@ out:
  * lcs_shutdown_device, called when setting the group device offline.
  */
 static int
-lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
+__lcs_shutdown_device(struct ccwgroup_device *ccwgdev, int recovery_mode)
 {
 	struct lcs_card *card;
 	enum lcs_dev_states recover_state;
@@ -2239,9 +2201,11 @@ lcs_shutdown_device(struct ccwgroup_devi
 	card = (struct lcs_card *)ccwgdev->dev.driver_data;
 	if (!card)
 		return -ENODEV;
-	lcs_set_allowed_threads(card, 0);
-	if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
-		return -ERESTARTSYS;
+	if (recovery_mode == 0) {
+		lcs_set_allowed_threads(card, 0);
+		if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
+			return -ERESTARTSYS;
+	}
 	LCS_DBF_HEX(3, setup, &card, sizeof(void*));
 	recover_state = card->state;
 
@@ -2256,6 +2220,43 @@ lcs_shutdown_device(struct ccwgroup_devi
 	return 0;
 }
 
+static int
+lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
+{
+	return __lcs_shutdown_device(ccwgdev, 0);
+}
+
+/**
+ * drive lcs recovery after startup and startlan initiated by Lan Gateway
+ */
+static int
+lcs_recovery(void *ptr)
+{
+	struct lcs_card *card;
+	struct ccwgroup_device *gdev;
+        int rc;
+
+	card = (struct lcs_card *) ptr;
+	daemonize("lcs_recover");
+
+	LCS_DBF_TEXT(4, trace, "recover1");
+	if (!lcs_do_run_thread(card, LCS_RECOVERY_THREAD))
+		return 0;
+	LCS_DBF_TEXT(4, trace, "recover2");
+	gdev = card->gdev;
+	PRINT_WARN("Recovery of device %s started...\n", gdev->dev.bus_id);
+	rc = __lcs_shutdown_device(gdev, 1);
+	rc = lcs_new_device(gdev);
+	if (!rc)
+		PRINT_INFO("Device %s successfully recovered!\n",
+				card->dev->name);
+	else
+		PRINT_INFO("Device %s could not be recovered!\n",
+				card->dev->name);
+	lcs_clear_thread_running_bit(card, LCS_RECOVERY_THREAD);
+	return 0;
+}
+
 /**
  * lcs_remove_device, free buffers and card
  */
-- 
1.2.4


^ permalink raw reply related

* [PATCH 5/5] s390: lcs driver bug fixes and improvements [2/2]
From: Frank Pavlic @ 2006-05-24  7:51 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev



From: Klaus Wacker <kdwacker@de.ibm.com>
	
	This is the second lcs driver patch containing the rest of lcs fixes.

Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>
---

 drivers/s390/net/lcs.h |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

6956e921ffef4871ce2d422cbcbdad863f7ab0b3
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 2fad5e4..9314393 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -73,13 +73,17 @@ do {                                    
 /**
  * LCS sense byte definitions
  */
+#define LCS_SENSE_BYTE_0 		0
+#define LCS_SENSE_BYTE_1 		1
+#define LCS_SENSE_BYTE_2 		2
+#define LCS_SENSE_BYTE_3 		3
 #define LCS_SENSE_INTERFACE_DISCONNECT	0x01
 #define LCS_SENSE_EQUIPMENT_CHECK	0x10
 #define LCS_SENSE_BUS_OUT_CHECK		0x20
 #define LCS_SENSE_INTERVENTION_REQUIRED 0x40
 #define LCS_SENSE_CMD_REJECT		0x80
-#define LCS_SENSE_RESETTING_EVENT	0x0080
-#define LCS_SENSE_DEVICE_ONLINE		0x0020
+#define LCS_SENSE_RESETTING_EVENT	0x80
+#define LCS_SENSE_DEVICE_ONLINE		0x20
 
 /**
  * LCS packet type definitions
@@ -152,10 +156,9 @@ enum lcs_dev_states {
 
 enum lcs_threads {
 	LCS_SET_MC_THREAD 	= 1,
-	LCS_STARTLAN_THREAD	= 2,
-	LCS_STOPLAN_THREAD	= 4,
-	LCS_STARTUP_THREAD	= 8,
+	LCS_RECOVERY_THREAD 	= 2,
 };
+
 /**
  * LCS struct declarations
  */
@@ -286,6 +289,7 @@ struct lcs_card {
 	struct net_device_stats stats;
 	unsigned short (*lan_type_trans)(struct sk_buff *skb,
 					 struct net_device *dev);
+	struct ccwgroup_device *gdev;
 	struct lcs_channel read;
 	struct lcs_channel write;
 	struct lcs_buffer *tx_buffer;
-- 
1.2.4


^ permalink raw reply related

* Re: reminder, 2.6.18 window...
From: Phil Dibowitz @ 2006-05-24  8:01 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20060523.182217.59656237.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 1695 bytes --]

David Miller wrote:
> Some time in the next few weeks, it is likely that the 2.6.18
> merge window will open up shortly after a 2.6.17 release.
> 
> So if you have major 2.6.18 submissions planned for the networking,
> you need to start thinking about getting it to me now.
> 
> There is a 2.6.18 tree up at:
> 
> master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.18.git
> 
> All it has right now is the I/O AT stuff at the moment, and I plan to
> put Stephen Hemminger's LLC multicast/datagram changes in there as
> well.

David,

I posted a patch for adding support for network device statistic
resetting via ethtool. I saw no objections to it... it impliments the
framework as well as skge support, so it touches both your and Jeff's area.

For your reference, here's the two times I've posted it this month - I'm
happy to send it along again.

2006-05-18
RESEND: [PATCH] Interface Stat Clearing Framework, skge support, ethtool
http://marc.theaimsgroup.com/?l=linux-netdev&m=114794065502155&w=2

2006-04-30
[PATCH] Interface Stat Clearing Framework, skge support, ethtool
http://marc.theaimsgroup.com/?l=linux-netdev&m=114636704207480&w=2

I'd like to get this into 2.6.18. It's self-contained, so it has little
chance of breaking other things and adds a useful feature that I've seen
a lot of requests for.

Thanks.
-- 
Phil Dibowitz                             phil@ipom.com
Freeware and Technical Pages              Insanity Palace of Metallica
http://www.phildev.net/                   http://www.ipom.com/

"Be who you are and say what you feel, because those who mind don't
matter and those who matter don't mind."
 - Dr. Seuss



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

^ permalink raw reply

* Re: [PATCH 3/4] myri10ge - Driver core
From: Brice Goglin @ 2006-05-24  8:04 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: netdev, gallatin, linux-kernel, benh
In-Reply-To: <20060523153928.GB5938@krispykreme>

Anton Blanchard wrote:
>> +/*
>> + * Set of routunes to get a new receive buffer.  Any buffer which
>> + * crosses a 4KB boundary must start on a 4KB boundary due to PCIe
>> + * wdma restrictions. We also try to align any smaller allocation to
>> + * at least a 16 byte boundary for efficiency.  We assume the linux
>> + * memory allocator works by powers of 2, and will not return memory
>> + * smaller than 2KB which crosses a 4KB boundary.  If it does, we fall
>> + * back to allocating 2x as much space as required.
>> + *
>> + * We intend to replace large (>4KB) skb allocations by using
>> + * pages directly and building a fraglist in the near future.
>> + */
>>     
>
> You go to a lot of trouble to align things. One thing on ppc64 is that
> we really want to start all DMA writes on a cacheline boundary. We
> enforce that in network drivers by making NET_IP_ALIGN = 0 and having
> the drivers do:
>
> skb_reserve(skb, NET_IP_ALIGN);
>
> It sounds like your small allocations will be only aligned to 16 bytes.
>   

We didn't get any ppc64 with PCI-E to run Linux so far. What performance
drop should we expect with our current code ?

> Id suggest using the dma API instead of the pci API. We have seen
> machines in the field that have failed large pci_alloc_consistent calls
> because it always asks for GFP_ATOMIC memory (it presumes the worst).
> The dma API allows you to pass a GFP_ flag in which will have a much
> better chance of succeeding when you dont need GFP_ATOMIC memory.
>   

Good idea, thanks,

>> +#ifdef CONFIG_MTRR
>> +	mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span,
>> +			     MTRR_TYPE_WRCOMB, 1);
>> +#endif
>>     
> ...
>   
>> +	mgp->sram = ioremap(mgp->iomem_base, mgp->board_span);
>>     
>
> Not sure how we are meant to specify write through in drivers. Any ideas Ben?
>   

I am not sure what you mean.
The only ppc64 with PCI-E that we have seen so far (a G5) couldn't do
write combining according to Apple.

Thanks,
Brice


^ permalink raw reply

* Re: [1/1] connector: export cn_already_initialized.
From: Evgeniy Polyakov @ 2006-05-24  8:38 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <20060516.161406.23276754.davem@davemloft.net>

On Tue, May 16, 2006 at 04:14:06PM -0700, David S. Miller (davem@davemloft.net) wrote:
> From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
> Date: Sat, 6 May 2006 12:40:45 +0400
> > I think the right solution is to call external init functions after cn
> > init function, but it's ordering is not always known.
> 
> In-kernel build of connector subsystem can be handled by
> making cn_init a "subsystem_init()", it will then be setup
> before any possible static or modular reference as long as
> those modules use module_init().

subsystem_init() seems to be kobject related initilizator.
Maybe subsys_initcall()?

I will cook up a patch if it works.
Thank you.

-- 
	Evgeniy Polyakov

^ permalink raw reply

* Re: Please pull 'upstream-fixes' branch of wireless-2.6
From: Andrew Morton @ 2006-05-24  8:52 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linville, netdev
In-Reply-To: <4473E06C.6060804@garzik.org>

Jeff Garzik <jeff@garzik.org> wrote:
>
> John W. Linville wrote:
> > The following changes since commit 353b28bafd1b962359a866ff263a7fad833d29a1:
> >   David S. Miller:
> >         [SPARC]: Add robust futex syscall entries.
> > 
> > are found in the git repository at:
> > 
> >   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream-fixes
> > 
> > Florin Malita:
> >       orinoco: possible null pointer dereference in orinoco_rx_monitor()
> 
> skipping, went in via akpm apparently.

Yes, sorry, I screwed that up - I thought John's pull request went to Linus
and when nothing had happened for 24 hrs, I sent the diff myself.  Doh.


^ permalink raw reply

* Re: iptables broken on ppc (ptrace too?) (2.6.17-rc3)
From: Meelis Roos @ 2006-05-24  9:20 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netdev
In-Reply-To: <4468D823.5090802@trash.net>

>> 32-bit kernel, this is a Motorola Powerstack II macine with 604e. PReP
>> subarch, only buildable from the old ARCH=ppc code (not yet migrated to
>> ARCH=powerpc).
>
> Ah OK, I thought it was related to the new compat code, but that isn't
> the case. Your trace doesn't give much clues, except that it shows that
> iptables dies with a SIGSEGV, which might be a bug in userspace or in
> the kernel. Which was the last kernel that worked for you, and can you
> try that version again to rule out userspace bugs?

Even worse. With yesterdays git iptable_nat loads but iptable_filter 
doesn't even load (Invalid argument).

-- 
Meelis Roos (mroos@linux.ee)

^ permalink raw reply

* Re: [Netchannel] Full TCP receiving support.
From: Evgeniy Polyakov @ 2006-05-24  9:38 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, kelly, rusty
In-Reply-To: <20060522163414.GA5426@2ka.mipt.ru>

[-- Attachment #1: Type: text/plain, Size: 1493 bytes --]

Hello, developers.

Initial TCP benchmark.
After tweaking some stuff I run netchannel vs socket TCP benchmark.
Unfortunately currently I'm unable to run 1Gbit test, since my test
machine is slightly broken... So only 100Mbit for now.

Performance graph attached.
Speed is the same, CPU usage is the same 
(socket CPU usage is 1% (or 20% :) more than netchannel one, but let's
throw this away as some experimental error).

Netchannel was setup in copy_to_user mode, so it was not expected to be
faster or eat less CPU, but main purpose of this test was to show that
netchannels with _all_ protocol processing moved to process' context can
be at least that fast as when it is splitted into pieces.
I've found some links in the web and blogs where some developers completely
disagree with VJ idea of moving stuff into process context...
Well, this should break theirs mostly theoretical arguments.

It is clear that using memcpy setup CPU usage numbers (at least) for netchannel 
are noticebly better than for sockets (see previous posted benchmarks). 
I will start changing core networking code to accept different copying 
"actor" methods which will allow to use netchannels preallocated mapped area 
instead of copy_to_user().

Full patch and userspace application are available from netchannel homepage [1].

Thank you.

1. Netchannel homepage.
http://tservice.net.ru/~s0mbre/old/?section=projects&item=netchannel

Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>

-- 
	Evgeniy Polyakov

[-- Attachment #2: netchannel_speed.png --]
[-- Type: image/png, Size: 7126 bytes --]

^ permalink raw reply

* Brauchen Sofort Deutsche Partner
From: Conventions B. Infuriates @ 2006-05-24 21:36 UTC (permalink / raw)
  To: Netdev

Guten Tag,
unser Unternehmen heisst Magnat Trading Group. Wir spezialisieren uns auf Dienstleistungen beim Kaufen und Verkaufen der Ware uber
internationales Onlineauktionshaus EBAY. Dank sehr grossen Angagement, konnte unsere Firma schon nach vier Jahren auf die internationalen
Ebene hinaufsteigen .Und  nach der Aussage der  Wirtschaftsexperten zahlt Magnat Trading Group zu den 20ig der einflussstarksten Firmen in
Bereich Ebay.
Zur Zeit ist die Position des Finanzmanagers in unserem Unternehmen zu besetzen.
Die Einzigen Anforderungen an Sie  sind:
- PC, Internet, E-mail,Telefonnummer
- Ein Konto bei einem  Zahlungsinstitut in Deutschland ist  bevorzugt.
Ihr Honorar betragt am Anfang 500-1000 euro in der Woche.

Sie konnen Ihren Arbeitstag moglichst flexibel gestalten, um Ihrem Haupterwerb problemlos nachzugehen. 
Im Laufe der ganzen Tatigkeit entstehen fur Sie keine Ausgaben, d.h. Sie brauchen also kein Startkapital

Falls unser Angebot Sie neugierig gemacht hat und Sie sich angesprochen fuhlen, dann melden Sie sich einfach per E-MAIL:
magnat_trading@km.ru

Mit besten Grussen!


^ permalink raw reply

* Re: [HAMRADIO] Remove remaining SET_MODULE_OWNER calls from hamradio drivers.
From: Ralf Baechle @ 2006-05-24 10:29 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, linux-hams
In-Reply-To: <4473EF72.7030201@garzik.org>

On Wed, May 24, 2006 at 01:30:26AM -0400, Jeff Garzik wrote:

> Ralf Baechle DL5RB wrote:
> >Signed-off-by: Ralf Baechle DL5RB <ralf@linux-mips.org>
> 
> ACK but does not apply

Of course not, DaveM applied the patch 3 weeks ago.

  Ralf

^ permalink raw reply

* [PATCH] TCP Veno module for kernel 2.6.16.13
From: #ZHOU BIN# @ 2006-05-24 11:08 UTC (permalink / raw)
  To: jmorris; +Cc: netdev

From: Bin Zhou <zhou0022@ntu.edu.sg>

TCP Veno module is a new congestion control module to improve TCP performance over wireless networks. The key innovation in TCP Veno is the enhancement of TCP Reno/Sack congestion control algorithm by using the estimated state of a connection based on TCP Vegas. This scheme significantly reduces "blind" reduction of TCP window regardless of the cause of packet loss.

This work is based on the research paper "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks." C. P. Fu, S. C. Liew, IEEE Journal on Selected Areas in Communication, Feb. 2003.

Original paper and many latest research works on veno can be reached at http://www.ntu.edu.sg/home/ascpfu/veno/veno.html  or through the www.google.com by entering keywords "TCP Veno"



Sign-off-by: Bin Zhou <zhou0022@ntu.edu.sg>
	         Cheng Peng Fu <ascpfu@ntu.edu.sg>


diff -urN linux-2.6.16.13/net/ipv4/Kconfig linux-2.6.16.13-veno/net/ipv4/Kconfig
--- linux-2.6.16.13/net/ipv4/Kconfig	2006-05-03 05:38:44.000000000 +0800
+++ linux-2.6.16.13-veno/net/ipv4/Kconfig	2006-05-20 16:16:44.712926200 +0800
@@ -521,6 +521,18 @@
 	window. TCP Vegas should provide less packet loss, but it is
 	not as aggressive as TCP Reno.
 
+config TCP_CONG_VENO
+	tristate "TCP Veno"
+	depends on EXPERIMENTAL
+	default n
+	---help---
+	TCP Veno is a sender-side only enhancement of TCP to obtain better
+	throughput over wirless networks. TCP Veno makes use of state 
+	distinguishing to circumvent the difficult judgment of the packet loss type.
+	TCP Veno cuts down less congestion window in response to random loss
+	packets. 
+	See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+	
 config TCP_CONG_SCALABLE
 	tristate "Scalable TCP"
 	depends on EXPERIMENTAL
diff -urN linux-2.6.16.13/net/ipv4/Makefile linux-2.6.16.13-veno/net/ipv4/Makefile
--- linux-2.6.16.13/net/ipv4/Makefile	2006-05-03 05:38:44.000000000 +0800
+++ linux-2.6.16.13-veno/net/ipv4/Makefile	2006-05-20 15:57:45.308758200 +0800
@@ -40,6 +40,7 @@
 obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o
 obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o
 obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o
+obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o
 obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
 
 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
diff -urN linux-2.6.16.13/net/ipv4/tcp_veno.c linux-2.6.16.13-veno/net/ipv4/tcp_veno.c
--- linux-2.6.16.13/net/ipv4/tcp_veno.c	1970-01-01 08:00:00.000000000 +0800
+++ linux-2.6.16.13-veno/net/ipv4/tcp_veno.c	2006-05-21 11:11:36.190398400 +0800
@@ -0,0 +1,253 @@
+/*
+ * TCP Veno congestion control
+ *
+ * This is based on the congestion detection/avoidance scheme described in
+ *    C. P. Fu, S. C. Liew.
+ *    "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks."
+ *    IEEE Journal on Selected Areas in Communication,
+ *    Feb. 2003.
+ * 	See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/inet_diag.h>
+
+#include <net/tcp.h>
+
+/* Default values of the Veno variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+static int beta  = 3<<V_PARAM_SHIFT;
+
+
+/* Veno variables */
+struct veno {
+	u8	doing_veno_now;/* if true, do veno for this RTT */
+	u16	cntRTT;		/* # of RTTs measured within last RTT */
+	u32	minRTT;		/* min of RTTs measured within last RTT (in usec) */
+	u32	baseRTT;	/* the min of all Veno RTT measurements seen (in usec) */
+	u32	inc;	/* decide whether to increase cwnd */
+	u32 diff;	/* calculate the diff rate */
+};
+
+/* There are several situations when we must "re-start" Veno:
+ *
+ *  o when a connection is established
+ *  o after an RTO
+ *  o after fast recovery
+ *  o when we send a packet and there is no outstanding
+ *    unacknowledged data (restarting an idle connection)
+ *
+ */
+static inline void veno_enable(struct sock *sk)
+{
+	struct veno *veno = inet_csk_ca(sk);
+
+	/* turn on Veno */
+	veno->doing_veno_now = 1;
+
+	veno->minRTT = 0x7fffffff;
+}
+
+static inline void veno_disable(struct sock *sk)
+{
+	struct veno *veno = inet_csk_ca(sk);
+
+	/* turn off Veno */
+	veno->doing_veno_now = 0;
+}
+
+static void tcp_veno_init(struct sock *sk)
+{
+	struct veno *veno = inet_csk_ca(sk);
+
+	veno->baseRTT = 0x7fffffff;
+	veno->inc = 1;
+	veno_enable(sk);
+}
+
+/* Do RTT sampling needed for Veno. */
+static void tcp_veno_rtt_calc(struct sock *sk, u32 usrtt)
+{
+	struct veno *veno = inet_csk_ca(sk);
+	u32 vrtt = usrtt + 1; /* Never allow zero rtt or baseRTT */
+
+	/* Filter to find propagation delay: */
+	if (vrtt < veno->baseRTT)
+		veno->baseRTT = vrtt;
+
+	/* Find the min RTT during the last RTT to find
+	 * the current prop. delay + queuing delay:
+	 */
+	veno->minRTT = min(veno->minRTT, vrtt);
+	veno->cntRTT++;
+}
+
+static void tcp_veno_state(struct sock *sk, u8 ca_state)
+{
+
+	if (ca_state == TCP_CA_Open)
+		veno_enable(sk);
+	else
+		veno_disable(sk);
+}
+
+/*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Veno calculations
+ * until we get fresh RTT samples.  So when we
+ * restart, we reset our Veno state to a clean
+ * state. After we get acks for this flight of
+ * packets, _then_ we can make Veno calculations
+ * again.
+ */
+static void tcp_veno_cwnd_event(struct sock *sk, enum tcp_ca_event event)
+{
+	if (event == CA_EVENT_CWND_RESTART ||
+	    event == CA_EVENT_TX_START)
+		tcp_veno_init(sk);
+}
+
+static void tcp_veno_cong_avoid(struct sock *sk, u32 ack,
+				 u32 seq_rtt, u32 in_flight, int flag)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct veno *veno = inet_csk_ca(sk); 
+
+	if (!veno->doing_veno_now)
+		return tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag); 
+
+	/* limited by applications */
+	if (!tcp_is_cwnd_limited(sk, in_flight))
+		return;
+
+	/* We do the Veno calculations only if we got enough RTT samples */
+	if (veno->cntRTT <= 2) {
+		/* We don't have enough RTT samples to do the Veno
+		 * calculation, so we'll behave like Reno.
+		 */ 
+		tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
+	} else {
+		u32 rtt, target_cwnd;
+
+		/* We have enough RTT samples, so, using the Veno
+		 * algorithm, we determine the state of the network.
+		 */
+
+		rtt = veno->minRTT;
+
+		target_cwnd = ((tp->snd_cwnd * veno->baseRTT)
+			       << V_PARAM_SHIFT) / rtt;
+		
+		veno->diff = (tp->snd_cwnd << V_PARAM_SHIFT) - target_cwnd;
+		
+		if (tp->snd_cwnd <= tp->snd_ssthresh) {
+			/* Slow start.  */ 
+			tcp_slow_start(tp);
+		} 
+		else if (sysctl_tcp_abc) {
+ 			/* RFC3465: Apppriate Byte Count
+ 	 		* increase once for each full cwnd acked.
+ 	 		* Veno has no idear about it so far, so we keep
+ 	 		* it as Reno.
+ 	 		*/
+ 			if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) {
+ 				tp->bytes_acked -= tp->snd_cwnd*tp->mss_cache;
+ 				if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ 					tp->snd_cwnd++;
+ 			}
+ 		}else {
+			/* Congestion avoidance. */ 
+			if (veno->diff < beta) {
+				/* In the "non-congestive state", increase cwnd
+				 *  every rtt.
+				 */ 
+				if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ 					if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ 						tp->snd_cwnd++;
+ 					tp->snd_cwnd_cnt = 0;
+ 				} else
+ 					tp->snd_cwnd_cnt++;
+			} else {
+				/* In the "congestive state", increase cwnd
+				 * every other rtt.
+				 */ 
+					if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ 						if (veno->inc && tp->snd_cwnd < tp->snd_cwnd_clamp) {
+ 						tp->snd_cwnd++;
+						veno->inc = 0;
+			}
+					else
+						veno->inc = 1;
+ 						tp->snd_cwnd_cnt = 0;
+ 					} else
+ 						tp->snd_cwnd_cnt++;
+			}
+			
+		}
+		if (tp->snd_cwnd < 2)
+			tp->snd_cwnd = 2;
+		else if (tp->snd_cwnd > tp->snd_cwnd_clamp)
+			tp->snd_cwnd = tp->snd_cwnd_clamp;
+	}
+		/* Wipe the slate clean for the next RTT. */
+	/* veno->cntRTT = 0; */
+	veno->minRTT = 0x7fffffff;
+	}
+
+/* Veno MD phase */
+u32 tcp_veno_ssthresh(struct sock *sk)
+{
+	const struct tcp_sock *tp = tcp_sk(sk);
+	struct veno *veno = inet_csk_ca(sk); 
+	if(veno->diff < beta) {
+		/* in "non-congestive state", cut cwnd by 1/5 */ 
+		return max(tp->snd_cwnd*4/5, 2U);
+	}else {
+		/* in "congestive state", cut cwnd by 1/2 */ 
+		return max(tp->snd_cwnd >> 1U, 2U);
+	}
+}
+
+u32 tcp_veno_min_cwnd(struct sock *sk)
+{
+	const struct tcp_sock *tp = tcp_sk(sk); 
+	return tp->snd_ssthresh;
+}
+
+
+static struct tcp_congestion_ops tcp_veno = {
+	.init		= tcp_veno_init,
+	.ssthresh	= tcp_veno_ssthresh,
+	.cong_avoid	= tcp_veno_cong_avoid,
+	.min_cwnd	= tcp_veno_min_cwnd,
+	.rtt_sample	= tcp_veno_rtt_calc,
+	.set_state	= tcp_veno_state, 
+	.cwnd_event	= tcp_veno_cwnd_event,
+
+	.owner		= THIS_MODULE,
+	.name		= "veno",
+};
+
+static int __init tcp_veno_register(void)
+{
+	BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE);
+	tcp_register_congestion_control(&tcp_veno);
+	return 0;
+}
+
+static void __exit tcp_veno_unregister(void)
+{
+	tcp_unregister_congestion_control(&tcp_veno);
+}
+
+module_init(tcp_veno_register);
+module_exit(tcp_veno_unregister);
+
+MODULE_AUTHOR("Bin Zhou, Cheng Peng Fu");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Veno");

^ permalink raw reply

* Re: Please pull 'upstream' branch of wireless-2.6
From: John W. Linville @ 2006-05-24 12:42 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev
In-Reply-To: <4473E288.3030005@garzik.org>

On Wed, May 24, 2006 at 12:35:20AM -0400, Jeff Garzik wrote:
> John W. Linville wrote:
> >The following changes since commit 
> >01d654d25d23fb73deb7904ce1c0b3a0f5fc2908:
> >  John W. Linville:
> >        Merge branch 'upstream-fixes' into upstream
> >
> >are found in the git repository at:
> >
> >  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git 
> >  upstream
> >
> >Marcin Juszkiewicz:
> >      hostap: new pcmcia IDs
> >
> > drivers/net/wireless/hostap/hostap_cs.c |    6 ++++++
> > 1 files changed, 6 insertions(+), 0 deletions(-)
> 
> WTF???  I pull, and see diffstat:
> 
> Merge db21e578e551421d76641d72cb3f8296ed3f9e61, made by recursive.
>  drivers/net/wireless/airo.c                     |    2
...

> This is vastly different from any 'pull upstream' email I've received 
> from you.  It is extremely uncool for me to pull, and receive something 
> other than what your email specified.

Jeff, I am terribly sorry.  I sent a request for this on 24 April,
but it does not appear in the archives.  It must have been dropped
(probably due to size) by the netdev list filters, and I neglected
to notice.

/me wishes the list would send me a note when it drops stuff due
to size...

> Nonetheless, I looked over the changes and they look OK, so I took the 
> lazy route and kept them.
 
I greatly appreciate that!

> For the future, I would perhaps recommend creating an upstream-jeff 
> branch at the time of submission, if you insist upon continuing to push 

The point is well taken.  It probably does make sense either to have an
upstream-jeff branch or to make a new branch if you haven't yet pulled.
I'll keep that in mind.

Thanks,

John
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply

* Re: [PATCH] TCP Veno module for kernel 2.6.16.13
From: Stephen Hemminger @ 2006-05-24 15:04 UTC (permalink / raw)
  To: #ZHOU BIN#; +Cc: jmorris, netdev
In-Reply-To: <A975FFC51622704CBEAB749E263D1799015540B3@mail01.student.main.ntu.edu.sg>

On Wed, 24 May 2006 19:08:05 +0800
"#ZHOU BIN#" <ZHOU0022@ntu.edu.sg> wrote:

> From: Bin Zhou <zhou0022@ntu.edu.sg>
> 
> TCP Veno module is a new congestion control module to improve TCP performance over wireless networks. The key innovation in TCP Veno is the enhancement of TCP Reno/Sack congestion control algorithm by using the estimated state of a connection based on TCP Vegas. This scheme significantly reduces "blind" reduction of TCP window regardless of the cause of packet loss.
> 
> This work is based on the research paper "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks." C. P. Fu, S. C. Liew, IEEE Journal on Selected Areas in Communication, Feb. 2003.
> 
> Original paper and many latest research works on veno can be reached at http://www.ntu.edu.sg/home/ascpfu/veno/veno.html  or through the www.google.com by entering keywords "TCP Veno"
> 
> 
> 
> Sign-off-by: Bin Zhou <zhou0022@ntu.edu.sg>
> 	         Cheng Peng Fu <ascpfu@ntu.edu.sg>

I will put this in my tcp git tree (along with LP and Compound).
Hope you don't mind if I will run it through Lindent first to cleanup whitespace.

^ permalink raw reply

* Re: [PATCH] TCP Veno module for kernel 2.6.16.13
From: James Morris @ 2006-05-24 15:20 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: #ZHOU BIN#, netdev
In-Reply-To: <20060524080449.2c81dc38@localhost.localdomain>

On Wed, 24 May 2006, Stephen Hemminger wrote:

> Hope you don't mind if I will run it through Lindent first to cleanup whitespace.

How about dropping the mixed caps, as well?



-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply

* Re: [PATCH] TCP Veno module for kernel 2.6.16.13
From: Baruch Even @ 2006-05-24 16:16 UTC (permalink / raw)
  To: #ZHOU BIN#; +Cc: jmorris, netdev
In-Reply-To: <A975FFC51622704CBEAB749E263D1799015540B3@mail01.student.main.ntu.edu.sg>

#ZHOU BIN# wrote:
> From: Bin Zhou <zhou0022@ntu.edu.sg>
> +		else if (sysctl_tcp_abc) {
> + 			/* RFC3465: Apppriate Byte Count
> + 	 		* increase once for each full cwnd acked.
> + 	 		* Veno has no idear about it so far, so we keep
> + 	 		* it as Reno.
> + 	 		*/
> + 			if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) {
> + 				tp->bytes_acked -= tp->snd_cwnd*tp->mss_cache;
> + 				if (tp->snd_cwnd < tp->snd_cwnd_clamp)
> + 					tp->snd_cwnd++;
> + 			}

You should prefer to ignore abc instead. At least that's what everyone
else is doing, the only place where abc is active is in NewReno.

Baruch

^ permalink raw reply

* Re: [PATCH] TCP Veno module for kernel 2.6.16.13
From: Stephen Hemminger @ 2006-05-24 16:46 UTC (permalink / raw)
  To: Baruch Even; +Cc: #ZHOU BIN#, jmorris, netdev
In-Reply-To: <447486F4.1050307@ev-en.org>

On Wed, 24 May 2006 17:16:52 +0100
Baruch Even <baruch@ev-en.org> wrote:

> #ZHOU BIN# wrote:
> > From: Bin Zhou <zhou0022@ntu.edu.sg>
> > +		else if (sysctl_tcp_abc) {
> > + 			/* RFC3465: Apppriate Byte Count
> > + 	 		* increase once for each full cwnd acked.
> > + 	 		* Veno has no idear about it so far, so we keep
> > + 	 		* it as Reno.
> > + 	 		*/
> > + 			if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) {
> > + 				tp->bytes_acked -= tp->snd_cwnd*tp->mss_cache;
> > + 				if (tp->snd_cwnd < tp->snd_cwnd_clamp)
> > + 					tp->snd_cwnd++;
> > + 			}
> 
> You should prefer to ignore abc instead. At least that's what everyone
> else is doing, the only place where abc is active is in NewReno.
> 
> Baruch

That was intentional. When ABC was added, the desire was to not change existing
behavior for other congestion control methods.

^ permalink raw reply

* [patch 0/3] bridge patches for 2.6.18
From: Stephen Hemminger @ 2006-05-24 17:12 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

Some stuff for 2.6.18. The most important is adding netlink
support for managing interfaces; this allows building STP
as an application.

--


^ permalink raw reply

* [patch 2/3] bridge: fix module startup error handling
From: Stephen Hemminger @ 2006-05-24 17:12 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20060524171216.706750000@localhost.localdomain>

[-- Attachment #1: bridge-startup-errorhandle.patch --]
[-- Type: text/plain, Size: 1826 bytes --]

Return address in use, if some other kernel code has the SAP.
Propogate out error codes from netfilter registration and unwind.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>


--- br.orig/net/bridge/br.c
+++ br/net/bridge/br.c
@@ -30,36 +30,44 @@ static struct llc_sap *br_stp_sap;
 
 static int __init br_init(void)
 {
+	int err;
+
 	br_stp_sap = llc_sap_open(LLC_SAP_BSPAN, br_stp_rcv);
 	if (!br_stp_sap) {
 		printk(KERN_ERR "bridge: can't register sap for STP\n");
-		return -EBUSY;
+		return -EADDRINUSE;
 	}
 
 	br_fdb_init();
 
-#ifdef CONFIG_BRIDGE_NETFILTER
-	if (br_netfilter_init())
-		return 1;
-#endif
+	err = br_netfilter_init();
+	if (err)
+		goto err_out1;
+
+	err = register_netdevice_notifier(&br_device_notifier);
+	if (err)
+		goto err_out2;
+
 	brioctl_set(br_ioctl_deviceless_stub);
 	br_handle_frame_hook = br_handle_frame;
 
 	br_fdb_get_hook = br_fdb_get;
 	br_fdb_put_hook = br_fdb_put;
 
-	register_netdevice_notifier(&br_device_notifier);
-
 	return 0;
+
+err_out2:
+	br_netfilter_fini();
+err_out1:
+	llc_sap_put(br_stp_sap);
+	return err;
 }
 
 static void __exit br_deinit(void)
 {
 	rcu_assign_pointer(br_stp_sap->rcv_func, NULL);
 
-#ifdef CONFIG_BRIDGE_NETFILTER
 	br_netfilter_fini();
-#endif
 	unregister_netdevice_notifier(&br_device_notifier);
 	brioctl_set(NULL);
 
--- br.orig/net/bridge/br_private.h
+++ br/net/bridge/br_private.h
@@ -192,8 +192,13 @@ extern int br_dev_ioctl(struct net_devic
 extern int br_ioctl_deviceless_stub(unsigned int cmd, void __user *arg);
 
 /* br_netfilter.c */
+#ifdef CONFIG_BRIDGE_NETFILTER
 extern int br_netfilter_init(void);
 extern void br_netfilter_fini(void);
+#else
+#define br_netfilter_init()	(0)
+#define br_netfilter_fini()	do { } while(0)
+#endif
 
 /* br_stp.c */
 extern void br_log_state(const struct net_bridge_port *p);

--


^ permalink raw reply

* [patch 1/3] bridge: optimize conditional in forward path
From: Stephen Hemminger @ 2006-05-24 17:12 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20060524171216.706750000@localhost.localdomain>

[-- Attachment #1: bridge-forward-opt.patch --]
[-- Type: text/plain, Size: 1072 bytes --]

Small optimizations of bridge forwarding path.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>


--- br.orig/net/bridge/br_forward.c
+++ br/net/bridge/br_forward.c
@@ -20,14 +20,11 @@
 #include <linux/netfilter_bridge.h>
 #include "br_private.h"
 
+/* Don't forward packets to originating port or forwarding diasabled */
 static inline int should_deliver(const struct net_bridge_port *p, 
 				 const struct sk_buff *skb)
 {
-	if (skb->dev == p->dev ||
-	    p->state != BR_STATE_FORWARDING)
-		return 0;
-
-	return 1;
+	return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING);
 }
 
 static inline unsigned packet_length(const struct sk_buff *skb)
@@ -55,10 +52,9 @@ int br_dev_queue_push_xmit(struct sk_buf
 
 int br_forward_finish(struct sk_buff *skb)
 {
-	NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
-			br_dev_queue_push_xmit);
+	return NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
+		       br_dev_queue_push_xmit);
 
-	return 0;
 }
 
 static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)

--


^ permalink raw reply

* [patch 3/3] bridge: netlink interface for link management
From: Stephen Hemminger @ 2006-05-24 17:12 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20060524171216.706750000@localhost.localdomain>

[-- Attachment #1: bridge-netlink.patch --]
[-- Type: text/plain, Size: 7922 bytes --]

Add basic netlink support to the Ethernet bridge. Including:
 * dump interfaces in bridges
 * monitor link status changes
 * change state of bridge port

For some demo programs see:
	http://developer.osdl.org/shemminger/prototypes/brnl.tar.gz

These are to allow building a daemon that does alternative implementations
of Spanning Tree Protocol.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>


--- br.orig/net/bridge/Makefile
+++ br/net/bridge/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_BRIDGE) += bridge.o
 
 bridge-y	:= br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
 			br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \
-			br_stp_if.o br_stp_timer.o
+			br_stp_if.o br_stp_timer.o br_netlink.o
 
 bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
 
--- /dev/null
+++ br/net/bridge/br_netlink.c
@@ -0,0 +1,199 @@
+/*
+ *	Bridge netlink control interface
+ *
+ *	Authors:
+ *	Stephen Hemminger		<shemminger@osdl.org>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/rtnetlink.h>
+#include "br_private.h"
+
+/*
+ * Create one netlink message for one interface
+ * Contains port and master info as well as carrier and bridge state.
+ */
+static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port,
+			  u32 pid, u32 seq, int event, unsigned int flags)
+{
+	const struct net_bridge *br = port->br;
+	const struct net_device *dev = port->dev;
+	struct ifinfomsg *r;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+	u32 mtu = dev->mtu;
+	u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+	u8 portstate = port->state;
+
+	pr_debug("br_fill_info event %d port %s master %s\n",
+		 event, dev->name, br->dev->name);
+
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
+	r = NLMSG_DATA(nlh);
+	r->ifi_family = AF_BRIDGE;
+	r->__ifi_pad = 0;
+	r->ifi_type = dev->type;
+	r->ifi_index = dev->ifindex;
+	r->ifi_flags = dev_get_flags(dev);
+	r->ifi_change = 0;
+
+	RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
+
+	RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex);
+
+	if (dev->addr_len)
+		RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
+
+	RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
+	if (dev->ifindex != dev->iflink)
+		RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
+
+
+	RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
+
+	if (event == RTM_NEWLINK)
+		RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate);
+
+	nlh->nlmsg_len = skb->tail - b;
+
+	return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+
+	skb_trim(skb, b - skb->data);
+	return -EINVAL;
+}
+
+/*
+ * Notify listeners of a change in port information
+ */
+void br_ifinfo_notify(int event, struct net_bridge_port *port)
+{
+	struct sk_buff *skb;
+	int err = -ENOMEM;
+
+	pr_debug("bridge notify event=%d\n", event);
+	skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128),
+			GFP_ATOMIC);
+	if (!skb)
+		goto err_out;
+
+	err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0);
+	if (err)
+		goto err_kfree;
+
+	NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
+	netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
+	return;
+
+err_kfree:
+	kfree_skb(skb);
+err_out:
+	netlink_set_err(rtnl, 0, RTNLGRP_LINK, err);
+}
+
+/*
+ * Dump information about all ports, in response to GETLINK
+ */
+static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct net_device *dev;
+	int idx;
+	int s_idx = cb->args[0];
+	int err = 0;
+
+	read_lock(&dev_base_lock);
+	for (dev = dev_base, idx = 0; dev; dev = dev->next) {
+		struct net_bridge_port *p = dev->br_port;
+
+		/* not a bridge port */
+		if (!p)
+			continue;
+
+		if (idx < s_idx)
+			continue;
+
+		err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid,
+				     cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
+		if (err <= 0)
+			break;
+		++idx;
+	}
+	read_unlock(&dev_base_lock);
+
+	cb->args[0] = idx;
+
+	return skb->len;
+}
+
+/*
+ * Change state of port (ie from forwarding to blocking etc)
+ * Used by spanning tree in user space.
+ */
+static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
+{
+	struct rtattr  **rta = arg;
+	struct ifinfomsg *ifm = NLMSG_DATA(nlh);
+	struct net_device *dev;
+	struct net_bridge_port *p;
+	u8 new_state;
+
+	if (ifm->ifi_family != AF_BRIDGE)
+		return -EPFNOSUPPORT;
+
+	/* Must pass valid state as PROTINFO */
+	if (rta[IFLA_PROTINFO-1]) {
+		u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]);
+		new_state = *pstate;
+	} else
+		return -EINVAL;
+
+	if (new_state > BR_STATE_BLOCKING)
+		return -EINVAL;
+
+	/* Find bridge port */
+	dev = __dev_get_by_index(ifm->ifi_index);
+	if (!dev)
+		return -ENODEV;
+
+	p = dev->br_port;
+	if (!p)
+		return -EINVAL;
+
+	/* if kernel STP is running, don't allow changes */
+	if (p->br->stp_enabled)
+		return -EBUSY;
+
+	if (!netif_running(dev))
+		return -ENETDOWN;
+
+	if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)
+		return -ENETDOWN;
+
+	p->state = new_state;
+	br_log_state(p);
+	return 0;
+}
+
+
+static struct rtnetlink_link bridge_rtnetlink_table[RTM_NR_MSGTYPES] = {
+	[RTM_GETLINK - RTM_BASE] = { .dumpit	= br_dump_ifinfo, },
+	[RTM_SETLINK - RTM_BASE] = { .doit      = br_rtm_setlink, },
+};
+
+void __init br_netlink_init(void)
+{
+	rtnetlink_links[PF_BRIDGE] = bridge_rtnetlink_table;
+}
+
+void __exit br_netlink_fini(void)
+{
+	rtnetlink_links[PF_BRIDGE] = NULL;
+}
+
--- br.orig/net/bridge/br_private.h
+++ br/net/bridge/br_private.h
@@ -29,7 +29,7 @@
 
 #define BR_PORT_DEBOUNCE (HZ/10)
 
-#define BR_VERSION	"2.1"
+#define BR_VERSION	"2.2"
 
 typedef struct bridge_id bridge_id;
 typedef struct mac_addr mac_addr;
@@ -237,6 +237,11 @@ extern struct net_bridge_fdb_entry *(*br
 extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
 
 
+/* br_netlink.c */
+extern void br_netlink_init(void);
+extern void br_netlink_fini(void);
+extern void br_ifinfo_notify(int event, struct net_bridge_port *port);
+
 #ifdef CONFIG_SYSFS
 /* br_sysfs_if.c */
 extern struct sysfs_ops brport_sysfs_ops;
--- br.orig/net/bridge/br_notify.c
+++ br/net/bridge/br_notify.c
@@ -14,6 +14,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/rtnetlink.h>
 
 #include "br_private.h"
 
@@ -49,6 +50,7 @@ static int br_device_event(struct notifi
 
 	case NETDEV_CHANGEADDR:
 		br_fdb_changeaddr(p, dev->dev_addr);
+		br_ifinfo_notify(RTM_NEWLINK, p);
 		br_stp_recalculate_bridge_id(br);
 		break;
 
--- br.orig/net/bridge/br_stp_if.c
+++ br/net/bridge/br_stp_if.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
 #include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
 
 #include "br_private.h"
 #include "br_private_stp.h"
@@ -86,6 +87,7 @@ void br_stp_disable_bridge(struct net_br
 void br_stp_enable_port(struct net_bridge_port *p)
 {
 	br_init_port(p);
+	br_ifinfo_notify(RTM_NEWLINK, p);
 	br_port_state_selection(p->br);
 }
 
@@ -99,6 +101,8 @@ void br_stp_disable_port(struct net_brid
 	printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
 	       br->dev->name, p->port_no, p->dev->name, "disabled");
 
+	br_ifinfo_notify(RTM_DELLINK, p);
+
 	wasroot = br_is_root_bridge(br);
 	br_become_designated_port(p);
 	p->state = BR_STATE_DISABLED;
--- br.orig/net/bridge/br.c
+++ br/net/bridge/br.c
@@ -48,6 +48,7 @@ static int __init br_init(void)
 	if (err)
 		goto err_out2;
 
+	br_netlink_init();
 	brioctl_set(br_ioctl_deviceless_stub);
 	br_handle_frame_hook = br_handle_frame;
 
@@ -67,6 +68,7 @@ static void __exit br_deinit(void)
 {
 	rcu_assign_pointer(br_stp_sap->rcv_func, NULL);
 
+	br_netlink_fini();
 	br_netfilter_fini();
 	unregister_netdevice_notifier(&br_device_notifier);
 	brioctl_set(NULL);

--


^ permalink raw reply

* Re: [resend PATCH 1/1] b44: fix ethool link settings support
From: Gary Zambrano @ 2006-05-24 10:21 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev
In-Reply-To: <4474000E.6070804@pobox.com>


The first test is to check if any advertising value is given.
The else path is when advertising == 0.
The b44->flags do not have the same values as the given advertising bits.
When any (or all) of the ADVERTISE_ALL bits are passed to the driver the b44->flags 
are set accordingly.
I think it's ok. 

Thanks,
Gary


On Wed, 2006-05-24 at 02:41 -0400, Jeff Garzik wrote:
> Gary Zambrano wrote:
> > +		if (cmd->advertising & ADVERTISE_ALL) {
> > +			if (cmd->advertising & ADVERTISE_10HALF)
> > +				bp->flags |= B44_FLAG_ADV_10HALF;
> > +			if (cmd->advertising & ADVERTISE_10FULL)
> > +				bp->flags |= B44_FLAG_ADV_10FULL;
> > +			if (cmd->advertising & ADVERTISE_100HALF)
> > +				bp->flags |= B44_FLAG_ADV_100HALF;
> > +			if (cmd->advertising & ADVERTISE_100FULL)
> > +				bp->flags |= B44_FLAG_ADV_100FULL;
> > +		} else {
> > +			bp->flags |= (B44_FLAG_ADV_10HALF |
> > +				      B44_FLAG_ADV_10FULL |
> > +				      B44_FLAG_ADV_100HALF |
> > +				      B44_FLAG_ADV_100FULL);
> > +		}
> 
> The logic above is backwards.  I presume the first test should be
> 	if (!(cmd->advertising & ADVERTISE_ALL))
> 
> The rest looks OK.
> 
> 	Jeff
> 
> 
> 


^ permalink raw reply

* Re: sky2 hw csum failure [was Re: sky2 large MTU problems]
From: Stephen Hemminger @ 2006-05-24 17:38 UTC (permalink / raw)
  To: Daniel J Blueman; +Cc: Netfilter Developer, netdev
In-Reply-To: <6278d2220605240228v576dd66atdad4855b308e64bf@mail.gmail.com>

On Wed, 24 May 2006 10:28:52 +0100
"Daniel J Blueman" <daniel.blueman@gmail.com> wrote:

> Having done some more stress testing with sky2 1.4 (in 2.6.17-rc4) and
> the latest patch, I have found problems when streaming lots of data
> out of the sky2 interface (eg via samba serving a large file to GigE
> client). Ultimately, the interface will stop sending.
> 
> Before this happens, I see lots of:
> 
> kernel: lan0: hw csum failure.
> kernel:  [__skb_checksum_complete+86/96] __skb_checksum_complete+0x56/0x60
> kernel:  [tcp_error+300/512] tcp_error+0x12c/0x200
> kernel:  [poison_obj+41/96] poison_obj+0x29/0x60
> kernel:  [tcp_error+0/512] tcp_error+0x0/0x200
> kernel:  [ip_conntrack_in+157/1072] ip_conntrack_in+0x9d/0x430
> kernel:  [kfree_skbmem+8/128] kfree_skbmem+0x8/0x80
> kernel:  [arp_process+102/1408] arp_process+0x66/0x580
> kernel:  [check_poison_obj+36/416] check_poison_obj+0x24/0x1a0
> kernel:  [arp_process+102/1408] arp_process+0x66/0x580
> kernel:  [nf_iterate+99/144] nf_iterate+0x63/0x90
> kernel:  [ip_rcv_finish+0/608] ip_rcv_finish+0x0/0x260
> kernel:  [nf_hook_slow+89/240] nf_hook_slow+0x59/0xf0
> kernel:  [ip_rcv_finish+0/608] ip_rcv_finish+0x0/0x260
> kernel:  [ip_rcv+386/1104] ip_rcv+0x182/0x450
> kernel:  [ip_rcv_finish+0/608] ip_rcv_finish+0x0/0x260
> kernel:  [packet_rcv_spkt+216/320] packet_rcv_spkt+0xd8/0x140
> kernel:  [netif_receive_skb+476/784] netif_receive_skb+0x1dc/0x310
> kernel:  [sky2_poll+879/2096] sky2_poll+0x36f/0x830
> kernel:  [_spin_lock_irqsave+9/16] _spin_lock_irqsave+0x9/0x10
> kernel:  [run_timer_softirq+290/416] run_timer_softirq+0x122/0x1a0
> kernel:  [net_rx_action+108/256] net_rx_action+0x6c/0x100
> kernel:  [__do_softirq+66/160] __do_softirq+0x42/0xa0
> kernel:  [do_softirq+78/96] do_softirq+0x4e/0x60
> kernel:  =======================
> kernel:  [do_IRQ+90/160] do_IRQ+0x5a/0xa0
> kernel:  [remove_vma+69/80] remove_vma+0x45/0x50
> kernel:  [common_interrupt+26/32] common_interrupt+0x1a/0x20
> kernel:  [get_offset_pmtmr+151/3584] get_offset_pmtmr+0x97/0xe00
> kernel:  [do_gettimeofday+26/208] do_gettimeofday+0x1a/0xd0
> kernel:  [sys_gettimeofday+26/144] sys_gettimeofday+0x1a/0x90
> kernel:  [syscall_call+7/11] syscall_call+0x7/0xb


What ever the netfilter chain is, it is trimming or altering the packet
without clearing or altering the hardware checksum. It is not a driver
problem, we saw these in VLAN's and ebtables already.


> One of these was preceeded by:
> 
> kernel: sky2 lan0: rx error, status 0x977d977d length 0

The receive FIFO got overrun. You must not be running hardware flow
control.

> 
> This was happening with the default MTU of 1500, not just at MTU size
> 9000 (but it was changed down from 9000). Hardware is Yukon-EC (0xb6)
> rev 1.
> 
> I'll do some more stress testing tonight without the MTU patch and
> without the MTU being raised to 9000 initially and see what happens.
> 
> Thanks for all your great work so far!


^ permalink raw reply

* Re: [patch 3/3] bridge: netlink interface for link management
From: jamal @ 2006-05-24 18:11 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, David Miller
In-Reply-To: <20060524171348.001557000@localhost.localdomain>


Very nice.

On Wed, 2006-24-05 at 10:12 -0700, Stephen Hemminger wrote:
> plain text document attachment (bridge-netlink.patch)
> Add basic netlink support to the Ethernet bridge. Including:
>  * dump interfaces in bridges
>  * monitor link status changes
>  * change state of bridge port


> +static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port,
> +			  u32 pid, u32 seq, int event, unsigned int flags)
> +{
> +	const struct net_bridge *br = port->br;
> +	const struct net_device *dev = port->dev;
> +	struct ifinfomsg *r;
> +	struct nlmsghdr *nlh;
> +	unsigned char *b = skb->tail;
> +	u32 mtu = dev->mtu;
> +	u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
> +	u8 portstate = port->state;
> +
> +	pr_debug("br_fill_info event %d port %s master %s\n",
> +		 event, dev->name, br->dev->name);
> +
> +	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
> +	r = NLMSG_DATA(nlh);
> +	r->ifi_family = AF_BRIDGE;
> +	r->__ifi_pad = 0;
> +	r->ifi_type = dev->type;
> +	r->ifi_index = dev->ifindex;
> +	r->ifi_flags = dev_get_flags(dev);
> +	r->ifi_change = 0;
> +
> +	RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
> +
> +	RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex);
> +
> +	if (dev->addr_len)
> +		RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
> +
> +	RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
> +	if (dev->ifindex != dev->iflink)
> +		RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
> +
> +
> +	RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
> +
> +	if (event == RTM_NEWLINK)
> +		RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate);
> +
> +	nlh->nlmsg_len = skb->tail - b;
> +
> +	return skb->len;
> +

Is it desirable to do the above? link events already happen for each
netdevice, no? If not it would probably make more sense to export the
link netlink code (instead of replicating it as above) and just call it
for each netdevice.
I think it is worth reporting all the children (their ifindices) of a
bridge when eventing.

BTW, Where is the bridge state (as in learning, blocking etc) carried? 
Having events for that i would deem as valuable.

> +static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
> +{
> +	struct rtattr  **rta = arg;
> +	struct ifinfomsg *ifm = NLMSG_DATA(nlh);
> +	struct net_device *dev;
> +	struct net_bridge_port *p;
> +	u8 new_state;
> +
> +	if (ifm->ifi_family != AF_BRIDGE)
> +		return -EPFNOSUPPORT;
> +
> +	/* Must pass valid state as PROTINFO */
> +	if (rta[IFLA_PROTINFO-1]) {

Why not a noun like IFLA_BRIDGE_STATE ?


> +	/* if kernel STP is running, don't allow changes */
> +	if (p->br->stp_enabled)
> +		return -EBUSY;

Hopefully above to die some day...

> +
> +	p->state = new_state;
> +	br_log_state(p);

Assuming the above will generate an event which reports things like the
children of the bridge and the STP state of the bridge etc i.e things in
struct net_bridge_port mostly.

cheers,
jamal




^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox