Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] [1/6] pasemi_mac: fix build break in pasemi_mac_probe()
From: David Miller @ 2007-09-26 21:22 UTC (permalink / raw)
  To: olof; +Cc: jgarzik, netdev
In-Reply-To: <20070926212242.GB24168@lixom.net>

From: Olof Johansson <olof@lixom.net>
Date: Wed, 26 Sep 2007 16:22:43 -0500

> pasemi_mac: fix build break in pasemi_mac_probe()
> 
> Fix breakage caused by recent unification of print_mac() stuff.
> 
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>

This one is in net-2.6.24 already, thanks!

^ permalink raw reply

* [PATCH] [6/6] pasemi_mac: pass in count of buffers to replenish rx ring with
From: Olof Johansson @ 2007-09-26 21:25 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev
In-Reply-To: <20070926212200.GA24168@lixom.net>

pasemi_mac: pass in count of buffers to replenish rx ring with

Refactor replenish_rx_ring to take an argument for how many entries to
fill. Since it's normally available from where it's called anyway, this
is just simpler. It also removes the awkward logic to try to figure out
if we're filling for the first time or not.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -375,23 +375,18 @@ static void pasemi_mac_free_rx_resources
 	mac->rx = NULL;
 }
 
-static void pasemi_mac_replenish_rx_ring(struct net_device *dev)
+static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int i;
 	int start = mac->rx->next_to_fill;
-	unsigned int limit, count;
-
-	limit = RING_AVAIL(mac->rx);
-	/* Check to see if we're doing first-time setup */
-	if (unlikely(mac->rx->next_to_clean == 0 && mac->rx->next_to_fill == 0))
-		limit = RX_RING_SIZE;
+	int count;
 
 	if (limit <= 0)
 		return;
 
 	i = start;
-	for (count = limit; count; count--) {
+	for (count = 0; count < limit; count++) {
 		struct pasemi_mac_buffer *info = &RX_DESC_INFO(mac, i);
 		u64 *buff = &RX_BUFF(mac, i);
 		struct sk_buff *skb;
@@ -422,10 +417,10 @@ static void pasemi_mac_replenish_rx_ring
 
 	wmb();
 
-	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), limit - count);
-	write_dma_reg(mac, PAS_DMA_RXINT_INCR(mac->dma_if), limit - count);
+	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), count);
+	write_dma_reg(mac, PAS_DMA_RXINT_INCR(mac->dma_if), count);
 
-	mac->rx->next_to_fill += limit - count;
+	mac->rx->next_to_fill += count;
 }
 
 static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
@@ -543,7 +538,7 @@ static int pasemi_mac_clean_rx(struct pa
 	}
 
 	mac->rx->next_to_clean += limit - count;
-	pasemi_mac_replenish_rx_ring(mac->netdev);
+	pasemi_mac_replenish_rx_ring(mac->netdev, limit-count);
 
 	spin_unlock(&mac->rx->lock);
 
@@ -830,7 +825,7 @@ static int pasemi_mac_open(struct net_de
 	write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
 			   PAS_DMA_TXCHAN_TCMDSTA_EN);
 
-	pasemi_mac_replenish_rx_ring(dev);
+	pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE);
 
 	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
 		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;

^ permalink raw reply

* [PATCH] [5/6] pasemi_mac: don't enable rx before there are buffers on the ring
From: Olof Johansson @ 2007-09-26 21:24 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev
In-Reply-To: <20070926212200.GA24168@lixom.net>

pasemi_mac: don't enable rx before there are buffers on the ring

Reorder initialization of the DMA channels and the interface. Before there
was a time window when the interface was enabled before DMA was enabled.
Also, now there will always be RX buffers available at the time the
MAC interface is enabled, to avoid temporary out-of-buffer errors for the
very first packets (on busy networks).


Signed-off-by: Olof Johansson <olof@lixom.net>


Index: 2.6.23/drivers/net/pasemi_mac.c
===================================================================
--- 2.6.23.orig/drivers/net/pasemi_mac.c
+++ 2.6.23/drivers/net/pasemi_mac.c
@@ -791,14 +791,6 @@ static int pasemi_mac_open(struct net_de
 
 	write_mac_reg(mac, PAS_MAC_CFG_TXP, flags);
 
-	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
-		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
-
-	if (mac->type == MAC_TYPE_GMAC)
-		flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
-	else
-		flags |= PAS_MAC_CFG_PCFG_TSR_10G | PAS_MAC_CFG_PCFG_SPD_10G;
-
 	write_iob_reg(mac, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
 			   PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
 
@@ -813,8 +805,6 @@ static int pasemi_mac_open(struct net_de
 	write_iob_reg(mac, PAS_IOB_DMA_COM_TIMEOUTCFG,
 			   PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
 
-	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
-
 	ret = pasemi_mac_setup_rx_resources(dev);
 	if (ret)
 		goto out_rx_resources;
@@ -842,6 +832,17 @@ static int pasemi_mac_open(struct net_de
 
 	pasemi_mac_replenish_rx_ring(dev);
 
+	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
+		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
+
+	if (mac->type == MAC_TYPE_GMAC)
+		flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
+	else
+		flags |= PAS_MAC_CFG_PCFG_TSR_10G | PAS_MAC_CFG_PCFG_SPD_10G;
+
+	/* Enable interface in MAC */
+	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
+
 	ret = pasemi_mac_phy_init(dev);
 	/* Some configs don't have PHYs (XAUI etc), so don't complain about
 	 * failed init due to -ENODEV.

^ permalink raw reply

* [PATCH] [5/6] pasemi_mac: flags as passed to spin_*_irqsave() should be unsigned long
From: Olof Johansson @ 2007-09-26 21:23 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev
In-Reply-To: <20070926212200.GA24168@lixom.net>

pasemi_mac: flags as passed to spin_*_irqsave() should be unsigned long.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
Signed-off-by: Olof Johansson <olof@lixom.net>

---
Found trying to build a -rt kernel, which has a BUILD_BUG_ON(), in this
caswe.

 drivers/net/pasemi_mac.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -557,7 +557,7 @@ static int pasemi_mac_clean_tx(struct pa
 	struct pas_dma_xct_descr *dp;
 	unsigned int start, count, limit;
 	unsigned int total_count;
-	int flags;
+	unsigned long flags;
 	struct sk_buff *skbs[32];
 	dma_addr_t dmas[32];
 
@@ -978,7 +978,7 @@ static int pasemi_mac_start_tx(struct sk
 	struct pas_dma_xct_descr *dp;
 	u64 dflags, mactx, ptr;
 	dma_addr_t map;
-	int flags;
+	unsigned long flags;
 
 	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_SS | XCT_MACTX_CRC_PAD;
 

^ permalink raw reply

* [PATCH] [3/6] pasemi_mac: set interface speed correctly on XAUI ports
From: Olof Johansson @ 2007-09-26 21:23 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev
In-Reply-To: <20070926212200.GA24168@lixom.net>

pasemi_mac: set interface speed correctly on XAUI ports

Set interface speed for XAUI to 10G per default, not 1G.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: 2.6.23/drivers/net/pasemi_mac.c
===================================================================
--- 2.6.23.orig/drivers/net/pasemi_mac.c
+++ 2.6.23/drivers/net/pasemi_mac.c
@@ -794,7 +794,10 @@ static int pasemi_mac_open(struct net_de
 	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
 		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
 
-	flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
+	if (mac->type == MAC_TYPE_GMAC)
+		flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
+	else
+		flags |= PAS_MAC_CFG_PCFG_TSR_10G | PAS_MAC_CFG_PCFG_SPD_10G;
 
 	write_iob_reg(mac, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
 			   PAS_IOB_DMA_RXCH_CFG_CNTTH(0));

^ permalink raw reply

* [PATCH] [2/6] pasemi_mac: fix build break in pasemi_mac_clean_rx()
From: Olof Johansson @ 2007-09-26 21:23 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev
In-Reply-To: <20070926212200.GA24168@lixom.net>

pasemi_mac: fix build break in pasemi_mac_clean_rx()

Fix breakage caused by the unification of stats structs.


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -530,8 +530,8 @@ static int pasemi_mac_clean_rx(struct pa
 		} else
 			skb->ip_summed = CHECKSUM_NONE;
 
-		dev->stats.rx_bytes += len;
-		dev->stats.rx_packets++;
+		mac->netdev->stats.rx_bytes += len;
+		mac->netdev->stats.rx_packets++;
 
 		skb->protocol = eth_type_trans(skb, mac->netdev);
 		netif_receive_skb(skb);

^ permalink raw reply

* [PATCH] [1/6] pasemi_mac: fix build break in pasemi_mac_probe()
From: Olof Johansson @ 2007-09-26 21:22 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev
In-Reply-To: <20070926212200.GA24168@lixom.net>

pasemi_mac: fix build break in pasemi_mac_probe()

Fix breakage caused by recent unification of print_mac() stuff.


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -1155,7 +1155,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 	struct net_device *dev;
 	struct pasemi_mac *mac;
 	int err;
-	DECLARE_MAC_BUF(mac);
+	DECLARE_MAC_BUF(mac_buf);
 
 	err = pci_enable_device(pdev);
 	if (err)
@@ -1241,7 +1241,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 		       "hw addr %s\n",
 		       dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",
 		       mac->dma_if, mac->dma_txch, mac->dma_rxch,
-		       print_mac(mac, dev->dev_addr));
+		       print_mac(mac_buf, dev->dev_addr));
 
 	return err;
 

^ permalink raw reply

* [PATCH] [0/6] Bugfixes for pasemi_mac
From: Olof Johansson @ 2007-09-26 21:22 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev

Hi,

Following patches are for various bug fixes against current netdev-2.6.24
upstream branch. Please apply.


[PATCH] [1/6] pasemi_mac: fix build break in pasemi_mac_probe()
[PATCH] [2/6] pasemi_mac: fix build break in pasemi_mac_clean_rx()
[PATCH] [3/6] pasemi_mac: set interface speed correctly on XAUI ports
[PATCH] [4/6] pasemi_mac: flags as passed to spin_*_irqsave() should be unsigned long
[PATCH] [5/6] pasemi_mac: don't enable rx before there are buffers on the ring
[PATCH] [6/6] pasemi_mac: pass in count of buffers to replenish rx ring with


Thanks,

-Olof

^ permalink raw reply

* Re: net-2.6.24 rebased...
From: David Miller @ 2007-09-26 20:01 UTC (permalink / raw)
  To: linville; +Cc: netdev, jeff, akpm
In-Reply-To: <20070926124649.GC6171@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Wed, 26 Sep 2007 08:46:49 -0400

> On Tue, Sep 25, 2007 at 11:33:44PM -0700, David Miller wrote:
> 
> > John, one patch didn't go in cleanly after I removed the
> > Z1211 driver.  I put it here for your consideration so it
> > doesn't get lost:
> > 
> > 	http://vger.kernel.org/~davem/0433-Z1211-Fix-TX-status-reports.patch
> > 
> > What probably needs to happen is some other changes that
> > were in z1211 need to go into the non-mac80211 driver and
> > then this patch applies correctly.
> 
> I have that one, so we're fine.  It is a mac80211-specific fix,
> so I think that takes care of it.

Great, thanks to everyone for checking this out.

^ permalink raw reply

* Re: [ofa-general] [PATCH v3] iw_cxgb3: Support "iwarp-only" interfaces to avoid 4-tuple conflicts.
From: Steve Wise @ 2007-09-26 19:02 UTC (permalink / raw)
  To: rdreier, sean.hefty; +Cc: netdev, linux-kernel, general
In-Reply-To: <20070923203649.8324.64524.stgit@dell3.ogc.int>

Rolan/Sean,

What do you all think?

Steve.


Steve Wise wrote:
> iw_cxgb3: Support "iwarp-only" interfaces to avoid 4-tuple conflicts.
> 
> Version 3:
> 
> - don't use list_del_init() where list_del() is sufficient.
> 
> Version 2:
> 
> - added a per-device mutex for the address and listening endpoints lists.
> 
> - wait for all replies if sending multiple passive_open requests to rnic.
> 
> - log warning if no addresses are available when a listen is issued.
> 
> - tested
> 
> ---
> 
> Design:
> 
> The sysadmin creates "for iwarp use only" alias interfaces of the form
> "devname:iw*" where devname is the native interface name (eg eth0) for the
> iwarp netdev device.  The alias label can be anything starting with "iw".
> The "iw" immediately after the ':' is the key used by the iw_cxgb3 driver.
> 
> EG:
> 	ifconfig eth0 192.168.70.123 up
> 	ifconfig eth0:iw1 192.168.71.123 up
> 	ifconfig eth0:iw2 192.168.72.123 up
> 
> In the above example, 192.168.70/24 is for TCP traffic, while
> 192.168.71/24 and 192.168.72/24 are for iWARP/RDMA use.
> 
> The rdma-only interface must be on its own IP subnet. This allows routing
> all rdma traffic onto this interface.
> 
> The iWARP driver must translate all listens on address 0.0.0.0 to the
> set of rdma-only ip addresses for the device in question.  This prevents
> incoming connect requests to the TCP ipaddresses from going up the
> rdma stack.
> 
> Implementation Details:
> 
> - The iw_cxgb3 driver registers for inetaddr events via
> register_inetaddr_notifier().  This allows tracking the iwarp-only
> addresses/subnets as they get added and deleted.  The iwarp driver
> maintains a list of the current iwarp-only addresses.
> 
> - The iw_cxgb3 driver builds the list of iwarp-only addresses for its
> devices at module insert time.  This is needed because the inetaddr
> notifier callbacks don't "replay" address-add events when someone
> registers.  So the driver must build the initial list at module load time.
> 
> - When a listen is done on address 0.0.0.0, then the iw_cxgb3 driver
> must translate that into a set of listens on the iwarp-only addresses.
> This is implemented by maintaining a list of stid/addr entries per
> listening endpoint.
> 
> - When a new iwarp-only address is added or removed, the iw_cxgb3 driver
> must traverse the set of listening endpoints and update them accordingly.
> This allows an application to bind to 0.0.0.0 prior to the iwarp-only
> interfaces being configured.  It also allows changing the iwarp-only set
> of addresses and getting the expected behavior for apps already bound
> to 0.0.0.0.  This is done by maintaining a list of listening endpoints
> off the device struct.
> 
> - The address list, the listening endpoint list, and each list of
> stid/addrs in use per listening endpoint are all protected via a mutex
> per iw_cxgb3 device.
> 
> Signed-off-by: Steve Wise <swise@opengridcomputing.com>
> ---
> 
>  drivers/infiniband/hw/cxgb3/iwch.c    |  125 ++++++++++++++++
>  drivers/infiniband/hw/cxgb3/iwch.h    |   11 +
>  drivers/infiniband/hw/cxgb3/iwch_cm.c |  259 +++++++++++++++++++++++++++------
>  drivers/infiniband/hw/cxgb3/iwch_cm.h |   15 ++
>  4 files changed, 360 insertions(+), 50 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c
> index 0315c9d..d81d46e 100644
> --- a/drivers/infiniband/hw/cxgb3/iwch.c
> +++ b/drivers/infiniband/hw/cxgb3/iwch.c
> @@ -63,6 +63,123 @@ struct cxgb3_client t3c_client = {
>  static LIST_HEAD(dev_list);
>  static DEFINE_MUTEX(dev_mutex);
>  
> +static void insert_ifa(struct iwch_dev *rnicp, struct in_ifaddr *ifa)
> +{
> +	struct iwch_addrlist *addr;
> +
> +	addr = kmalloc(sizeof *addr, GFP_KERNEL);
> +	if (!addr) {
> +		printk(KERN_ERR MOD "%s - failed to alloc memory!\n",
> +		       __FUNCTION__);
> +		return;
> +	}
> +	addr->ifa = ifa;
> +	mutex_lock(&rnicp->mutex);
> +	list_add_tail(&addr->entry, &rnicp->addrlist);
> +	mutex_unlock(&rnicp->mutex);
> +}
> +
> +static void remove_ifa(struct iwch_dev *rnicp, struct in_ifaddr *ifa)
> +{
> +	struct iwch_addrlist *addr, *tmp;
> +
> +	mutex_lock(&rnicp->mutex);
> +	list_for_each_entry_safe(addr, tmp, &rnicp->addrlist, entry) {
> +		if (addr->ifa == ifa) {
> +			list_del(&addr->entry);
> +			kfree(addr);
> +			goto out;
> +		}
> +	}
> +out:
> +	mutex_unlock(&rnicp->mutex);
> +}
> +
> +static int netdev_is_ours(struct iwch_dev *rnicp, struct net_device *netdev)
> +{
> +	int i;
> +
> +	for (i = 0; i < rnicp->rdev.port_info.nports; i++)
> +		if (netdev == rnicp->rdev.port_info.lldevs[i])
> +			return 1;
> +	return 0;
> +}
> +
> +static inline int is_iwarp_label(char *label)
> +{
> +	char *colon;
> +
> +	colon = strchr(label, ':');
> +	if (colon && !strncmp(colon+1, "iw", 2))
> +		return 1;
> +	return 0;
> +}
> +
> +static int nb_callback(struct notifier_block *self, unsigned long event,
> +		       void *ctx)
> +{
> +	struct in_ifaddr *ifa = ctx;
> +	struct iwch_dev *rnicp = container_of(self, struct iwch_dev, nb);
> +
> +	PDBG("%s rnicp %p event %lx\n", __FUNCTION__, rnicp, event);
> +
> +	switch (event) {
> +	case NETDEV_UP:
> +		if (netdev_is_ours(rnicp, ifa->ifa_dev->dev) &&
> +		    is_iwarp_label(ifa->ifa_label)) {
> +			PDBG("%s label %s addr 0x%x added\n",
> +				__FUNCTION__, ifa->ifa_label, ifa->ifa_address);
> +			insert_ifa(rnicp, ifa);
> +			iwch_listeners_add_addr(rnicp, ifa->ifa_address);
> +		}
> +		break;
> +	case NETDEV_DOWN:
> +		if (netdev_is_ours(rnicp, ifa->ifa_dev->dev) &&
> +		    is_iwarp_label(ifa->ifa_label)) {
> +			PDBG("%s label %s addr 0x%x deleted\n",
> +				__FUNCTION__, ifa->ifa_label, ifa->ifa_address);
> +			iwch_listeners_del_addr(rnicp, ifa->ifa_address);
> +			remove_ifa(rnicp, ifa);
> +		}
> +		break;
> +	default:
> +		break;
> +	}
> +	return 0;
> +}
> +
> +static void delete_addrlist(struct iwch_dev *rnicp)
> +{
> +	struct iwch_addrlist *addr, *tmp;
> +
> +	mutex_lock(&rnicp->mutex);
> +	list_for_each_entry_safe(addr, tmp, &rnicp->addrlist, entry) {
> +		list_del(&addr->entry);
> +		kfree(addr);
> +	}
> +	mutex_unlock(&rnicp->mutex);
> +}
> +
> +static void populate_addrlist(struct iwch_dev *rnicp)
> +{
> +	int i;
> +	struct in_device *indev;
> +
> +	for (i = 0; i < rnicp->rdev.port_info.nports; i++) {
> +		indev = in_dev_get(rnicp->rdev.port_info.lldevs[i]);
> +		if (!indev)
> +			continue;
> +		for_ifa(indev)
> +			if (is_iwarp_label(ifa->ifa_label)) {
> +				PDBG("%s label %s addr 0x%x added\n",
> +				     __FUNCTION__, ifa->ifa_label,
> +				     ifa->ifa_address);
> +				insert_ifa(rnicp, ifa);
> +			}
> +		endfor_ifa(indev);
> +	}
> +}
> +
>  static void rnic_init(struct iwch_dev *rnicp)
>  {
>  	PDBG("%s iwch_dev %p\n", __FUNCTION__,  rnicp);
> @@ -70,6 +187,12 @@ static void rnic_init(struct iwch_dev *r
>  	idr_init(&rnicp->qpidr);
>  	idr_init(&rnicp->mmidr);
>  	spin_lock_init(&rnicp->lock);
> +	INIT_LIST_HEAD(&rnicp->addrlist);
> +	INIT_LIST_HEAD(&rnicp->listen_eps);
> +	mutex_init(&rnicp->mutex);
> +	rnicp->nb.notifier_call = nb_callback;
> +	populate_addrlist(rnicp);
> +	register_inetaddr_notifier(&rnicp->nb);
>  
>  	rnicp->attr.vendor_id = 0x168;
>  	rnicp->attr.vendor_part_id = 7;
> @@ -148,6 +271,8 @@ static void close_rnic_dev(struct t3cdev
>  	mutex_lock(&dev_mutex);
>  	list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
>  		if (dev->rdev.t3cdev_p == tdev) {
> +			unregister_inetaddr_notifier(&dev->nb);
> +			delete_addrlist(dev);
>  			list_del(&dev->entry);
>  			iwch_unregister_device(dev);
>  			cxio_rdev_close(&dev->rdev);
> diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h
> index caf4e60..7fa0a47 100644
> --- a/drivers/infiniband/hw/cxgb3/iwch.h
> +++ b/drivers/infiniband/hw/cxgb3/iwch.h
> @@ -36,6 +36,8 @@ #include <linux/mutex.h>
>  #include <linux/list.h>
>  #include <linux/spinlock.h>
>  #include <linux/idr.h>
> +#include <linux/notifier.h>
> +#include <linux/inetdevice.h>
>  
>  #include <rdma/ib_verbs.h>
>  
> @@ -101,6 +103,11 @@ struct iwch_rnic_attributes {
>  	u32 cq_overflow_detection;
>  };
>  
> +struct iwch_addrlist {
> +	struct list_head entry;
> +	struct in_ifaddr *ifa;
> +};
> +
>  struct iwch_dev {
>  	struct ib_device ibdev;
>  	struct cxio_rdev rdev;
> @@ -111,6 +118,10 @@ struct iwch_dev {
>  	struct idr mmidr;
>  	spinlock_t lock;
>  	struct list_head entry;
> +	struct notifier_block nb;
> +	struct list_head addrlist;
> +	struct list_head listen_eps;
> +	struct mutex mutex;
>  };
>  
>  static inline struct iwch_dev *to_iwch_dev(struct ib_device *ibdev)
> diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
> index 1cdfcd4..afc8a48 100644
> --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
> +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
> @@ -1127,23 +1127,149 @@ static int act_open_rpl(struct t3cdev *t
>  	return CPL_RET_BUF_DONE;
>  }
>  
> -static int listen_start(struct iwch_listen_ep *ep)
> +static int wait_for_reply(struct iwch_ep_common *epc)
> +{
> +	PDBG("%s ep %p waiting\n", __FUNCTION__, epc);
> +	wait_event(epc->waitq, epc->rpl_done);
> +	PDBG("%s ep %p done waiting err %d\n", __FUNCTION__, epc, epc->rpl_err);
> +	return epc->rpl_err;
> +}
> +
> +static struct iwch_listen_entry *alloc_listener(struct iwch_listen_ep *ep,
> +						  __be32 addr)
> +{
> +	struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> +	struct iwch_listen_entry *le;
> +
> +	le = kmalloc(sizeof *le, GFP_KERNEL);
> +	if (!le) {
> +		printk(KERN_ERR MOD "%s - failed to alloc memory!\n",
> +		       __FUNCTION__);
> +		return NULL;
> +	}
> +	le->stid = cxgb3_alloc_stid(h->rdev.t3cdev_p,
> +				    &t3c_client, ep);
> +	if (le->stid == -1) {
> +		printk(KERN_ERR MOD "%s - cannot alloc stid.\n",
> +		       __FUNCTION__);
> +		kfree(le);
> +		return NULL;
> +	}
> +	le->addr = addr;
> +	PDBG("%s stid %u addr %x port %x\n", __FUNCTION__, le->stid,
> +	     ntohl(le->addr), ntohs(ep->com.local_addr.sin_port));
> +	return le;
> +}
> +
> +static void dealloc_listener(struct iwch_listen_ep *ep,
> +			     struct iwch_listen_entry *le)
> +{
> +	PDBG("%s stid %u addr %x port %x\n", __FUNCTION__, le->stid,
> +	     ntohl(le->addr), ntohs(ep->com.local_addr.sin_port));
> +	cxgb3_free_stid(ep->com.tdev, le->stid);
> +	kfree(le);
> +}
> +
> +static void dealloc_listener_list(struct iwch_listen_ep *ep)
> +{
> +	struct iwch_listen_entry *le, *tmp;
> +	struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> +
> +	mutex_lock(&h->mutex);
> +	list_for_each_entry_safe(le, tmp, &ep->listeners, entry) {
> +		list_del(&le->entry);
> +		dealloc_listener(ep, le);
> +	}
> +	mutex_unlock(&h->mutex);
> +}
> +
> +static int alloc_listener_list(struct iwch_listen_ep *ep)
> +{
> +	struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> +	struct iwch_addrlist *addr;
> +	struct iwch_listen_entry *le;
> +	int err = 0;
> +	int added=0;
> +	mutex_lock(&h->mutex);
> +	list_for_each_entry(addr, &h->addrlist, entry) {
> +		if (ep->com.local_addr.sin_addr.s_addr == 0 ||
> +		    ep->com.local_addr.sin_addr.s_addr ==
> +		    addr->ifa->ifa_address) {
> +			le = alloc_listener(ep, addr->ifa->ifa_address);
> +			if (!le)
> +				break;
> +			list_add_tail(&le->entry, &ep->listeners);
> +			added++;
> +		}
> +	}
> +	mutex_unlock(&h->mutex);
> +	if (ep->com.local_addr.sin_addr.s_addr != 0 && !added)
> +		err = -EADDRNOTAVAIL;
> +	if (!err && !added)
> +		printk(KERN_WARNING MOD
> +		       "No RDMA interface found for device %s\n",
> +		       pci_name(h->rdev.rnic_info.pdev));
> +	return err;
> +}
> +
> +static int listen_stop_one(struct iwch_listen_ep  *ep, unsigned int stid)
>  {
>  	struct sk_buff *skb;
> -	struct cpl_pass_open_req *req;
> +	struct cpl_close_listserv_req *req;
> +
> +	PDBG("%s stid %u\n", __FUNCTION__, stid);
> +	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
> +	if (!skb) {
> +		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
> +		return -ENOMEM;
> +	}
> +	req = (struct cpl_close_listserv_req *) skb_put(skb, sizeof(*req));
> +	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
> +	req->cpu_idx = 0;
> +	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_LISTSRV_REQ, stid));
> +	skb->priority = 1;
> +	ep->com.rpl_err = 0;
> +	ep->com.rpl_done = 0;
> +	cxgb3_ofld_send(ep->com.tdev, skb);
> +	return wait_for_reply(&ep->com);
> +}
> +
> +static int listen_stop(struct iwch_listen_ep *ep)
> +{
> +	struct iwch_listen_entry *le;
> +	struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> +	int err = 0;
>  
>  	PDBG("%s ep %p\n", __FUNCTION__, ep);
> +	mutex_lock(&h->mutex);
> +	list_for_each_entry(le, &ep->listeners, entry) {
> +		err = listen_stop_one(ep, le->stid);
> +		if (err)
> +			break;
> +	}
> +	mutex_unlock(&h->mutex);
> +	return err;
> +}
> +
> +static int listen_start_one(struct iwch_listen_ep *ep, unsigned int stid,
> +			    __be32 addr, __be16 port)
> +{
> +	struct sk_buff *skb;
> +	struct cpl_pass_open_req *req;
> +
> +	PDBG("%s stid %u addr %x port %x\n", __FUNCTION__, stid, ntohl(addr),
> +	     ntohs(port));
>  	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
>  	if (!skb) {
> -		printk(KERN_ERR MOD "t3c_listen_start failed to alloc skb!\n");
> +		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
>  		return -ENOMEM;
>  	}
>  
>  	req = (struct cpl_pass_open_req *) skb_put(skb, sizeof(*req));
>  	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
> -	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, ep->stid));
> -	req->local_port = ep->com.local_addr.sin_port;
> -	req->local_ip = ep->com.local_addr.sin_addr.s_addr;
> +	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, stid));
> +	req->local_port = port;
> +	req->local_ip = addr;
>  	req->peer_port = 0;
>  	req->peer_ip = 0;
>  	req->peer_netmask = 0;
> @@ -1152,8 +1278,32 @@ static int listen_start(struct iwch_list
>  	req->opt1 = htonl(V_CONN_POLICY(CPL_CONN_POLICY_ASK));
>  
>  	skb->priority = 1;
> +	ep->com.rpl_err = 0;
> +	ep->com.rpl_done = 0;
>  	cxgb3_ofld_send(ep->com.tdev, skb);
> -	return 0;
> +	return wait_for_reply(&ep->com);
> +}
> +
> +static int listen_start(struct iwch_listen_ep *ep)
> +{
> +	struct iwch_listen_entry *le;
> +	struct iwch_dev *h = to_iwch_dev(ep->com.cm_id->device);
> +	int err = 0;
> +
> +	PDBG("%s ep %p\n", __FUNCTION__, ep);
> +	mutex_lock(&h->mutex);
> +	list_for_each_entry(le, &ep->listeners, entry) {
> +		err = listen_start_one(ep, le->stid, le->addr,
> +				 ep->com.local_addr.sin_port);
> +		if (err)
> +			goto fail;
> +	}
> +	mutex_unlock(&h->mutex);
> +	return err;
> +fail:
> +	mutex_unlock(&h->mutex);
> +	listen_stop(ep);
> +	return err;
>  }
>  
>  static int pass_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
> @@ -1170,39 +1320,59 @@ static int pass_open_rpl(struct t3cdev *
>  	return CPL_RET_BUF_DONE;
>  }
>  
> -static int listen_stop(struct iwch_listen_ep *ep)
> -{
> -	struct sk_buff *skb;
> -	struct cpl_close_listserv_req *req;
> -
> -	PDBG("%s ep %p\n", __FUNCTION__, ep);
> -	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
> -	if (!skb) {
> -		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
> -		return -ENOMEM;
> -	}
> -	req = (struct cpl_close_listserv_req *) skb_put(skb, sizeof(*req));
> -	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
> -	req->cpu_idx = 0;
> -	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_LISTSRV_REQ, ep->stid));
> -	skb->priority = 1;
> -	cxgb3_ofld_send(ep->com.tdev, skb);
> -	return 0;
> -}
> -
>  static int close_listsrv_rpl(struct t3cdev *tdev, struct sk_buff *skb,
>  			     void *ctx)
>  {
>  	struct iwch_listen_ep *ep = ctx;
>  	struct cpl_close_listserv_rpl *rpl = cplhdr(skb);
>  
> -	PDBG("%s ep %p\n", __FUNCTION__, ep);
> +	PDBG("%s ep %p stid %u\n", __FUNCTION__, ep, GET_TID(rpl));
> +
>  	ep->com.rpl_err = status2errno(rpl->status);
>  	ep->com.rpl_done = 1;
>  	wake_up(&ep->com.waitq);
>  	return CPL_RET_BUF_DONE;
>  }
>  
> +void iwch_listeners_add_addr(struct iwch_dev *rnicp, __be32 addr)
> +{
> +	struct iwch_listen_ep *listen_ep;
> +	struct iwch_listen_entry *le;
> +
> +	mutex_lock(&rnicp->mutex);
> +	list_for_each_entry(listen_ep, &rnicp->listen_eps, entry) {
> +		if (listen_ep->com.local_addr.sin_addr.s_addr)
> +			continue;
> +		le = alloc_listener(listen_ep, addr);
> +		if (le) {
> +			list_add_tail(&le->entry, &listen_ep->listeners);
> +			listen_start_one(listen_ep, le->stid, addr,
> +					 listen_ep->com.local_addr.sin_port);
> +		}
> +	}
> +	mutex_unlock(&rnicp->mutex);
> +}
> +
> +void iwch_listeners_del_addr(struct iwch_dev *rnicp, __be32 addr)
> +{
> +	struct iwch_listen_ep *listen_ep;
> +	struct iwch_listen_entry *le, *tmp;
> +
> +	mutex_lock(&rnicp->mutex);
> +	list_for_each_entry(listen_ep, &rnicp->listen_eps, entry) {
> +		if (listen_ep->com.local_addr.sin_addr.s_addr)
> +			continue;
> +		list_for_each_entry_safe(le, tmp, &listen_ep->listeners,
> +					 entry)
> +			if (le->addr == addr) {
> +				listen_stop_one(listen_ep, le->stid);
> +				list_del(&le->entry);
> +				dealloc_listener(listen_ep, le);
> +			}
> +	}
> +	mutex_unlock(&rnicp->mutex);
> +}
> +
>  static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb)
>  {
>  	struct cpl_pass_accept_rpl *rpl;
> @@ -1767,8 +1937,7 @@ int iwch_accept_cr(struct iw_cm_id *cm_i
>  		goto err;
>  
>  	/* wait for wr_ack */
> -	wait_event(ep->com.waitq, ep->com.rpl_done);
> -	err = ep->com.rpl_err;
> +	err = wait_for_reply(&ep->com);
>  	if (err)
>  		goto err;
>  
> @@ -1887,31 +2056,23 @@ int iwch_create_listen(struct iw_cm_id *
>  	ep->com.cm_id = cm_id;
>  	ep->backlog = backlog;
>  	ep->com.local_addr = cm_id->local_addr;
> +	INIT_LIST_HEAD(&ep->listeners);
>  
> -	/*
> -	 * Allocate a server TID.
> -	 */
> -	ep->stid = cxgb3_alloc_stid(h->rdev.t3cdev_p, &t3c_client, ep);
> -	if (ep->stid == -1) {
> -		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __FUNCTION__);
> -		err = -ENOMEM;
> +	err = alloc_listener_list(ep);
> +	if (err)
>  		goto fail2;
> -	}
>  
>  	state_set(&ep->com, LISTEN);
>  	err = listen_start(ep);
> -	if (err)
> -		goto fail3;
>  
> -	/* wait for pass_open_rpl */
> -	wait_event(ep->com.waitq, ep->com.rpl_done);
> -	err = ep->com.rpl_err;
>  	if (!err) {
>  		cm_id->provider_data = ep;
> +		mutex_lock(&h->mutex);
> +		list_add_tail(&ep->entry, &h->listen_eps);
> +		mutex_unlock(&h->mutex);
>  		goto out;
>  	}
> -fail3:
> -	cxgb3_free_stid(ep->com.tdev, ep->stid);
> +	dealloc_listener_list(ep);
>  fail2:
>  	cm_id->rem_ref(cm_id);
>  	put_ep(&ep->com);
> @@ -1923,18 +2084,20 @@ out:
>  int iwch_destroy_listen(struct iw_cm_id *cm_id)
>  {
>  	int err;
> +	struct iwch_dev *h = to_iwch_dev(cm_id->device);
>  	struct iwch_listen_ep *ep = to_listen_ep(cm_id);
>  
>  	PDBG("%s ep %p\n", __FUNCTION__, ep);
>  
>  	might_sleep();
> +	mutex_lock(&h->mutex);
> +	list_del(&ep->entry);
> +	mutex_unlock(&h->mutex);
>  	state_set(&ep->com, DEAD);
>  	ep->com.rpl_done = 0;
>  	ep->com.rpl_err = 0;
>  	err = listen_stop(ep);
> -	wait_event(ep->com.waitq, ep->com.rpl_done);
> -	cxgb3_free_stid(ep->com.tdev, ep->stid);
> -	err = ep->com.rpl_err;
> +	dealloc_listener_list(ep);
>  	cm_id->rem_ref(cm_id);
>  	put_ep(&ep->com);
>  	return err;
> diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
> index 6107e7c..23e5a22 100644
> --- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
> +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
> @@ -162,10 +162,19 @@ struct iwch_ep_common {
>  	int rpl_err;
>  };
>  
> -struct iwch_listen_ep {
> -	struct iwch_ep_common com;
> +struct iwch_listen_entry {
> +	struct list_head entry;
>  	unsigned int stid;
> +	__be32 addr;
> +};
> +
> +struct iwch_listen_ep {
> +	struct iwch_ep_common com;	/* Must be first entry! */
> +	struct list_head entry;
> +	struct list_head listeners;
>  	int backlog;
> +	int listen_count;
> +	int listen_rpls;
>  };
>  
>  struct iwch_ep {
> @@ -222,6 +231,8 @@ int iwch_resume_tid(struct iwch_ep *ep);
>  void __free_ep(struct kref *kref);
>  void iwch_rearp(struct iwch_ep *ep);
>  int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, struct l2t_entry *l2t);
> +void iwch_listeners_add_addr(struct iwch_dev *rnicp, __be32 addr);
> +void iwch_listeners_del_addr(struct iwch_dev *rnicp, __be32 addr);
>  
>  int __init iwch_cm_init(void);
>  void __exit iwch_cm_term(void);
> _______________________________________________
> general mailing list
> general@lists.openfabrics.org
> http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general
> 
> To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

^ permalink raw reply

* Re: [RFC] Zero-length write() does not generate a datagram on connected socket
From: Vlad Yasevich @ 2007-09-26 18:47 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Stephen Hemminger, netdev
In-Reply-To: <E1IaNQ7-0004DX-00@gondolin.me.apana.org.au>

Herbert Xu wrote:
> Stephen Hemminger <shemminger@linux-foundation.org> wrote:
>> The bug http://bugzilla.kernel.org/show_bug.cgi?id=5731
>> describes an issue where write() can't be used to generate a zero-length
>> datagram (but send, and sendto do work).
>>
>> I think the following is needed:
>>
>> --- a/net/socket.c      2007-08-20 09:54:28.000000000 -0700
>> +++ b/net/socket.c      2007-09-24 15:31:25.000000000 -0700
>> @@ -777,8 +777,11 @@ static ssize_t sock_aio_write(struct kio
>>        if (pos != 0)
>>                return -ESPIPE;
>>
>> -       if (iocb->ki_left == 0) /* Match SYS5 behaviour */
>> -               return 0;
>> +       if (unlikely(iocb->ki_left == 0)) {
>> +               struct socket *sock = iocb->ki_filp->private_data;
>> +               if (sock->type == SOCK_STREAM)
>> +                       return 0;
>> +       }
> 
> I'm not sure whether all STREAM protocols treat zero-length
> sends as no-ops.  What about SCTP?

0 byte writes are not allowed in SCTP.  A no-op is fine, otherwise
SCTP would return an error.

-vlad

> 
> Put it another way, do we really need to keep the short-circuit
> for SOCK_STREAM?
> 
> Cheers,


^ permalink raw reply

* Re: e100 problems in .23rc8 ?
From: Dave Jones @ 2007-09-26 18:18 UTC (permalink / raw)
  To: Kok, Auke; +Cc: netdev
In-Reply-To: <46FAA083.9020604@intel.com>

On Wed, Sep 26, 2007 at 11:10:11AM -0700, Kok, Auke wrote:
 > Dave Jones wrote:
 > > Last night, I hit this bug during boot up..
 > > http://www.codemonkey.org.uk/junk/e100-2.jpg
 > > 
 > > This morning, I got a mail from a Fedora user of the same
 > > .23-rc8 based kernel that has seen a different trace
 > > also implicating e100..
 > > 
 > > http://www.codemonkey.org.uk/junk/e100.jpg
 > > 
 > > It may be that the two problems are unrelated, and it's
 > > just coincidence that both reports happen to be on an e100,
 > > but the timing is odd.  Have there been other reports
 > > of similar problems recently ?
 > 
 > there hasn't been a change to e100 in two months now - perhaps something slipped
 > into the stack that broke it? If this reproduces, could you bisect?

Yeah, I notice only 3 changes to e100 since .22
I'll see if I can reproduce the first one and bisect.

	Dave

-- 
http://www.codemonkey.org.uk

^ permalink raw reply

* Re: e100 problems in .23rc8 ?
From: Kok, Auke @ 2007-09-26 18:10 UTC (permalink / raw)
  To: Dave Jones; +Cc: netdev
In-Reply-To: <20070926150447.GA3761@redhat.com>

Dave Jones wrote:
> Last night, I hit this bug during boot up..
> http://www.codemonkey.org.uk/junk/e100-2.jpg
> 
> This morning, I got a mail from a Fedora user of the same
> .23-rc8 based kernel that has seen a different trace
> also implicating e100..
> 
> http://www.codemonkey.org.uk/junk/e100.jpg
> 
> It may be that the two problems are unrelated, and it's
> just coincidence that both reports happen to be on an e100,
> but the timing is odd.  Have there been other reports
> of similar problems recently ?

there hasn't been a change to e100 in two months now - perhaps something slipped
into the stack that broke it? If this reproduces, could you bisect?

Auke

^ permalink raw reply

* Re: [RFC] Zero-length write() does not generate a datagram on connected socket
From: Rick Jones @ 2007-09-26 17:17 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Stephen Hemminger, netdev
In-Reply-To: <E1IaNQ7-0004DX-00@gondolin.me.apana.org.au>

Herbert Xu wrote:
> Stephen Hemminger <shemminger@linux-foundation.org> wrote:
> 
>>The bug http://bugzilla.kernel.org/show_bug.cgi?id=5731
>>describes an issue where write() can't be used to generate a zero-length
>>datagram (but send, and sendto do work).
>>
>>I think the following is needed:
>>
>>--- a/net/socket.c      2007-08-20 09:54:28.000000000 -0700
>>+++ b/net/socket.c      2007-09-24 15:31:25.000000000 -0700
>>@@ -777,8 +777,11 @@ static ssize_t sock_aio_write(struct kio
>>       if (pos != 0)
>>               return -ESPIPE;
>>
>>-       if (iocb->ki_left == 0) /* Match SYS5 behaviour */
>>-               return 0;
>>+       if (unlikely(iocb->ki_left == 0)) {
>>+               struct socket *sock = iocb->ki_filp->private_data;
>>+               if (sock->type == SOCK_STREAM)
>>+                       return 0;
>>+       }
> 
> 
> I'm not sure whether all STREAM protocols treat zero-length
> sends as no-ops.  What about SCTP?

I asked Vlad that very question, since SCTP can preserve message 
boundaries. He tells me that a zero-length message is not part of SCTP.

rick jones

^ permalink raw reply

* e100 problems in .23rc8 ?
From: Dave Jones @ 2007-09-26 15:04 UTC (permalink / raw)
  To: netdev

Last night, I hit this bug during boot up..
http://www.codemonkey.org.uk/junk/e100-2.jpg

This morning, I got a mail from a Fedora user of the same
.23-rc8 based kernel that has seen a different trace
also implicating e100..

http://www.codemonkey.org.uk/junk/e100.jpg

It may be that the two problems are unrelated, and it's
just coincidence that both reports happen to be on an e100,
but the timing is odd.  Have there been other reports
of similar problems recently ?

	Dave

-- 
http://www.codemonkey.org.uk

^ permalink raw reply

* [PATCH] [TCP] MIB: Fine-tune reordered ACK's SACK block counting more
From: Ilpo Järvinen @ 2007-09-26 14:07 UTC (permalink / raw)
  To: David Miller; +Cc: Netdev
In-Reply-To: <20070925.224711.26514452.davem@davemloft.net>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 4110 bytes --]

On Tue, 25 Sep 2007, David Miller wrote:

> From: "Ilpo_Järvinen" <ilpo.jarvinen@helsinki.fi>
> Date: Mon, 24 Sep 2007 12:04:07 +0300
> 
> > In case of ACK reordering, the SACK block might be valid in it's
> > time but is already obsoleted since we've received another kind
> > of confirmation about arrival of the segments through snd_una
> > advancement of an earlier packet.
> > 
> > I didn't bother to build distinguishing of valid and invalid
> > SACK blocks but simply made reordered SACK blocks that are too
> > old always not counted regardless of their "real" validity which
> > could be determined by using the ack field of the reordered
> > packet (won't be significant IMHO).
> > 
> > DSACKs can very well be considered useful even in this situation,
> > so won't do any of this for them.
> > 
> > Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
> 
> This looks fine to me, applied.
> 
> If the skipped case is interesting we can add another MIB
> stat for it :-)

Hmm, thought a bit more about it... How about this then? No additional 
counter. Compile tested. Not that I see a large benefit from it, in theory 
could help logging in some malicious attempt cases; we safely discarded in 
such case anyway... ...of course if somebody is paranoid enough one might 
rejoice in it more than I do... :-) Buggy cases will very likely show up 
regardless this reordering corner-case.


From: =?ISO-8859-1?q?Ilpo_J=E4rvinen?= <ilpo.jarvinen@helsinki.fi>
Date: Wed, 26 Sep 2007 14:17:12 +0300
Subject: [PATCH] [TCP] MIB: Fine-tune reordered ACK's SACK block counting more

Check the SACK block against the state that TCP was in at the
time of that ACK. Not really since we can summon just snd_una
back and not snd_nxt but that shouldn't be a problem. Reused
checking code which avoids adding other nasty wrap, etc. holes.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
---
 net/ipv4/tcp_input.c |   17 +++++++++++------
 1 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 259f517..95c8a4a 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1063,7 +1063,7 @@ static void tcp_update_reordering(struct sock *sk, const int metric,
  * be used as an exaggerated estimate.
  */
 static int tcp_is_sackblock_valid(struct tcp_sock *tp, int is_dsack,
-				  u32 start_seq, u32 end_seq)
+				  u32 start_seq, u32 end_seq, u32 snd_una)
 {
 	/* Too far in future, or reversed (interpretation is ambiguous) */
 	if (after(end_seq, tp->snd_nxt) || !before(start_seq, end_seq))
@@ -1076,14 +1076,14 @@ static int tcp_is_sackblock_valid(struct tcp_sock *tp, int is_dsack,
 	/* In outstanding window? ...This is valid exit for DSACKs too.
 	 * start_seq == snd_una is non-sensical (see comments above)
 	 */
-	if (after(start_seq, tp->snd_una))
+	if (after(start_seq, snd_una))
 		return 1;
 
 	if (!is_dsack || !tp->undo_marker)
 		return 0;
 
 	/* ...Then it's D-SACK, and must reside below snd_una completely */
-	if (!after(end_seq, tp->snd_una))
+	if (!after(end_seq, snd_una))
 		return 0;
 
 	if (!before(start_seq, tp->undo_marker))
@@ -1244,16 +1244,21 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 		int fack_count;
 		int dup_sack = (found_dup_sack && (i == first_sack_index));
 
-		if (!tcp_is_sackblock_valid(tp, dup_sack, start_seq, end_seq)) {
+		if (!tcp_is_sackblock_valid(tp, dup_sack, start_seq, end_seq,
+					    tp->snd_una)) {
 			if (dup_sack) {
 				if (!tp->undo_marker)
 					NET_INC_STATS_BH(LINUX_MIB_TCPDSACKIGNOREDNOUNDO);
 				else
 					NET_INC_STATS_BH(LINUX_MIB_TCPDSACKIGNOREDOLD);
 			} else {
-				/* Don't count olds caused by ACK reordering */
+				/* Don't count old SACK blocks caused by ACK
+				 * reordering if it was valid back then
+				 */
 				if ((TCP_SKB_CB(ack_skb)->ack_seq != tp->snd_una) &&
-				    !after(end_seq, tp->snd_una))
+				    tcp_is_sackblock_valid(tp, dup_sack,
+							   start_seq, end_seq,
+							   TCP_SKB_CB(ack_skb)->ack_seq))
 					continue;
 				NET_INC_STATS_BH(LINUX_MIB_TCPSACKDISCARD);
 			}
-- 
1.5.0.6

^ permalink raw reply related

* Re: [PATCH: 2.6.13-15-SMP 3/3] network: concurrentlyrunsoftirqnetwork code on SMP
From: jamal @ 2007-09-26 13:26 UTC (permalink / raw)
  To: John Ye
  Cc: Stephen Hemminger, David Miller, netdev, kuznet, pekkas, jmorris,
	kaber, iceburgue
In-Reply-To: <004d01c7ffe2$b73fec20$ca8510ac@asimco>

On Wed, 2007-26-09 at 10:12 +0800, John Ye wrote:

> cpu hash (srcip + dstip) % nr_cpus, plus checking cpu balance periodically,
> shift cpu by an extra seed value?

That may work maybe even add ipproto as a 3rd tuple; experiments will
tell - you need to be able to generate a random enough traffic pattern.
For example if the traffic pattern is always for your local host the
dstip may not be useful to the hash. 
You could always try the hash tests outside first; look at some of the
jenkins hashes in the kernel

> __do_IRQ has a tendency to collect same IRQ on different CPUs into one CPU
> when NIC is busy(by IRQ_PENDING & IRQ_INPROGRESS control skill). so,
> dispatch the load to SMP here may be good thing(?).

possibly. Or you may wanna tie the NIC IRQ to a CPU. 

cheers,
jamal



^ permalink raw reply

* Re: Userspace network stack and netchannels.
From: Evgeniy Polyakov @ 2007-09-26 13:22 UTC (permalink / raw)
  To: jamal; +Cc: netdev
In-Reply-To: <1190812125.4257.2.camel@localhost>

Hi Jamal.

On Wed, Sep 26, 2007 at 09:08:45AM -0400, jamal (hadi@cyberus.ca) wrote:
> Those numbers look impressive. How mysterious do things get in SMP?
> Sorry havent had time to stare at the code. How do you measure cpu you
> quoted?

I did not checked how netchannels and userspace stack behaves on SMP
just because I do not have SMP test machines. Getting into account that
netchannels have smaller number of locks (actually only one to queue
skb) compared to sockets, it should not behave worse, but I did not test
that.

CPU usage was obtained via /proc/$pid statistics.

-- 
	Evgeniy Polyakov

^ permalink raw reply

* Re: [RFC][NET_SCHED] explict hold dev tx lock
From: jamal @ 2007-09-26 13:11 UTC (permalink / raw)
  To: David Miller; +Cc: herbert, netdev, kaber, dada1, johnpol
In-Reply-To: <20070925.192811.08341847.davem@davemloft.net>

On Tue, 2007-25-09 at 19:28 -0700, David Miller wrote:

> I've applied this to net-2.6.24, although I want to study more deeply
> the implications of this change myself at some point :)

sounds reasonable. Ive done a lot of testing with my 2-3 NIC variants;
ive cced whoever i thought was a stakeholder and they ALL seemed
silently-happy-joyous (wink;->), so letting more people go at it is the
best thing to do. I will be watching that space.

cheers,
jamal


^ permalink raw reply

* Re: Userspace network stack and netchannels.
From: jamal @ 2007-09-26 13:08 UTC (permalink / raw)
  To: Evgeniy Polyakov; +Cc: netdev
In-Reply-To: <20070925180043.GA16698@2ka.mipt.ru>

Evgeniy,

Those numbers look impressive. How mysterious do things get in SMP?
Sorry havent had time to stare at the code. How do you measure cpu you
quoted?

cheers,
jamal





^ permalink raw reply

* Re: net-2.6.24 rebased...
From: John W. Linville @ 2007-09-26 12:46 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, jeff, akpm
In-Reply-To: <20070925.233344.43202361.davem@davemloft.net>

On Tue, Sep 25, 2007 at 11:33:44PM -0700, David Miller wrote:

> John, one patch didn't go in cleanly after I removed the
> Z1211 driver.  I put it here for your consideration so it
> doesn't get lost:
> 
> 	http://vger.kernel.org/~davem/0433-Z1211-Fix-TX-status-reports.patch
> 
> What probably needs to happen is some other changes that
> were in z1211 need to go into the non-mac80211 driver and
> then this patch applies correctly.

I have that one, so we're fine.  It is a mac80211-specific fix,
so I think that takes care of it.

Thanks!

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

^ permalink raw reply

* Re: [SCTP PULL Request]: Bug fixes for 2.6.23
From: Vlad Yasevich @ 2007-09-26 13:02 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, lksctp-developers
In-Reply-To: <20070925.225330.60538571.davem@davemloft.net>

David Miller wrote:
> From: Vlad Yasevich <vladislav.yasevich@hp.com>
> Date: Mon, 24 Sep 2007 16:59:25 -0400
> 
>> Can you please pull the following changes since commit a41d3015c11a4e864b95cb57f579f2d8f40cd41b:
> 
> I had to apply this by hand because:
> 
>>   David S. Miller (1):
>>         Revert "PCI: disable MSI by default on systems with Serverworks HT1000 chips"
> 
> You did this work on a very old tree of mine that I redid
> at one point.  This MSI changeset I yanked out of my net-2.6
> tree during a rebase, so if I pull I get the thing back
> which I definitely don't want :-)
> 
> Just to let you know what's happening and why I couldn't
> pull directly from your tree into mine.

Sorry, this was my fault.  I forgot the -f when I pushed out the changes.  That
should have updated the tree.

/me adds a + to the push line.

-vlad


^ permalink raw reply

* Re: Userspace network stack and netchannels.
From: Robert Iakobashvili @ 2007-09-26 10:43 UTC (permalink / raw)
  To: Evgeniy Polyakov; +Cc: netdev
In-Reply-To: <20070926085303.GB13187@2ka.mipt.ru>

On 9/26/07, Evgeniy Polyakov <johnpol@2ka.mipt.ru> wrote:
> > > http://tservice.net.ru/~s0mbre/blog/devel/networking/2006_10_26.html
> > > http://tservice.net.ru/~s0mbre/blog/devel/networking/2006_12_21.html
> > >
> >
> > Very interesting. Are there any details of your benchmarking available,
> > namely, how it was done?
> > Have you some comparison profiling data (oprofile) to figure out where
> > the advantages are coming from?

> My analysis says that reduced number of syscalls is
> main improvement factor,
Great! Just oprofile of the comparison tests is of my curiosity.

> but different (non-rfc-compliant) congestion
> control allows faster start and faster recovery.

People like compliance to standards, even if it decreases performance.
:) Take care.

-- 
Sincerely,
Robert Iakobashvili,
coroberti %x40 gmail %x2e com
...........................................................
http://curl-loader.sourceforge.net
A web testing and traffic generation tool.

^ permalink raw reply

* Re: [PATCH] ipg: add IP1000A driver to kernel tree
From: linux @ 2007-09-26  9:46 UTC (permalink / raw)
  To: netdev

(Resend to netdev; already sent to relevant individuals.)

Here's a possible fix for the p[] array issues akpm noticed.
This replaces them with calls to a new mdio_write_bits function.

Boot-tested, passes net traffic, and mii-tool and mii-diag produce sensible
output (including noticing link status changes).

Also, regarding
>> +	for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
>> +		offset = (u32) &sp->txd[i].next_desc - (u32) sp->txd;
>> +		printk(KERN_INFO "%2.2x %4.4x TFDNextPtr = %16.16lx\n", i,
>> +		       offset, (unsigned long) sp->txd[i].next_desc);
>> +
>> +		offset = (u32) &sp->txd[i].tfc - (u32) sp->txd;
>
> Is the u32 cast safe here on all architectures?

IPG_TFDLIST_LENGTH is 256, and sp->txd is an array of struct ipg_tx,
which are 24 bytes each, so the most it can be is 6K.  The result fits
into 32 bits, so the inputs can be safely truncated.

A more awkward way to write it would be
	offset = i * sizeof(struct ipg_tx) + offsetof(struct ipg_tx, tfc);


This patch is placed in the public domain; copyright abandoned.

(The final hunk is a space-TAB whitespace repair that git complained about
when I imported the patch.)

diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 87a674c..6267a34 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -180,12 +180,31 @@ static u16 read_phy_bit(void __iomem * ioaddr, u8 phyctrlpolarity)
 }
 
 /*
+ * Transmit the given bits, MSB-first, through the MgmtData bit (bit 1)
+ * of the PhyCtrl register. 1 <= len <= 32.  "ioaddr" is the register
+ * address, and "otherbits" are the values of the other bits.
+ */
+static void mdio_write_bits(void __iomem *ioaddr, u8 otherbits, u32 data, unsigned len)
+{
+	otherbits |= IPG_PC_MGMTDIR;
+	do {
+		/* IPG_PC_MGMTDATA is a power of 2; compiler knows to shift */
+		u8 d = ((data >> --len) & 1) * IPG_PC_MGMTDATA;
+		/* + rather than | lets compiler microoptimize better */
+		ipg_drive_phy_ctl_low_high(ioaddr, d + otherbits);
+	} while (len);
+}
+
+/*
  * Read a register from the Physical Layer device located
  * on the IPG NIC, using the IPG PHYCTRL register.
  */
 static int mdio_read(struct net_device * dev, int phy_id, int phy_reg)
 {
 	void __iomem *ioaddr = ipg_ioaddr(dev);
+	u8 const polarity = ipg_r8(PHY_CTRL) &
+			(IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
+	unsigned i, data = 0;
 	/*
 	 * The GMII mangement frame structure for a read is as follows:
 	 *
@@ -199,75 +218,30 @@ static int mdio_read(struct net_device * dev, int phy_id, int phy_reg)
 	 * D = bit of read data (MSB first)
 	 *
 	 * Transmission order is 'Preamble' field first, bits transmitted
-	 * left to right (first to last).
+	 * left to right (msbit-first).
 	 */
-	struct {
-		u32 field;
-		unsigned int len;
-	} p[] = {
-		{ GMII_PREAMBLE,	32 },	/* Preamble */
-		{ GMII_ST,		2  },	/* ST */
-		{ GMII_READ,		2  },	/* OP */
-		{ phy_id,		5  },	/* PHYAD */
-		{ phy_reg,		5  },	/* REGAD */
-		{ 0x0000,		2  },	/* TA */
-		{ 0x0000,		16 },	/* DATA */
-		{ 0x0000,		1  }	/* IDLE */
-	};
-	unsigned int i, j;
-	u8 polarity, data;
-
-	polarity  = ipg_r8(PHY_CTRL);
-	polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
-
-	/* Create the Preamble, ST, OP, PHYAD, and REGAD field. */
-	for (j = 0; j < 5; j++) {
-		for (i = 0; i < p[j].len; i++) {
-			/* For each variable length field, the MSB must be
-			 * transmitted first. Rotate through the field bits,
-			 * starting with the MSB, and move each bit into the
-			 * the 1st (2^1) bit position (this is the bit position
-			 * corresponding to the MgmtData bit of the PhyCtrl
-			 * register for the IPG).
-			 *
-			 * Example: ST = 01;
-			 *
-			 *          First write a '0' to bit 1 of the PhyCtrl
-			 *          register, then write a '1' to bit 1 of the
-			 *          PhyCtrl register.
-			 *
-			 * To do this, right shift the MSB of ST by the value:
-			 * [field length - 1 - #ST bits already written]
-			 * then left shift this result by 1.
-			 */
-			data  = (p[j].field >> (p[j].len - 1 - i)) << 1;
-			data &= IPG_PC_MGMTDATA;
-			data |= polarity | IPG_PC_MGMTDIR;
-
-			ipg_drive_phy_ctl_low_high(ioaddr, data);
-		}
-	}
-
-	send_three_state(ioaddr, polarity);
-
-	read_phy_bit(ioaddr, polarity);
+	mdio_write_bits(ioaddr, polarity, GMII_PREAMBLE, 32);
+	mdio_write_bits(ioaddr, polarity, GMII_ST<<12 | GMII_READ << 10 |
+	                                  phy_id << 5 | phy_reg, 14);
 
 	/*
 	 * For a read cycle, the bits for the next two fields (TA and
 	 * DATA) are driven by the PHY (the IPG reads these bits).
 	 */
-	for (i = 0; i < p[6].len; i++) {
-		p[6].field |=
-		    (read_phy_bit(ioaddr, polarity) << (p[6].len - 1 - i));
-	}
+	send_three_state(ioaddr, polarity);	/* TA first bit */
+	(void)read_phy_bit(ioaddr, polarity);		/* TA second bit */
 
+	for (i = 0; i < 16; i++)
+		data += data + read_phy_bit(ioaddr, polarity);
+
+	/* Trailing idle */
 	send_three_state(ioaddr, polarity);
 	send_three_state(ioaddr, polarity);
 	send_three_state(ioaddr, polarity);
 	send_end(ioaddr, polarity);
 
 	/* Return the value of the DATA field. */
-	return p[6].field;
+	return data;
 }
 
 /*
@@ -277,6 +251,8 @@ static int mdio_read(struct net_device * dev, int phy_id, int phy_reg)
 static void mdio_write(struct net_device *dev, int phy_id, int phy_reg, int val)
 {
 	void __iomem *ioaddr = ipg_ioaddr(dev);
+	u8 const polarity = ipg_r8(PHY_CTRL) &
+			(IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
 	/*
 	 * The GMII mangement frame structure for a read is as follows:
 	 *
@@ -290,66 +266,18 @@ static void mdio_write(struct net_device *dev, int phy_id, int phy_reg, int val)
 	 * D = bit of write data (MSB first)
 	 *
 	 * Transmission order is 'Preamble' field first, bits transmitted
-	 * left to right (first to last).
+	 * left to right (msbit-first).
 	 */
-	struct {
-		u32 field;
-		unsigned int len;
-	} p[] = {
-		{ GMII_PREAMBLE,	32 },	/* Preamble */
-		{ GMII_ST,		2  },	/* ST */
-		{ GMII_WRITE,		2  },	/* OP */
-		{ phy_id,		5  },	/* PHYAD */
-		{ phy_reg,		5  },	/* REGAD */
-		{ 0x0002,		2  },	/* TA */
-		{ val & 0xffff,		16 },	/* DATA */
-		{ 0x0000,		1  }	/* IDLE */
-	};
-	unsigned int i, j;
-	u8 polarity, data;
-
-	polarity  = ipg_r8(PHY_CTRL);
-	polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
-
-	/* Create the Preamble, ST, OP, PHYAD, and REGAD field. */
-	for (j = 0; j < 7; j++) {
-		for (i = 0; i < p[j].len; i++) {
-			/* For each variable length field, the MSB must be
-			 * transmitted first. Rotate through the field bits,
-			 * starting with the MSB, and move each bit into the
-			 * the 1st (2^1) bit position (this is the bit position
-			 * corresponding to the MgmtData bit of the PhyCtrl
-			 * register for the IPG).
-			 *
-			 * Example: ST = 01;
-			 *
-			 *          First write a '0' to bit 1 of the PhyCtrl
-			 *          register, then write a '1' to bit 1 of the
-			 *          PhyCtrl register.
-			 *
-			 * To do this, right shift the MSB of ST by the value:
-			 * [field length - 1 - #ST bits already written]
-			 * then left shift this result by 1.
-			 */
-			data  = (p[j].field >> (p[j].len - 1 - i)) << 1;
-			data &= IPG_PC_MGMTDATA;
-			data |= polarity | IPG_PC_MGMTDIR;
-
-			ipg_drive_phy_ctl_low_high(ioaddr, data);
-		}
-	}
+	mdio_write_bits(ioaddr, polarity, GMII_PREAMBLE, 32);
+	mdio_write_bits(ioaddr, polarity, GMII_ST << 14 | GMII_WRITE << 12 |
+	                                  phy_id << 7 | phy_reg << 2 |
+					  0x2, 16);
+	mdio_write_bits(ioaddr, polarity, val, 16);	/* DATA */
 
 	/* The last cycle is a tri-state, so read from the PHY. */
-	for (j = 7; j < 8; j++) {
-		for (i = 0; i < p[j].len; i++) {
-			ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | polarity);
-
-			p[j].field |= ((ipg_r8(PHY_CTRL) &
-				IPG_PC_MGMTDATA) >> 1) << (p[j].len - 1 - i);
-
-			ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | polarity);
-		}
-	}
+	ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | polarity);
+	(void)ipg_r8(PHY_CTRL);
+	ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | polarity);
 }
 
 /* Set LED_Mode JES20040127EEPROM */
@@ -1484,7 +1412,7 @@ static int ipg_nic_rx(struct net_device *dev)
 				 * Indicate IP checksums were performed
 				 * by the IPG.
 				 *
-			 	skb->ip_summed = CHECKSUM_UNNECESSARY;
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
 			 } else
 			 */
 			 {

^ permalink raw reply related

* Re: PROBLEM: 2.6.23-rc "NETDEV WATCHDOG: eth0: transmit timed out"
From: Karl Meyer @ 2007-09-26  9:07 UTC (permalink / raw)
  To: Francois Romieu; +Cc: Michal Piotrowski, linux-kernel, netdev
In-Reply-To: <20070912205025.GA31709@electric-eye.fr.zoreil.com>

Hi Francois,

this is what I found and sent:

The error exists from patch 2 on. I did some network testing with
patch 1 and currently use it and have no errors so far.
>From my experiences up to now patch 1 should be error free.

Do you need additional info?

2007/9/12, Francois Romieu <romieu@fr.zoreil.com>:
> Karl Meyer <adhocrocker@gmail.com> :
> [...]
> > am am looking for this issue for some time now, but there where no
> > errors in 2.6.22-r2 (gentoo speak, I guess this is 2.6.22.2
> > officially), I also ran git-bisect (for more information see the older
> > messages in this thread).
>
> 2.6.22-r2 in gentoo is based on 2.6.22.1. It is way before
> 0e4851502f846b13b29b7f88f1250c980d57e944 that you reported to work.
> Thus it is not surprizing that it works.
>
> Any update regarding the patchkit that I sent on 2007/08/16 ?
>
> It would help to narrow the culprit.
>
> --
> Ueimor
>

^ 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