Netdev List
 help / color / mirror / Atom feed
* RE: [openib-general] [PATCH v2 1/2] iWARP Connection Manager.
From: Sean Hefty @ 2006-06-13 21:36 UTC (permalink / raw)
  To: 'Steve Wise', Tom Tucker
  Cc: Andrew Morton, netdev, rdreier, linux-kernel, openib-general
In-Reply-To: <1150230871.17394.68.camel@stevo-desktop>

>> Er...no. It will lose this event. Depending on the event...the carnage
>> varies. We'll take a look at this.
>>
>
>This behavior is consistent with the Infiniband CM (see
>drivers/infiniband/core/cm.c function cm_recv_handler()).  But I think
>we should at least log an error because a lost event will usually stall
>the rdma connection.

I believe that there's a difference here.  For the Infiniband CM, an allocation
error behaves the same as if the received MAD were lost or dropped.  Since MADs
are unreliable anyway, it's not so much that an IB CM event gets lost, as it
doesn't ever occur.  A remote CM should retry the send, which hopefully allows
the connection to make forward progress.

- Sean

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: David Miller @ 2006-06-13 21:26 UTC (permalink / raw)
  To: lkml; +Cc: jheffner, torvalds, linux-kernel, netdev
In-Reply-To: <448F0D4B.30201@rtr.ca>

From: Mark Lord <lkml@rtr.ca>
Date: Tue, 13 Jun 2006 15:08:59 -0400

> Err.. no, the networking stack simply decided to become incompatible
> with certain sites, as a result of the user adding more RAM to their
> machine.

Let's discuss some facts.

First, you are getting window scaling by default with the older
kernel too.  It's just a smaller window scale, using a shift
value of say 1 or 2.

What these broken middle boxes do is ignore the window scale
entirely.

So they don't apply a window scale to the advertised windows in each
packet.  Therefore, they think a smaller amount of window space is
being advertised than really is.  So they will silently drop packets
they think is outside of this bogus window they've calculated.

Now, when the window scale is smaller, the connection can still limp
along, albeit slowly, making forward progress even in the face of such
broken devices because half or a quarter of the window is still
available.  It will retransmit a lot, and the congestion window won't
grow at all.

When the window scale is larger, this middle box bug makes it such
that not even one packet can fit into the miscalculated window and
things wedge.  The box thinks that your window is "94" instead of
"94 << WINDOW_SCALE".

I think OpenBSD's claim (they did have the bug and probably still do
for all that I know) was that they wanted to make their firewalling
"stateless".  This is a bogus argument because by definition you
cannot interpret the TCP window without having seen the initial
connection startup where the parameters are negotiated, and in
particular the window scale which will be used.

And you want to say we should try to work around systems designed
by people who think this is ok? :-)

It is impossible to fill a cross-continental connection without using
window scaling.  A 64K window is all you get without scaling.  Big
buffers are absolutely necessary, and as John Heffner showed this need
is growing exponentially and not slowing down.  6 megabit downlink is
pretty commonplace in the US, and the standard is much higher in well
connected countries such as South Korea.

Also, as John Heffner mentioned, even if we could detect the broken
boxes you can't just "turn off window scaling" after it's been
negotiated.  It's immutably active for the entire connection once
enabled.

Window scaling has been standardized and around for 14 years, RFC1323
was published in May of 1992.  How much longer can we wait for it
to be deployed properly? :-)

So the broken boxes, which to be honest are few and far between these
days, need to go, they really do.

^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Daniel Phillips @ 2006-06-13 21:12 UTC (permalink / raw)
  To: bidulock; +Cc: Stephen Hemminger, Sridhar Samudrala, netdev, linux-kernel
In-Reply-To: <20060613052215.B27858@openss7.org>

Brian F. G. Bidulock wrote:
> Stephen,
> 
> On Tue, 13 Jun 2006, Stephen Hemminger wrote:
> 
> 
>>>@@ -2176,3 +2279,13 @@ EXPORT_SYMBOL(sock_wake_async);
>>> EXPORT_SYMBOL(sockfd_lookup);
>>> EXPORT_SYMBOL(kernel_sendmsg);
>>> EXPORT_SYMBOL(kernel_recvmsg);
>>>+EXPORT_SYMBOL(kernel_bind);
>>>+EXPORT_SYMBOL(kernel_listen);
>>>+EXPORT_SYMBOL(kernel_accept);
>>>+EXPORT_SYMBOL(kernel_connect);
>>>+EXPORT_SYMBOL(kernel_getsockname);
>>>+EXPORT_SYMBOL(kernel_getpeername);
>>>+EXPORT_SYMBOL(kernel_getsockopt);
>>>+EXPORT_SYMBOL(kernel_setsockopt);
>>>+EXPORT_SYMBOL(kernel_sendpage);
>>>+EXPORT_SYMBOL(kernel_ioctl);
>>
>>Don't we want to restrict this to GPL code with EXPORT_SYMBOL_GPL?
> 
> 
> There are direct derivatives of the BSD/POSIX system call
> interface.  The protocol function pointers within the socket
> structure are not GPL only.  Why make this wrappered access to
> them GPL only?  It will only encourange the reverse of what they
> were intended to do: be used instead of the protocol function
> pointers within the socket structure, that currently carry no
> such restriction.

This has the makings of a nice stable internal kernel api.  Why do we want
to provide this nice stable internal api to proprietary modules?

Regards,

Daniel

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: Barry K. Nathan @ 2006-06-13 20:45 UTC (permalink / raw)
  To: John Heffner; +Cc: Linus Torvalds, Mark Lord, Linux Kernel, netdev, davem
In-Reply-To: <448F03B3.5040501@psc.edu>

On 6/13/06, John Heffner <jheffner@psc.edu> wrote:
> Though I haven't gotten my hands on it, I believe Windows will soon have
> this capability, too.  I'm sure Windows is big enough that whenever they
> turn this on, it will flush out all these boxes pretty quickly.  We
> could wait for them to do it first, that that's not my favored approach.

Yes, that appears to be the case with Windows Vista:
http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec_blog_tcpip_2.aspx

*However*, they're also adding "black hole detection", for working
around broken boxes that drop ICMP. And that kinda makes me wonder how
long they're going to stick to their guns for enabling window scaling.
(For instance, if too many sites break, maybe they'll disable it again
with Vista Service Pack 1 or something.)
-- 
-Barry K. Nathan <barryn@pobox.com>

^ permalink raw reply

* Re: [PATCH] [2.6.17-rc6] Section mismatch in drivers/net/ne.o during modpost
From: Sam Ravnborg @ 2006-06-13 20:38 UTC (permalink / raw)
  To: Keith Owens
  Cc: Mikael Pettersson, rdunlap, akpm, jgarzik, linux-kernel, netdev
In-Reply-To: <10735.1150176929@kao2.melbourne.sgi.com>

 
> Probably over enthusiastic gcc inlining.  gcc 4 will inline functions
> that are not declared as inline.  That is not so bad, except that some
> versions of gcc will ignore a mismatch in function attributes and
> inline a __init function into normal text, generating additional
> section mismatches.
When using -ffunction-sections (or similar) then we ask gcc to put each
function in separate sections. In this case it is OK to mix sections.
But I agree, gcc should not mix user specified sections.

> For a specific example, see
> 
> http://marc.theaimsgroup.com/?l=linux-kernel&m=113824309203482&w=2
That's a good example - thanks!

	Sam

^ permalink raw reply

* Re: [PATCH v2 1/2] iWARP Connection Manager.
From: Steve Wise @ 2006-06-13 20:34 UTC (permalink / raw)
  To: Tom Tucker
  Cc: Andrew Morton, rdreier, mshefty, linux-kernel, netdev,
	openib-general
In-Reply-To: <1150127698.22704.9.camel@trinity.ogc.int>

<snip>

> > > +static void cm_event_handler(struct iw_cm_id *cm_id,
> > > +			     struct iw_cm_event *iw_event) 
> > > +{
> > > +	struct iwcm_work *work;
> > > +	struct iwcm_id_private *cm_id_priv;
> > > +	unsigned long flags;
> > > +
> > > +	work = kmalloc(sizeof(*work), GFP_ATOMIC);
> > > +	if (!work)
> > > +		return;
> > 
> > This allocation _will_ fail sometimes.  The driver must recover from it. 
> > Will it do so?
> 
> Er...no. It will lose this event. Depending on the event...the carnage
> varies. We'll take a look at this.
> 

This behavior is consistent with the Infiniband CM (see
drivers/infiniband/core/cm.c function cm_recv_handler()).  But I think
we should at least log an error because a lost event will usually stall
the rdma connection.

> > 
> > > +EXPORT_SYMBOL(iw_cm_init_qp_attr);
> > 
> > This file exports a ton of symbols.  It's usual to provide some justifying
> > commentary in the changelog when this happens.
> 
> This module is a logical instance of the xx_cm where xx is the transport
> type. I think there is some discussion warranted on whether or not these
> should all be built into and exported by rdma_cm. One rationale would be
> that the rdma_cm is the only client for many of these functions (this
> being a particularly good example) and doing so would reduce the export
> count. Others would be reasonably needed for any application (connect,
> etc...)
> 

Transport-dependent ULPs, in theory, are able to use the
transport-specific CM directly if they don't wish to use the RDMA CM.  I
think that's the rationale for have the xx_cm modules seperate from the
rdma_cm module and exporting the various functions.   

> All that said, we'll be sure to document the exported symbols in a
> follow-up patch.
> 

I'll add commentary explaining this.

Steve.


^ permalink raw reply

* [PATCH 4/4] bcm43xx: Port PIO fixes to d80211
From: Michael Buesch @ 2006-06-13 19:18 UTC (permalink / raw)
  To: linville; +Cc: bcm43xx-dev, netdev
In-Reply-To: <20060613191206.122150000@ppc1>

Port the PIO fixes from bcm43xx-softmac to bcm43xx-d80211.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.h
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.h	2006-06-13 21:11:05.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.h	2006-06-13 21:11:48.000000000 +0200
@@ -223,6 +223,14 @@
 void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
 {
 }
+static inline
+void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+{
+}
+static inline
+void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+{
+}
 
 #endif /* CONFIG_BCM43XX_D80211_DMA */
 #endif /* BCM43xx_DMA_H_ */
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c	2006-06-13 21:11:24.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c	2006-06-13 21:11:48.000000000 +0200
@@ -27,6 +27,7 @@
 #include "bcm43xx_pio.h"
 #include "bcm43xx_main.h"
 #include "bcm43xx_xmit.h"
+#include "bcm43xx_power.h"
 
 #include <linux/delay.h>
 
@@ -44,10 +45,10 @@
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
 				  octet);
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-				  BCM43xx_PIO_TXCTL_WRITEHI);
+				  BCM43xx_PIO_TXCTL_WRITELO);
 	} else {
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-				  BCM43xx_PIO_TXCTL_WRITEHI);
+				  BCM43xx_PIO_TXCTL_WRITELO);
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
 				  octet);
 	}
@@ -103,7 +104,7 @@
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
 				  skb->data[skb->len - 1]);
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-				  BCM43xx_PIO_TXCTL_WRITEHI |
+				  BCM43xx_PIO_TXCTL_WRITELO |
 				  BCM43xx_PIO_TXCTL_COMPLETE);
 	} else {
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
@@ -112,9 +113,10 @@
 }
 
 static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
-			   int packetindex)
+			   struct bcm43xx_pio_txpacket *packet)
 {
 	u16 cookie = 0x0000;
+	int packetindex;
 
 	/* We use the upper 4 bits for the PIO
 	 * controller ID and the lower 12 bits
@@ -135,6 +137,7 @@
 	default:
 		assert(0);
 	}
+	packetindex = pio_txpacket_getindex(packet);
 	assert(((u16)packetindex & 0xF000) == 0x0000);
 	cookie |= (u16)packetindex;
 
@@ -184,8 +187,8 @@
 	bcm43xx_generate_txhdr(queue->bcm,
 			       &txhdr, skb->data, skb->len,
 			       1,//FIXME
-			       generate_cookie(queue, pio_txpacket_getindex(packet)),
-			       packet->ctl);
+			       generate_cookie(queue, packet),
+			       &packet->txstat.control);
 
 	tx_start(queue);
 	octets = skb->len + sizeof(txhdr);
@@ -200,10 +203,12 @@
 {
 	struct bcm43xx_pioqueue *queue = packet->queue;
 
-	if (irq_context)
-		dev_kfree_skb_irq(packet->skb);
-	else
-		dev_kfree_skb(packet->skb);
+	if (packet->skb) {
+		if (irq_context)
+			dev_kfree_skb_irq(packet->skb);
+		else
+			dev_kfree_skb(packet->skb);
+	}
 	list_move(&packet->list, &queue->txfree);
 	queue->nr_txfree++;
 }
@@ -216,8 +221,8 @@
 
 	octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
 	if (queue->tx_devq_size < octets) {
-		dprintkl(KERN_WARNING PFX "PIO queue too small. "
-					  "Dropping packet.\n");
+		printkl(KERN_WARNING PFX "PIO queue too small. "
+					 "Dropping packet.\n");
 		/* Drop it silently (return success) */
 		free_txpacket(packet, 1);
 		return 0;
@@ -256,10 +261,14 @@
 	unsigned long flags;
 	struct bcm43xx_pio_txpacket *packet, *tmp_packet;
 	int err;
+	u16 txctl;
 
 	bcm43xx_lock_irqonly(bcm, flags);
 	if (queue->tx_frozen)
 		goto out_unlock;
+	txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
+	if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
+		goto out_unlock;
 
 	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
 		/* Try to transmit the packet. This can fail, if
@@ -316,12 +325,19 @@
 		     (unsigned long)queue);
 
 	value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-	value |= BCM43xx_SBF_XFER_REG_BYTESWAP;
+	value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP;
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
 
 	qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
+	if (qsize == 0) {
+		printk(KERN_ERR PFX "ERROR: This card does not support PIO "
+				    "operation mode. Please use DMA mode "
+				    "(module parameter pio=0).\n");
+		goto err_freequeue;
+	}
 	if (qsize <= BCM43xx_PIO_TXQADJUST) {
-		printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize);
+		printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n",
+		       qsize);
 		goto err_freequeue;
 	}
 	qsize -= BCM43xx_PIO_TXQADJUST;
@@ -430,20 +446,19 @@
 {
 	struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
 	struct bcm43xx_pio_txpacket *packet;
-	u16 tmp;
 
 	assert(!queue->tx_suspended);
 	assert(!list_empty(&queue->txfree));
 
-	tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
-	if (tmp & BCM43xx_PIO_TXCTL_SUSPEND)
-		return -EBUSY;
-
 	packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
 	packet->skb = skb;
-	packet->ctl = ctl;
+
+	memset(&packet->txstat, 0, sizeof(packet->txstat));
+	memcpy(&packet->txstat.control, ctl, sizeof(*ctl));
+
 	list_move_tail(&packet->list, &queue->txqueue);
 	queue->nr_txfree--;
+	queue->nr_tx_packets++;
 	assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
 
 	tasklet_schedule(&queue->txtask);
@@ -459,11 +474,20 @@
 
 	queue = parse_cookie(bcm, status->cookie, &packet);
 	assert(queue);
-//TODO
-if (!queue)
-return;
+
+	queue->tx_devq_packets--;
+	queue->tx_devq_used -= (packet->skb->len + sizeof(struct bcm43xx_txhdr));
+
+	packet->txstat.ack = !!(status->flags & BCM43xx_TXSTAT_FLAG_ACK);
+	packet->txstat.retry_count = status->cnt2 - 1;
+	ieee80211_tx_status_irqsafe(bcm->net_dev, packet->skb,
+				    &(packet->txstat));
+	packet->skb = NULL;
+
 	free_txpacket(packet, 1);
-	/* If there are packets on the txqueue, poke the tasklet. */
+	/* If there are packets on the txqueue, poke the tasklet
+	 * to transmit them.
+	 */
 	if (!list_empty(&queue->txqueue))
 		tasklet_schedule(&queue->txtask);
 }
@@ -508,12 +532,9 @@
 	int i, preamble_readwords;
 	struct sk_buff *skb;
 
-return;
 	tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
-	if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) {
-		dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk.
+	if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE))
 		return;
-	}
 	bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
 			  BCM43xx_PIO_RXCTL_DATAAVAILABLE);
 
@@ -527,8 +548,7 @@
 	return;
 data_ready:
 
-//FIXME: endianess in this function.
-	len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
+	len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
 	if (unlikely(len > 0x700)) {
 		pio_rx_error(queue, 0, "len > 0x700");
 		return;
@@ -544,7 +564,7 @@
 		preamble_readwords = 18 / sizeof(u16);
 	for (i = 0; i < preamble_readwords; i++) {
 		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
-		preamble[i + 1] = cpu_to_be16(tmp);//FIXME?
+		preamble[i + 1] = cpu_to_le16(tmp);
 	}
 	rxhdr = (struct bcm43xx_rxhdr *)preamble;
 	rxflags2 = le16_to_cpu(rxhdr->flags2);
@@ -580,20 +600,43 @@
 	}
 	skb_put(skb, len);
 	for (i = 0; i < len - 1; i += 2) {
-		tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
-		*((u16 *)(skb->data + i)) = tmp;
+		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+		*((u16 *)(skb->data + i)) = cpu_to_le16(tmp);
 	}
 	if (len % 2) {
 		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
 		skb->data[len - 1] = (tmp & 0x00FF);
+/* The specs say the following is required, but
+ * it is wrong and corrupts the PLCP. If we don't do
+ * this, the PLCP seems to be correct. So ifdef it out for now.
+ */
+#if 0
 		if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
-			skb->data[0x20] = (tmp & 0xFF00) >> 8;
+			skb->data[2] = (tmp & 0xFF00) >> 8;
 		else
-			skb->data[0x1E] = (tmp & 0xFF00) >> 8;
+			skb->data[0] = (tmp & 0xFF00) >> 8;
+#endif
 	}
 	bcm43xx_rx(queue->bcm, skb, rxhdr);
 }
 
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+{
+	bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1);
+	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+			  bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+			  | BCM43xx_PIO_TXCTL_SUSPEND);
+}
+
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+{
+	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+			  bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+			  & ~BCM43xx_PIO_TXCTL_SUSPEND);
+	bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
+	tasklet_schedule(&queue->txtask);
+}
+
 void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
 {
 	struct bcm43xx_pio *pio;
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.h
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.h	2006-06-13 21:11:24.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.h	2006-06-13 21:11:48.000000000 +0200
@@ -14,8 +14,8 @@
 #define BCM43xx_PIO_RXCTL		0x08
 #define BCM43xx_PIO_RXDATA		0x0A
 
-#define BCM43xx_PIO_TXCTL_WRITEHI	(1 << 0)
-#define BCM43xx_PIO_TXCTL_WRITELO	(1 << 1)
+#define BCM43xx_PIO_TXCTL_WRITELO	(1 << 0)
+#define BCM43xx_PIO_TXCTL_WRITEHI	(1 << 1)
 #define BCM43xx_PIO_TXCTL_COMPLETE	(1 << 2)
 #define BCM43xx_PIO_TXCTL_INIT		(1 << 3)
 #define BCM43xx_PIO_TXCTL_SUSPEND	(1 << 7)
@@ -41,7 +41,7 @@
 struct bcm43xx_pio_txpacket {
 	struct bcm43xx_pioqueue *queue;
 	struct sk_buff *skb;
-	struct ieee80211_tx_control *ctl;
+	struct ieee80211_tx_status txstat;
 	struct list_head list;
 };
 
@@ -94,6 +94,7 @@
 		       u16 offset, u16 value)
 {
 	bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
+	mmiowb();
 }
 
 
@@ -108,6 +109,10 @@
 void bcm43xx_pio_get_tx_stats(struct bcm43xx_private *bcm,
 			      struct ieee80211_tx_queue_stats *stats);
 void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
+
+/* Suspend TX queue in hardware. */
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
 /* Suspend (freeze) the TX tasklet (software level). */
 void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm);
 void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm);
@@ -145,6 +150,14 @@
 {
 }
 static inline
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+{
+}
+static inline
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+{
+}
+static inline
 void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
 {
 }

--


^ permalink raw reply

* [PATCH 3/4] bcm43xx: Port suspend-mac-in-long-pwork from d80211
From: Michael Buesch @ 2006-06-13 19:18 UTC (permalink / raw)
  To: linville; +Cc: bcm43xx-dev, netdev
In-Reply-To: <20060613191206.122150000@ppc1>

Port the Suspend MAC In Long Periodic Work patch from bcm43xx-softmac to bcm43xx-d80211.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-06-13 21:11:08.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-06-13 21:11:37.000000000 +0200
@@ -743,6 +743,8 @@
 	u32 irq_savedstate;
 	/* Link Quality calculation context. */
 	struct bcm43xx_noise_calculation noisecalc;
+	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
+	int mac_suspended;
 
 	/* Interrupt Service Routine tasklet (bottom-half) */
 	struct tasklet_struct isr_tasklet;
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-06-13 21:11:24.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-06-13 21:11:37.000000000 +0200
@@ -2169,13 +2169,17 @@
 /* http://bcm-specs.sipsolutions.net/EnableMac */
 void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
 {
-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-	                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-			| BCM43xx_SBF_MAC_ENABLED);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
-	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
-	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
-	bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+	bcm->mac_suspended--;
+	assert(bcm->mac_suspended >= 0);
+	if (bcm->mac_suspended == 0) {
+		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+				| BCM43xx_SBF_MAC_ENABLED);
+		bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
+		bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+		bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+		bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+	}
 }
 
 /* http://bcm-specs.sipsolutions.net/SuspendMAC */
@@ -2184,18 +2188,23 @@
 	int i;
 	u32 tmp;
 
-	bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-	                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-			& ~BCM43xx_SBF_MAC_ENABLED);
-	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
-	for (i = 100000; i; i--) {
-		tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
-		if (tmp & BCM43xx_IRQ_READY)
-			return;
-		udelay(10);
+	assert(bcm->mac_suspended >= 0);
+	if (bcm->mac_suspended == 0) {
+		bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+				& ~BCM43xx_SBF_MAC_ENABLED);
+		bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+		for (i = 100000; i; i--) {
+			tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+			if (tmp & BCM43xx_IRQ_READY)
+				goto out;
+			udelay(10);
+		}
+		printkl(KERN_ERR PFX "MAC suspend failed\n");
 	}
-	printkl(KERN_ERR PFX "MAC suspend failed\n");
+out:
+	bcm->mac_suspended++;
 }
 
 static void bcm43xx_select_opmode(struct bcm43xx_private *bcm)
@@ -3013,8 +3022,10 @@
 		/* Periodic work will take a long time, so we want it to
 		 * be preemtible.
 		 */
-		bcm43xx_lock_irqonly(bcm, flags);
 		netif_stop_queue(bcm->net_dev);
+		synchronize_net();
+		bcm43xx_lock_irqonly(bcm, flags);
+		bcm43xx_mac_suspend(bcm);
 		if (bcm43xx_using_pio(bcm))
 			bcm43xx_pio_freeze_txqueues(bcm);
 		savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
@@ -3037,6 +3048,7 @@
 			bcm43xx_interrupt_enable(bcm, savedirqs);
 			if (bcm43xx_using_pio(bcm))
 				bcm43xx_pio_thaw_txqueues(bcm);
+			bcm43xx_mac_enable(bcm);
 		}
 		netif_wake_queue(bcm->net_dev);
 		mmiowb();
@@ -4371,6 +4383,7 @@
 
 	bcm->ieee = ieee;
 	bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+	bcm->mac_suspended = 1;
 	bcm->pci_dev = pci_dev;
 	bcm->net_dev = net_dev;
 	bcm->bad_frames_preempt = modparam_bad_frames_preempt;

--


^ permalink raw reply

* [PATCH 2/4] bcm43xx: Port preemptible-periodic-work to d80211
From: Michael Buesch @ 2006-06-13 19:18 UTC (permalink / raw)
  To: linville; +Cc: bcm43xx-dev, netdev
In-Reply-To: <20060613191206.122150000@ppc1>

Port the preemptible periodic work patch from bcm43xx-softmac to bcm43xx-d80211.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-06-13 21:11:08.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-06-13 21:11:24.000000000 +0200
@@ -529,11 +529,21 @@
 	return old_mask;
 }
 
+/* Synchronize IRQ top- and bottom-half.
+ * IRQs must be masked before calling this.
+ * This must not be called with the irq_lock held.
+ */
+static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
+{
+	synchronize_irq(bcm->irq);
+	tasklet_disable(&bcm->isr_tasklet);
+}
+
 /* Make sure we don't receive more data from the device. */
 static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
 {
-	u32 old;
 	unsigned long flags;
+	u32 old;
 
 	bcm43xx_lock_irqonly(bcm, flags);
 	if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
@@ -541,8 +551,9 @@
 		return -EBUSY;
 	}
 	old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-	tasklet_disable(&bcm->isr_tasklet);
 	bcm43xx_unlock_irqonly(bcm, flags);
+	bcm43xx_synchronize_irq(bcm);
+
 	if (oldstate)
 		*oldstate = old;
 
@@ -2951,14 +2962,10 @@
 	//TODO for APHY (temperature?)
 }
 
-static void bcm43xx_periodic_work_handler(void *d)
+static void do_periodic_work(struct bcm43xx_private *bcm)
 {
-	struct bcm43xx_private *bcm = d;
-	unsigned long flags;
 	unsigned int state;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
-
 	state = bcm->periodic_state;
 	if (state % 8 == 0)
 		bcm43xx_periodic_every120sec(bcm);
@@ -2966,13 +2973,79 @@
 		bcm43xx_periodic_every60sec(bcm);
 	if (state % 2 == 0)
 		bcm43xx_periodic_every30sec(bcm);
-	bcm43xx_periodic_every15sec(bcm);
+	if (state % 1 == 0)
+		bcm43xx_periodic_every15sec(bcm);
 	bcm->periodic_state = state + 1;
 
 	schedule_delayed_work(&bcm->periodic_work, HZ * 15);
+}
 
-	mmiowb();
-	bcm43xx_unlock_irqsafe(bcm, flags);
+/* Estimate a "Badness" value based on the periodic work
+ * state-machine state. "Badness" is worse (bigger), if the
+ * periodic work will take longer.
+ */
+static int estimate_periodic_work_badness(unsigned int state)
+{
+	int badness = 0;
+
+	if (state % 8 == 0) /* every 120 sec */
+		badness += 10;
+	if (state % 4 == 0) /* every 60 sec */
+		badness += 5;
+	if (state % 2 == 0) /* every 30 sec */
+		badness += 1;
+	if (state % 1 == 0) /* every 15 sec */
+		badness += 1;
+
+#define BADNESS_LIMIT	4
+	return badness;
+}
+
+static void bcm43xx_periodic_work_handler(void *d)
+{
+	struct bcm43xx_private *bcm = d;
+	unsigned long flags;
+	u32 savedirqs = 0;
+	int badness;
+
+	badness = estimate_periodic_work_badness(bcm->periodic_state);
+	if (badness > BADNESS_LIMIT) {
+		/* Periodic work will take a long time, so we want it to
+		 * be preemtible.
+		 */
+		bcm43xx_lock_irqonly(bcm, flags);
+		netif_stop_queue(bcm->net_dev);
+		if (bcm43xx_using_pio(bcm))
+			bcm43xx_pio_freeze_txqueues(bcm);
+		savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+		bcm43xx_unlock_irqonly(bcm, flags);
+		bcm43xx_lock_noirq(bcm);
+		bcm43xx_synchronize_irq(bcm);
+	} else {
+		/* Periodic work should take short time, so we want low
+		 * locking overhead.
+		 */
+		bcm43xx_lock_irqsafe(bcm, flags);
+	}
+
+	do_periodic_work(bcm);
+
+	if (badness > BADNESS_LIMIT) {
+		bcm43xx_lock_irqonly(bcm, flags);
+		if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
+			tasklet_enable(&bcm->isr_tasklet);
+			bcm43xx_interrupt_enable(bcm, savedirqs);
+			if (bcm43xx_using_pio(bcm))
+				bcm43xx_pio_thaw_txqueues(bcm);
+		}
+		netif_wake_queue(bcm->net_dev);
+		mmiowb();
+		bcm43xx_unlock_irqonly(bcm, flags);
+		bcm43xx_unlock_noirq(bcm);
+	} else {
+		mmiowb();
+		bcm43xx_unlock_irqsafe(bcm, flags);
+	}
 }
 
 static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
@@ -4178,9 +4251,11 @@
 static int bcm43xx_net_stop(struct net_device *net_dev)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	int err;
 
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
-		bcm43xx_disable_interrupts_sync(bcm, NULL);
+		err = bcm43xx_disable_interrupts_sync(bcm, NULL);
+		assert(!err);
 		bcm43xx_free_board(bcm);
 	}
 
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-06-13 21:11:08.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-06-13 21:11:24.000000000 +0200
@@ -1410,7 +1410,10 @@
 u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 ret;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	if (phy->connected) {
 		bcm43xx_phy_write(bcm, 0x15, 0xE300);
 		control <<= 8;
@@ -1430,8 +1433,10 @@
 		bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
 		udelay(8);
 	}
+	ret = bcm43xx_phy_read(bcm, 0x002D);
+	local_irq_restore(flags);
 
-	return bcm43xx_phy_read(bcm, 0x002D);
+	return ret;
 }
 
 static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c	2006-06-13 21:11:08.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c	2006-06-13 21:11:24.000000000 +0200
@@ -258,6 +258,9 @@
 	int err;
 
 	bcm43xx_lock_irqonly(bcm, flags);
+	if (queue->tx_frozen)
+		goto out_unlock;
+
 	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
 		/* Try to transmit the packet. This can fail, if
 		 * the device queue is full. In case of failure, the
@@ -270,6 +273,7 @@
 		if (err)
 			break;
 	}
+out_unlock:
 	bcm43xx_unlock_irqonly(bcm, flags);
 }
 
@@ -589,3 +593,35 @@
 	}
 	bcm43xx_rx(queue->bcm, skb, rxhdr);
 }
+
+void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_pio *pio;
+
+	assert(bcm43xx_using_pio(bcm));
+	pio = bcm43xx_current_pio(bcm);
+	pio->queue0->tx_frozen = 1;
+	pio->queue1->tx_frozen = 1;
+	pio->queue2->tx_frozen = 1;
+	pio->queue3->tx_frozen = 1;
+}
+
+void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_pio *pio;
+
+	assert(bcm43xx_using_pio(bcm));
+	pio = bcm43xx_current_pio(bcm);
+	pio->queue0->tx_frozen = 0;
+	pio->queue1->tx_frozen = 0;
+	pio->queue2->tx_frozen = 0;
+	pio->queue3->tx_frozen = 0;
+	if (!list_empty(&pio->queue0->txqueue))
+		tasklet_schedule(&pio->queue0->txtask);
+	if (!list_empty(&pio->queue1->txqueue))
+		tasklet_schedule(&pio->queue1->txtask);
+	if (!list_empty(&pio->queue2->txqueue))
+		tasklet_schedule(&pio->queue2->txtask);
+	if (!list_empty(&pio->queue3->txqueue))
+		tasklet_schedule(&pio->queue3->txtask);
+}
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.h
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.h	2006-06-13 21:11:05.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.h	2006-06-13 21:11:24.000000000 +0200
@@ -52,6 +52,7 @@
 	u16 mmio_base;
 
 	u8 tx_suspended:1,
+	   tx_frozen:1,
 	   need_workarounds:1; /* Workarounds needed for core.rev < 3 */
 
 	/* Adjusted size of the device internal TX buffer. */
@@ -106,8 +107,10 @@
 				   struct bcm43xx_xmitstatus *status);
 void bcm43xx_pio_get_tx_stats(struct bcm43xx_private *bcm,
 			      struct ieee80211_tx_queue_stats *stats);
-
 void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
+/* Suspend (freeze) the TX tasklet (software level). */
+void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm);
+void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm);
 
 #else /* CONFIG_BCM43XX_D80211_PIO */
 
@@ -141,6 +144,14 @@
 void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
 {
 }
+static inline
+void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+{
+}
+static inline
+void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+{
+}
 
 #endif /* CONFIG_BCM43XX_D80211_PIO */
 #endif /* BCM43xx_PIO_H_ */

--


^ permalink raw reply

* [PATCH 1/4] bcm43xx: Port new locking scheme to d80211
From: Michael Buesch @ 2006-06-13 19:18 UTC (permalink / raw)
  To: linville; +Cc: bcm43xx-dev, netdev
In-Reply-To: <20060613191206.122150000@ppc1>

Port the new locking scheme from bcm43xx-softmac to bcm43xx-d80211.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-06-13 21:11:05.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-06-13 21:11:08.000000000 +0200
@@ -649,6 +649,17 @@
 	unsigned int promisc:1;
 };
 
+/* Driver initialization status. */
+enum {
+	BCM43xx_STAT_UNINIT,		/* Uninitialized. */
+	BCM43xx_STAT_INITIALIZING,	/* init_board() in progress. */
+	BCM43xx_STAT_INITIALIZED,	/* Fully operational. */
+	BCM43xx_STAT_SHUTTINGDOWN,	/* free_board() in progress. */
+	BCM43xx_STAT_RESTARTING,	/* controller_restart() called. */
+};
+#define bcm43xx_status(bcm)		atomic_read(&(bcm)->init_status)
+#define bcm43xx_set_status(bcm, stat)	atomic_set(&(bcm)->init_status, (stat))
+
 struct bcm43xx_private {
 	struct ieee80211_hw *ieee;
 	struct ieee80211_low_level_stats ieee_stats;
@@ -659,18 +670,17 @@
 
 	void __iomem *mmio_addr;
 
-	/* Do not use the lock directly. Use the bcm43xx_lock* helper
-	 * functions, to be MMIO-safe. */
-	spinlock_t _lock;
-
-	/* Driver status flags. */
-	u32 initialized:1,		/* init_board() succeed */
-	    was_initialized:1,		/* for PCI suspend/resume. */
-	    shutting_down:1,		/* free_board() in progress */
+	/* Locking, see "theory of locking" text below. */
+	spinlock_t irq_lock;
+	struct mutex mutex;
+
+	/* Driver initialization status BCM43xx_STAT_*** */
+	atomic_t init_status;
+
+	u16 was_initialized:1,		/* for PCI suspend/resume. */
 	    __using_pio:1,		/* Internal, use bcm43xx_using_pio(). */
 	    bad_frames_preempt:1,	/* Use "Bad Frames Preemption" (default off) */
 	    reg124_set_0x4:1,		/* Some variable to keep track of IRQ stuff. */
-	    powersaving:1,		/* TRUE if we are in PowerSaving mode. FALSE otherwise. */
 	    short_preamble:1,		/* TRUE, if short preamble is enabled. */
 	    short_slot:1,		/* TRUE, if short slot timing is enabled. */
 	    firmware_norelease:1;	/* Do not release the firmware. Used on suspend. */
@@ -738,7 +748,7 @@
 	struct tasklet_struct isr_tasklet;
 
 	/* Periodic tasks */
-	struct timer_list periodic_tasks;
+	struct work_struct periodic_work;
 	unsigned int periodic_state;
 
 	struct work_struct restart_work;
@@ -766,21 +776,55 @@
 #endif
 };
 
-/* bcm43xx_(un)lock() protect struct bcm43xx_private.
- * Note that _NO_ MMIO writes are allowed. If you want to
- * write to the device through MMIO in the critical section, use
- * the *_mmio lock functions.
- * MMIO read-access is allowed, though.
- */
-#define bcm43xx_lock(bcm, flags)	spin_lock_irqsave(&(bcm)->_lock, flags)
-#define bcm43xx_unlock(bcm, flags)	spin_unlock_irqrestore(&(bcm)->_lock, flags)
-/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO.
- * MMIO write-access to the device is allowed.
- * All MMIO writes are flushed on unlock, so it is guaranteed to not
- * interfere with other threads writing MMIO registers.
+
+/*    *** THEORY OF LOCKING ***
+ *
+ * We have two different locks in the bcm43xx driver.
+ * => bcm->mutex:    General sleeping mutex. Protects struct bcm43xx_private
+ *                   and the device registers.
+ * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
+ *
+ * We have three types of helper function pairs to utilize these locks.
+ *     (Always use the helper functions.)
+ * 1) bcm43xx_{un}lock_noirq():
+ *     Takes bcm->mutex. Does _not_ protect against IRQ concurrency,
+ *     so it is almost always unsafe, if device IRQs are enabled.
+ *     So only use this, if device IRQs are masked.
+ *     Locking may sleep.
+ *     You can sleep within the critical section.
+ * 2) bcm43xx_{un}lock_irqonly():
+ *     Takes bcm->irq_lock. Does _not_ protect against
+ *     bcm43xx_lock_noirq() critical sections.
+ *     Does only protect against the IRQ handler path and other
+ *     irqonly() critical sections.
+ *     Locking does not sleep.
+ *     You must not sleep within the critical section.
+ * 3) bcm43xx_{un}lock_irqsafe():
+ *     This is the cummulative lock and takes both, mutex and irq_lock.
+ *     Protects against noirq() and irqonly() critical sections (and
+ *     the IRQ handler path).
+ *     Locking may sleep.
+ *     You must not sleep within the critical section.
  */
-#define bcm43xx_lock_mmio(bcm, flags)	bcm43xx_lock(bcm, flags)
-#define bcm43xx_unlock_mmio(bcm, flags)	do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0)
+
+/* Lock type 1 */
+#define bcm43xx_lock_noirq(bcm)		mutex_lock(&(bcm)->mutex)
+#define bcm43xx_unlock_noirq(bcm)	mutex_unlock(&(bcm)->mutex)
+/* Lock type 2 */
+#define bcm43xx_lock_irqonly(bcm, flags)	\
+	spin_lock_irqsave(&(bcm)->irq_lock, flags)
+#define bcm43xx_unlock_irqonly(bcm, flags)	\
+	spin_unlock_irqrestore(&(bcm)->irq_lock, flags)
+/* Lock type 3 */
+#define bcm43xx_lock_irqsafe(bcm, flags) do {	\
+	bcm43xx_lock_noirq(bcm);		\
+	bcm43xx_lock_irqonly(bcm, flags);	\
+		} while (0)
+#define bcm43xx_unlock_irqsafe(bcm, flags) do {	\
+	bcm43xx_unlock_irqonly(bcm, flags);	\
+	bcm43xx_unlock_noirq(bcm);		\
+		} while (0)
+
 
 static inline
 struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
@@ -848,16 +892,6 @@
 	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
 }
 
-/* Are we running in init_board() context? */
-static inline
-int bcm43xx_is_initializing(struct bcm43xx_private *bcm)
-{
-	if (bcm->initialized)
-		return 0;
-	if (bcm->shutting_down)
-		return 0;
-	return 1;
-}
 
 static inline
 struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c	2006-06-13 21:11:05.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c	2006-06-13 21:11:08.000000000 +0200
@@ -77,8 +77,8 @@
 
 	down(&big_buffer_sem);
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		fappend("Board not initialized.\n");
 		goto out;
 	}
@@ -121,7 +121,7 @@
 	fappend("\n");
 
 out:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	up(&big_buffer_sem);
 	return res;
@@ -159,8 +159,8 @@
 	unsigned long flags;
 
 	down(&big_buffer_sem);
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		fappend("Board not initialized.\n");
 		goto out;
 	}
@@ -169,7 +169,7 @@
 	fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
 
 out:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	up(&big_buffer_sem);
 	return res;
@@ -188,8 +188,8 @@
 	u64 tsf;
 
 	down(&big_buffer_sem);
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		fappend("Board not initialized.\n");
 		goto out;
 	}
@@ -199,7 +199,7 @@
 		(unsigned int)(tsf & 0xFFFFFFFFULL));
 
 out:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	up(&big_buffer_sem);
 	return res;
@@ -221,8 +221,8 @@
 	        res = -EFAULT;
 		goto out_up;
 	}
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
 		res = -EFAULT;
 		goto out_unlock;
@@ -233,10 +233,11 @@
 		goto out_unlock;
 	}
 	bcm43xx_tsf_write(bcm, tsf);
+	mmiowb();
 	res = buf_size;
 	
 out_unlock:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 out_up:
 	up(&big_buffer_sem);
 	return res;
@@ -257,7 +258,7 @@
 	int i, cnt, j = 0;
 
 	down(&big_buffer_sem);
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 
 	fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
 		BCM43xx_NR_LOGGED_XMITSTATUS);
@@ -293,14 +294,14 @@
 			i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
 	}
 
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	if (*ppos == pos) {
 		/* Done. Drop the copied data. */
 		e->xmitstatus_printing = 0;
 	}
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	up(&big_buffer_sem);
 	return res;
 }
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c	2006-06-13 21:11:05.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c	2006-06-13 21:11:08.000000000 +0200
@@ -51,12 +51,12 @@
 	struct bcm43xx_private *bcm = led->bcm;
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 	if (led->blink_interval) {
 		bcm43xx_led_changestate(led);
 		mod_timer(&led->blink_timer, jiffies + led->blink_interval);
 	}
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 }
 
 static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-06-13 21:11:05.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-06-13 21:11:08.000000000 +0200
@@ -369,7 +369,7 @@
 	 * Time is measured in microseconds.
 	 */
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 	radio = bcm43xx_current_radio(bcm);
 	oldchan = radio->channel;
 	testchan = (oldchan == 6) ? 7 : 6;
@@ -377,7 +377,7 @@
 	bcm43xx_radio_selectchannel(bcm, testchan, 0);
 	bcm43xx_tsf_read(bcm, &stop);
 	bcm43xx_radio_selectchannel(bcm, oldchan, 0);
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 
 	assert(stop > start);
 	bcm->ieee->channel_change_time = stop - start;
@@ -535,14 +535,14 @@
 	u32 old;
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) {
-		bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
+	if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
+		bcm43xx_unlock_irqonly(bcm, flags);
 		return -EBUSY;
 	}
 	old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
 	tasklet_disable(&bcm->isr_tasklet);
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 	if (oldstate)
 		*oldstate = old;
 
@@ -1277,7 +1277,7 @@
 			bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
 #endif
 	}
-	if (bcm->shutting_down) {
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
 		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
 		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
 				& ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
@@ -1592,7 +1592,7 @@
 # define bcmirq_handled(irq)	do { /* nothing */ } while (0)
 #endif /* CONFIG_BCM43XX_D80211_DEBUG*/
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 	reason = bcm->irq_reason;
 	dma_reason[0] = bcm->dma_reason[0];
 	dma_reason[1] = bcm->dma_reason[1];
@@ -1617,7 +1617,8 @@
 		        dma_reason[0], dma_reason[1],
 			dma_reason[2], dma_reason[3]);
 		bcm43xx_controller_restart(bcm, "DMA error");
-		bcm43xx_unlock_mmio(bcm, flags);
+		mmiowb();
+		bcm43xx_unlock_irqonly(bcm, flags);
 		return;
 	}
 	if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
@@ -1704,7 +1705,8 @@
 	if (!modparam_noleds)
 		bcm43xx_leds_update(bcm, activity);
 	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
-	bcm43xx_unlock_mmio(bcm, flags);
+	mmiowb();
+	bcm43xx_unlock_irqonly(bcm, flags);
 }
 
 static void pio_irq_workaround(struct bcm43xx_private *bcm,
@@ -1753,7 +1755,7 @@
 	if (!bcm)
 		return IRQ_NONE;
 
-	spin_lock(&bcm->_lock);
+	spin_lock(&bcm->irq_lock);
 
 	reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
 	if (reason == 0xffffffff) {
@@ -1782,7 +1784,7 @@
 	 * completely, but some careful work is needed to fix this. I think it
 	 * is best to stay with this cheap workaround for now... .
 	 */
-	if (likely(bcm->initialized)) {
+	if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
 		/* disable all IRQs. They are enabled again in the bottom half. */
 		bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
 		/* save the reason code and call our bottom half. */
@@ -1792,7 +1794,7 @@
 
 out:
 	mmiowb();
-	spin_unlock(&bcm->_lock);
+	spin_unlock(&bcm->irq_lock);
 
 	return ret;
 }
@@ -2949,15 +2951,14 @@
 	//TODO for APHY (temperature?)
 }
 
-static void bcm43xx_periodic_task_handler(unsigned long d)
+static void bcm43xx_periodic_work_handler(void *d)
 {
-	struct bcm43xx_private *bcm = (struct bcm43xx_private *)d;
+	struct bcm43xx_private *bcm = d;
 	unsigned long flags;
 	unsigned int state;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 
-	assert(bcm->initialized);
 	state = bcm->periodic_state;
 	if (state % 8 == 0)
 		bcm43xx_periodic_every120sec(bcm);
@@ -2968,26 +2969,24 @@
 	bcm43xx_periodic_every15sec(bcm);
 	bcm->periodic_state = state + 1;
 
-	mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15));
+	schedule_delayed_work(&bcm->periodic_work, HZ * 15);
 
-	bcm43xx_unlock_mmio(bcm, flags);
+	mmiowb();
+	bcm43xx_unlock_irqsafe(bcm, flags);
 }
 
 static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
 {
-	del_timer_sync(&bcm->periodic_tasks);
+	cancel_rearming_delayed_work(&bcm->periodic_work);
 }
 
 static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
-	struct timer_list *timer = &(bcm->periodic_tasks);
+	struct work_struct *work = &(bcm->periodic_work);
 
-	assert(bcm->initialized);
-	setup_timer(timer,
-		    bcm43xx_periodic_task_handler,
-		    (unsigned long)bcm);
-	timer->expires = jiffies;
-	add_timer(timer);
+	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+	INIT_WORK(work, bcm43xx_periodic_work_handler, bcm);
+	schedule_work(work);
 }
 
 static void bcm43xx_free_modes(struct bcm43xx_private *bcm)
@@ -3637,16 +3636,12 @@
 static void bcm43xx_free_board(struct bcm43xx_private *bcm)
 {
 	int i, err;
-	unsigned long flags;
 
+	bcm43xx_lock_noirq(bcm);
 	bcm43xx_sysfs_unregister(bcm);
-
 	bcm43xx_periodic_tasks_delete(bcm);
 
-	bcm43xx_lock(bcm, flags);
-	bcm->initialized = 0;
-	bcm->shutting_down = 1;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
 
 	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
 		if (!bcm->core_80211[i].available)
@@ -3662,23 +3657,19 @@
 	bcm43xx_pctl_set_crystal(bcm, 0);
 	bcm43xx_free_modes(bcm);
 
-	bcm43xx_lock(bcm, flags);
-	bcm->shutting_down = 0;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+	bcm43xx_unlock_noirq(bcm);
 }
 
 static int bcm43xx_init_board(struct bcm43xx_private *bcm)
 {
 	int i, err;
 	int connect_phy;
-	unsigned long flags;
 
 	might_sleep();
 
-	bcm43xx_lock(bcm, flags);
-	bcm->initialized = 0;
-	bcm->shutting_down = 0;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_lock_noirq(bcm);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
 
 	err = bcm43xx_pctl_set_crystal(bcm, 1);
 	if (err)
@@ -3750,15 +3741,15 @@
 	}
 
 	/* Initialization of the board is done. Flag it as such. */
-	bcm43xx_lock(bcm, flags);
-	bcm->initialized = 1;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
 
 	bcm43xx_periodic_tasks_setup(bcm);
 	bcm43xx_sysfs_register(bcm);
 
 	assert(err == 0);
 out:
+	bcm43xx_unlock_noirq(bcm);
+
 	return err;
 
 err_80211_unwind:
@@ -3983,14 +3974,14 @@
 	int err = -ENODEV;
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (likely(bcm->initialized)) {
+	bcm43xx_lock_irqonly(bcm, flags);
+	if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
 		if (bcm43xx_using_pio(bcm))
 			err = bcm43xx_pio_tx(bcm, skb, ctl);
 		else
 			err = bcm43xx_dma_tx(bcm, skb, ctl);
 	}
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 
 	return err;
 }
@@ -4000,9 +3991,9 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 	bcm43xx_controller_restart(bcm, "IEEE reset");
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 
 	return 0;
 }
@@ -4015,9 +4006,9 @@
 	struct bcm43xx_phyinfo *phy;
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized) {
-		bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+		bcm43xx_unlock_irqonly(bcm, flags);
 		return 0;
 	}
 	radio = bcm43xx_current_radio(bcm);
@@ -4052,7 +4043,7 @@
 	//TODO: phymode
 	//TODO: antennas
 
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 
 	return 0;
 }
@@ -4092,7 +4083,7 @@
 	index = (u8)(key->keyidx);
 	if (index >= ARRAY_SIZE(bcm->key))
 		goto out;
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	switch (cmd) {
 	case SET_KEY:
 		err = bcm43xx_key_write(bcm, index, algorithm,
@@ -4120,7 +4111,7 @@
 		break;
 	}
 out_unlock:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 out:
 	return err;
 }
@@ -4139,15 +4130,15 @@
 	unsigned long flags;
 	int err = -ENODEV;
 
-	bcm43xx_lock(bcm, flags);
-	if (likely(bcm->initialized)) {
+	bcm43xx_lock_irqonly(bcm, flags);
+	if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
 		if (bcm43xx_using_pio(bcm))
 			bcm43xx_pio_get_tx_stats(bcm, stats);
 		else
 			bcm43xx_dma_get_tx_stats(bcm, stats);
 		err = 0;
 	}
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 
 	return err;
 }
@@ -4158,9 +4149,9 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	memcpy(stats, &bcm->ieee_stats, sizeof(*stats));
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return 0;
 }
@@ -4188,7 +4179,7 @@
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 
-	if (bcm->initialized) {
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
 		bcm43xx_disable_interrupts_sync(bcm, NULL);
 		bcm43xx_free_board(bcm);
 	}
@@ -4203,7 +4194,7 @@
 	unsigned long flags;
 	int err = -EOPNOTSUPP;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 
 	if (conf->type == IEEE80211_IF_TYPE_MNTR) {
 		bcm->interface.monitor++;
@@ -4215,7 +4206,7 @@
 		bcm->interface.mac_addr = conf->mac_addr;
 		bcm->interface.type = conf->type;
 	}
-	if (bcm->initialized)
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
 		bcm43xx_select_opmode(bcm);
 	err = 0;
 
@@ -4226,7 +4217,7 @@
 		BCM43xx_MACARG(conf->mac_addr));
 
 out_unlock:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err;
 }
@@ -4237,15 +4228,15 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	if (conf->type == IEEE80211_IF_TYPE_MNTR) {
 		bcm->interface.monitor--;
 		assert(bcm->interface.monitor >= 0);
 	} else
 		bcm->interface.operating = 0;
-	if (bcm->initialized)
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
 		bcm43xx_select_opmode(bcm);
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	dprintk(KERN_INFO PFX "Virtual interface removed "
 			      "(type: 0x%08X, ID: %d, MAC: "
@@ -4261,12 +4252,12 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	if (conf->type != IEEE80211_IF_TYPE_MNTR) {
 		assert(bcm->interface.if_id == if_id);
 		bcm->interface.bssid = conf->bssid;
 	}
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return 0;
 }
@@ -4278,13 +4269,13 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 	if (bcm->interface.promisc != !!(netflags & IFF_PROMISC)) {
 		bcm->interface.promisc = !!(netflags & IFF_PROMISC);
-		if (bcm->initialized)
+		if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
 			bcm43xx_select_opmode(bcm);
 	}
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 }
 
 /* Initialization of struct net_device, just after allocation. */
@@ -4308,7 +4299,8 @@
 	bcm->pci_dev = pci_dev;
 	bcm->net_dev = net_dev;
 	bcm->bad_frames_preempt = modparam_bad_frames_preempt;
-	spin_lock_init(&bcm->_lock);
+	spin_lock_init(&bcm->irq_lock);
+	mutex_init(&bcm->mutex);
 	tasklet_init(&bcm->isr_tasklet,
 		     (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
 		     (unsigned long)bcm);
@@ -4445,7 +4437,7 @@
 	struct pci_dev *pci_dev = bcm->pci_dev;
 	struct ieee80211_hw *ieee = bcm->ieee;
 	int err;
-	int was_initialized = bcm->initialized;
+	int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
 
 	ieee80211_netif_oper(bcm->net_dev, NETIF_DETACH);
 	tasklet_disable(&bcm->isr_tasklet);
@@ -4480,6 +4472,7 @@
  */
 void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
 {
+	bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
 	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
 	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
 	printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
@@ -4498,11 +4491,11 @@
 
 	dprintk(KERN_INFO PFX "Suspending...\n");
 
-	bcm43xx_lock(bcm, flags);
-	bcm->was_initialized = bcm->initialized;
-	if (bcm->initialized)
+	bcm43xx_lock_irqsafe(bcm, flags);
+	bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+	if (bcm->was_initialized)
 		try_to_shutdown = 1;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	ieee80211_netif_oper(bcm->net_dev, NETIF_DETACH);
 	if (try_to_shutdown) {
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c	2006-06-13 21:11:05.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c	2006-06-13 21:11:08.000000000 +0200
@@ -120,12 +120,12 @@
 			GFP_KERNEL);
 	if (!sprom)
 		return -ENOMEM;
-	bcm43xx_lock_mmio(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	err = bcm43xx_sprom_read(bcm, sprom);
 	if (!err)
 		err = sprom2hex(sprom, buf, PAGE_SIZE);
-	bcm43xx_unlock_mmio(bcm, flags);
+	mmiowb();
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	kfree(sprom);
 
 	return err;
@@ -150,10 +150,10 @@
 	err = hex2sprom(sprom, buf, count);
 	if (err)
 		goto out_kfree;
-	bcm43xx_lock_mmio(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	err = bcm43xx_sprom_write(bcm, sprom);
-	bcm43xx_unlock_mmio(bcm, flags);
+	mmiowb();
+	bcm43xx_unlock_irqsafe(bcm, flags);
 out_kfree:
 	kfree(sprom);
 
@@ -170,15 +170,13 @@
 					    char *buf)
 {
 	struct bcm43xx_private *bcm = dev_to_bcm(dev);
-	unsigned long flags;
 	int err;
 	ssize_t count = 0;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	bcm43xx_lock(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_noirq(bcm);
 
 	switch (bcm43xx_current_radio(bcm)->interfmode) {
 	case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -195,7 +193,7 @@
 	}
 	err = 0;
 
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_noirq(bcm);
 
 	return err ? err : count;
 
@@ -231,16 +229,15 @@
 		return -EINVAL;
 	}
 
-	bcm43xx_lock_mmio(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_irqsafe(bcm, flags);
 
 	err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
 	if (err) {
 		printk(KERN_ERR PFX "Interference Mitigation not "
 				    "supported by device\n");
 	}
-
-	bcm43xx_unlock_mmio(bcm, flags);
+	mmiowb();
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err ? err : count;
 }
@@ -254,15 +251,13 @@
 					  char *buf)
 {
 	struct bcm43xx_private *bcm = dev_to_bcm(dev);
-	unsigned long flags;
 	int err;
 	ssize_t count;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	bcm43xx_lock(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_noirq(bcm);
 
 	if (bcm->short_preamble)
 		count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
@@ -270,7 +265,7 @@
 		count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
 
 	err = 0;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_noirq(bcm);
 
 	return err ? err : count;
 }
@@ -290,13 +285,12 @@
 	value = get_boolean(buf, count);
 	if (value < 0)
 		return value;
-	bcm43xx_lock(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_irqsafe(bcm, flags);
 
 	bcm->short_preamble = !!value;
 
 	err = 0;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err ? err : count;
 }
@@ -310,7 +304,7 @@
 	struct device *dev = &bcm->pci_dev->dev;
 	int err;
 
-	assert(bcm->initialized);
+	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
 
 	err = device_create_file(dev, &dev_attr_sprom);
 	if (err)
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-06-13 21:11:06.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-06-13 21:11:08.000000000 +0200
@@ -1648,7 +1648,7 @@
 void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
 {
 	static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
-	const int is_initializing = bcm43xx_is_initializing(bcm);
+	const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING);
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
 	u16 h, i, oldi = 0, j;
Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c
===================================================================
--- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c	2006-06-13 21:11:06.000000000 +0200
+++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c	2006-06-13 21:11:08.000000000 +0200
@@ -257,7 +257,7 @@
 	struct bcm43xx_pio_txpacket *packet, *tmp_packet;
 	int err;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
 		/* Try to transmit the packet. This can fail, if
 		 * the device queue is full. In case of failure, the
@@ -270,7 +270,7 @@
 		if (err)
 			break;
 	}
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 }
 
 static void setup_txqueues(struct bcm43xx_pioqueue *queue)
@@ -339,7 +339,6 @@
 	struct bcm43xx_pio_txpacket *packet, *tmp_packet;
 
 	ieee80211_netif_oper(queue->bcm->net_dev, NETIF_DETACH);
-	assert(queue->bcm->shutting_down);
 	tasklet_disable(&queue->txtask);
 
 	list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)

--


^ permalink raw reply

* [PATCH 0/4] bcm43xx: Port patches to d80211
From: Michael Buesch @ 2006-06-13 19:12 UTC (permalink / raw)
  To: linville; +Cc: bcm43xx-dev, netdev

Hi John,

Please apply this series to wireless-dev.
This ports various patches from bcm43xx-softmac to bcm43xx-d80211.

--


^ permalink raw reply

* Re: 2.6.17: networking bug??
From: Mark Lord @ 2006-06-13 19:08 UTC (permalink / raw)
  To: John Heffner; +Cc: Linus Torvalds, Linux Kernel, netdev, davem
In-Reply-To: <448F0344.9000008@rtr.ca>

Mark Lord wrote:
> Linus Torvalds wrote:
>
>> It's not like there aren't broken boxes out there, and it might be 
>> better to make the default buffer sizes just be low enough that window 
>> scaling simply isn't an issue.
>>
>> I suspect that the people who really want/need window scaling know 
>> about it, and could be assumed to know enough to raise their limits, no?
> 
> Agreed.  It's taken me over a month here to realize that the particular
> webserver in question (www.everymac.com) wasn't "dead", but merely being
> blocked by my 2.6.17 kernel.  All was fine with 2.6.16, as I discovered 
> today.
> 
> I wonder how many other "dead sites" there are out there,
> that will be shut off from people when they "upgrade" to 2.6.17 ?
> 
> I'm a kernel hacker.  Most users of 2.6.17 will not be.
> The default should be something that works "by default".

Further to this, the current behaviour is badly unpredictable.

A machine could be working perfectly, not (noticeably) affected
by this bug.  And then the user adds another stick of RAM to it.

Poof.. many sites from the internet stop responding.
Obviously the RAM upgrade broke things.. must be bad RAM, right?

Err.. no, the networking stack simply decided to become incompatible
with certain sites, as a result of the user adding more RAM to their machine.

BbD.

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: John Heffner @ 2006-06-13 18:28 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Mark Lord, Linux Kernel, netdev, davem
In-Reply-To: <Pine.LNX.4.64.0606131048550.5498@g5.osdl.org>

Linus Torvalds wrote:
> 
> On Tue, 13 Jun 2006, John Heffner wrote:
>> The best thing you can do is try to find this broken box and inform its owner
>> that it needs to be fixed.  (If you can find out what it is, I'd be interested
>> to know.)  In the meantime, disabling window scaling will work around the
>> problem for you.
> 
> Well, arguably, we shouldn't necessarily have defaults that use window 
> scaling, or we should have ways to recognize automatically when it 
> doesn't work (which may not be possible).
> 
> It's not like there aren't broken boxes out there, and it might be better 
> to make the default buffer sizes just be low enough that window scaling 
> simply isn't an issue.
> 
> I suspect that the people who really want/need window scaling know about 
> it, and could be assumed to know enough to raise their limits, no?
> 
> 		Linus

Unfortunately, there's really no way to detect this, at least not until 
it's too late.  You can't un-negotiate window scale after the connection 
is initiated.

64k buffers, the largest you can use without window scaling, are 
adequate for most home users on DSL or cable modems (good to about 10 
Mbps across the US, not quite that over trans-oceanic links). 
Unfortunately, that's about a factor of ten too small for that average 
university user, and a factor of 100-1000 too small for high end use. 
Check out the figure at 
<http://people.internet2.edu/~ghb/pmwiki/pmwiki.php/BridgingTheGap/BtGWizGap>, 
which has some data points.  (The bottom line is the best "normal" users 
can get with system default buffers, the top line is what high-end users 
have gotten with tuned systems over the wide area.  Note that this gap 
is increasing at an exponential rate.)

In the last couple years, we've added code that can automatically size 
the buffers as appropriate for each connection, but it's completely 
crippled unless you use a window scale.  Personally, I think it's not a 
question of *whether* we have to start using a window scale by default, 
but *when*.  I don't know that we want to let a small number of 
unambiguously broken middleboxes kill our forward progress.

Though I haven't gotten my hands on it, I believe Windows will soon have 
this capability, too.  I'm sure Windows is big enough that whenever they 
turn this on, it will flush out all these boxes pretty quickly.  We 
could wait for them to do it first, that that's not my favored approach.

BTW, as one data point, I've been personally running with a large window 
scale for about 5 years, and only seen a small handful of problems, most 
of which were corrected fairly quickly after I sent email to the admin 
of the box in question.  No "big" sites have been an issue.

Thanks,
   -John

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: Mark Lord @ 2006-06-13 18:26 UTC (permalink / raw)
  To: John Heffner; +Cc: Linus Torvalds, Linux Kernel, netdev, davem
In-Reply-To: <Pine.LNX.4.64.0606131048550.5498@g5.osdl.org>

Linus Torvalds wrote:
> 
> On Tue, 13 Jun 2006, John Heffner wrote:
>> The best thing you can do is try to find this broken box and inform its owner
>> that it needs to be fixed.  (If you can find out what it is, I'd be interested
>> to know.)  In the meantime, disabling window scaling will work around the
>> problem for you.
> 
> Well, arguably, we shouldn't necessarily have defaults that use window 
> scaling, or we should have ways to recognize automatically when it 
> doesn't work (which may not be possible).
> 
> It's not like there aren't broken boxes out there, and it might be better 
> to make the default buffer sizes just be low enough that window scaling 
> simply isn't an issue.
> 
> I suspect that the people who really want/need window scaling know about 
> it, and could be assumed to know enough to raise their limits, no?

Agreed.  It's taken me over a month here to realize that the particular
webserver in question (www.everymac.com) wasn't "dead", but merely being
blocked by my 2.6.17 kernel.  All was fine with 2.6.16, as I discovered today.

I wonder how many other "dead sites" there are out there,
that will be shut off from people when they "upgrade" to 2.6.17 ?

I'm a kernel hacker.  Most users of 2.6.17 will not be.
The default should be something that works "by default".

Cheers

^ permalink raw reply

* Re: Remove Prism II support from Orinoco
From: Jar @ 2006-06-13 18:24 UTC (permalink / raw)
  To: netdev

Stephen Hemminger wrote:

 >use blacklist in module config to block one.
 >Just put in /etc/modprobe.conf

 >blacklist orinoco

Unfortunately this is not work at least it is not work with FC4. I can 
blacklist eepro100 and 8139cp.

blacklist eepro100
blacklist 8139cp

but I can't blacklist orinoco_pci
blacklist orinoco_pci

It always loads itself with or without blacklist. That's why I have to 
do 'rm -f orinoco*.* && depmod -a' when the new kernel arrives. Seems 
that users are directed to use unsecure orinoco (wep) driver rather than 
secure hostap (wpa/wpa2,tkip,aes) driver for their prism2 hardware.

-- 
Best Regards, Jar

^ permalink raw reply

* Re: [PATCH 2.6.18 3/6] bnx2: Use CPU native page size
From: Michael Chan @ 2006-06-13 18:19 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20060612.222036.15588314.davem@davemloft.net>

On Mon, 2006-06-12 at 22:20 -0700, David Miller wrote:
> From: "Michael Chan" <mchan@broadcom.com>
> Date: Mon, 12 Jun 2006 17:17:13 -0700
> 
> > Use CPU native page size to determine various ring sizes. This allows
> > order-0 memory allocations on all systems.
> > 
> > Signed-off-by: Michael Chan <mchan@broadcom.com>
> 
> Are you sure you want to do this when the base page size is up to 64K
> on some IA64/PowerPC64/Sparc64 configurations?
> 
> Maybe you can use a limit with some ifdef tests, something like:
> 
> #if PAGE_SHIFT > 13
> #define BCM_PAGE_BITS 13
> #else
> #define BCM_PAGE_BITS PAGE_SHIFT
> #endif
> 
> which would limit it to 8K.
> 
Yes, this makes sense. Here's the revised patch:

Use CPU native page size to determine various ring sizes. This allows
order-0 memory allocations on all systems.

Added check to limit the page size to 16K since that's the maximum rx
ring size that will be used. This will prevent using unnecessarily
large page sizes on some architectures with large page sizes.
[Suggested by David Miller]

Signed-off-by: Michael Chan <mchan@broadcom.com>


diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 49c09da..cefb129 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -32,6 +32,7 @@
 #include <asm/irq.h>
 #include <linux/delay.h>
 #include <asm/byteorder.h>
+#include <asm/page.h>
 #include <linux/time.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index ea1ab06..69cebd9 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -3750,7 +3750,12 @@ struct l2_fhdr {
 #define DMA_READ_CHANS	5
 #define DMA_WRITE_CHANS	3
 
-#define BCM_PAGE_BITS	12
+/* Use CPU native page size up to 16K for the ring sizes.  */
+#if (PAGE_SHIFT > 14)
+#define BCM_PAGE_BITS	14
+#else
+#define BCM_PAGE_BITS	PAGE_SHIFT
+#endif
 #define BCM_PAGE_SIZE	(1 << BCM_PAGE_BITS)
 
 #define TX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct tx_bd))
@@ -3773,7 +3778,7 @@ struct l2_fhdr {
 
 #define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
 
-#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> 8)
+#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4))
 #define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
 
 /* Context size. */



^ permalink raw reply related

* Re: 2.6.17: networking bug??
From: Linus Torvalds @ 2006-06-13 17:50 UTC (permalink / raw)
  To: John Heffner; +Cc: Mark Lord, Linux Kernel, netdev, davem
In-Reply-To: <448EF85E.50405@psc.edu>



On Tue, 13 Jun 2006, John Heffner wrote:
> 
> The best thing you can do is try to find this broken box and inform its owner
> that it needs to be fixed.  (If you can find out what it is, I'd be interested
> to know.)  In the meantime, disabling window scaling will work around the
> problem for you.

Well, arguably, we shouldn't necessarily have defaults that use window 
scaling, or we should have ways to recognize automatically when it 
doesn't work (which may not be possible).

It's not like there aren't broken boxes out there, and it might be better 
to make the default buffer sizes just be low enough that window scaling 
simply isn't an issue.

I suspect that the people who really want/need window scaling know about 
it, and could be assumed to know enough to raise their limits, no?

		Linus

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: John Heffner @ 2006-06-13 17:39 UTC (permalink / raw)
  To: Mark Lord; +Cc: Linux Kernel, netdev, Linus Torvalds, davem
In-Reply-To: <448EF45B.2080601@rtr.ca>

Mark Lord wrote:
> John / David:  Any ideas on what's gone awry here?
> 
> 

Yes, you have some sort of a broken middlebox in your path (firewall, 
transparent proxy, or similar) that doesn't correctly handle window 
scaling.  Check out this thread: 
<http://marc.theaimsgroup.com/?l=linux-netdev&m=114478312100641&w=2>.

The best thing you can do is try to find this broken box and inform its 
owner that it needs to be fixed.  (If you can find out what it is, I'd 
be interested to know.)  In the meantime, disabling window scaling will 
work around the problem for you.

   -John

^ permalink raw reply

* Netchannels: alternative TCP/IP stack?
From: Evgeniy Polyakov @ 2006-06-13 17:33 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <20060608171555.GA10273@2ka.mipt.ru>

Hello, developers.

I've implemented simple rfc793 TCP/IP stack, which is currently tested
in userspace through packet socket. After ISO (~650Mb) transfer over 
gigabit ethernet between two Linux boxes, file was not corrupted.

I would even say that stack is really trivial (1800 lines of code, 42K
of sources where TCP state machine takes about 12K), but it includes:
* routing table for src/dst IP and MAC addresses (O(n) access).
	It includes static destination routing and ARP cache.
	No dynamic ARP probes.
* socket-like (actually netchannel-like) interface for data reading.
* ethernet sending/receiving support.
* IP sending/receiving support.
* TCP (rfc793) state machine implementation.
* UDP code (not tested).

Current code does not have options and TCP extensions, ack generation
does not use any heueristics, no congestion control, no prediction
(although I have some doubts about that idea), no ICMP. 
Sending was not tested yet.
Next option in agenda is to check various loss and reordering
issues. Then I plan to implement PAWS and timestamp TCP option.
MSS option would be usefull too.

I want to run various tests with congestions to collect some statistic
about generic TCP/IP behaviour, so I would like to ask
how much it will be frowned upon if I will use that simple stack for
netchannels (I plan to use only alternative TCP part with generic Linux
routing tables, IP and ethernet processing and so on)
and if miracle happens (it happens sometimes) and results will be better
than it is now [1] (it is planned if paid job will not get all the time)
and I will start pushing it upstream?
Or is it better to just make lobotomy right now?

1. Netchannel benchmarks vs. socket code.
http://tservice.net.ru/~s0mbre/old/?section=projects&item=netchannel

Thank you.

-- 
	Evgeniy Polyakov

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: Mark Lord @ 2006-06-13 17:22 UTC (permalink / raw)
  To: Linux Kernel; +Cc: netdev, Linus Torvalds, jheffner, davem
In-Reply-To: <448EEE9D.10105@rtr.ca>

Mark Lord wrote:
> ..
>> The site www.everymac.com is still not browseable until
>> setting /proc/sys/net/ipv4/tcp_window_scaling===0.
>>
>> There's one other difference I see in the tcpdump traces.
>> The first packets from each trace below show different
>> values for "wscale".  The old (working) kernels use "wscale 2",
>> whereas 2.6.17 uses "wscale 6".  In both cases, the value
>> seen in /proc/sys/net/ipv4/tcp_adv_win_scale is 2.
> 
> Okay.  More progress here.  The calculation of the "wscale" values
> is based on the "tcp_rmem" sysctl numbers.
> 
> The defaults for these *differ* between 2.6.16.18 and 2.6.17-rc*.
> 
> 2.6.16: 4096    87380    174760
> 2.6.17: 4096    87380   2097152
> 
> If I change the tcp_rmem setting on 2.6.17 to match the old value,
> then the website www.everymac.com becomes accessible again:
> 
> echo 4096 87380 174760 > /proc/sys/net/ipv4/tcp_rmem
> 
> Looking at diffs between 2.6.16 and 2.6.17, I see a big rework
> of the tcp_rmem code in linux/net/ipv4/tcp.c
> 
> Looks like something got broken there, or possibly the wscale
> calculations have a bug that is only triggered by the new rmem values ??
> 

Okay, here's the blob that broke it.

> [TCP]: Set default max buffers from memory pool size
> author	John Heffner <jheffner@psc.edu>
> 	Sat, 25 Mar 2006 09:34:07 +0000 (01:34 -0800)
> committer	David S. Miller <davem@davemloft.net>
> 	Sat, 25 Mar 2006 09:34:07 +0000 (01:34 -0800)
> commit	7b4f4b5ebceab67ce440a61081a69f0265e17c2a
> tree	ac02c685ce23f2440fecbebaa5b55cd47947c03e	tree
> parent	2babf9daae4a3561f3264638a22ac7d0b14a6f52	commit | commitdiff
> [TCP]: Set default max buffers from memory pool size
> 
> This patch sets the maximum TCP buffer sizes (available to automatic
> buffer tuning, not to setsockopt) based on the TCP memory pool size.
> The maximum sndbuf and rcvbuf each will be up to 4 MB, but no more
> than 1/128 of the memory pressure threshold.
> 
> Signed-off-by: John Heffner <jheffner@psc.edu>
> Signed-off-by: David S. Miller <davem@davemloft.net>

John / David:  Any ideas on what's gone awry here?




^ permalink raw reply

* Re: 2.6.17: networking bug??
From: Mark Lord @ 2006-06-13 16:58 UTC (permalink / raw)
  To: Linux Kernel; +Cc: netdev, Linus Torvalds
In-Reply-To: <448ED9B3.8050506@rtr.ca>

..
> The site www.everymac.com is still not browseable until
> setting /proc/sys/net/ipv4/tcp_window_scaling===0.
> 
> There's one other difference I see in the tcpdump traces.
> The first packets from each trace below show different
> values for "wscale".  The old (working) kernels use "wscale 2",
> whereas 2.6.17 uses "wscale 6".  In both cases, the value
> seen in /proc/sys/net/ipv4/tcp_adv_win_scale is 2.

Okay.  More progress here.  The calculation of the "wscale" values
is based on the "tcp_rmem" sysctl numbers.

The defaults for these *differ* between 2.6.16.18 and 2.6.17-rc*.

2.6.16: 4096    87380    174760  
2.6.17: 4096    87380   2097152

If I change the tcp_rmem setting on 2.6.17 to match the old value,
then the website www.everymac.com becomes accessible again:

echo 4096 87380 174760 > /proc/sys/net/ipv4/tcp_rmem

Looking at diffs between 2.6.16 and 2.6.17, I see a big rework
of the tcp_rmem code in linux/net/ipv4/tcp.c

Looks like something got broken there, or possibly the wscale
calculations have a bug that is only triggered by the new rmem values ??



^ permalink raw reply

* Re: Network Performance Comparison between Linux 2.4 and 2.6
From: Rick Jones @ 2006-06-13 16:44 UTC (permalink / raw)
  To: Bharath; +Cc: netdev
In-Reply-To: <c4166a920606130408m7780f956i814abb2d3f5aaf78@mail.gmail.com>

> I have included the throughput figures for bridging for both 2.4 and
> 2.6 kernels in the table below.
> Packet Size(bytes)            2.4.31(Mbps)          2.6.16(Mbps)
> ------------------------------------------------------------------------------------------ 
> 
> 64                                     2.11                       2.19
> 128                                    3.59                       3.75
> 256                                    6.33                       6.48
> 512                                   10.93                      11.16
> 1024                                 17.49                      17.33
> 1280                                 20.00                      19.83
> 1518                                 22.09                      19.91
> 
> About the tests, the MIPS malta board has two D-Link PCI ethernet
> cards. A bridge br0 is configured over the two ethernet interfaces (
> eth0 and eth1). There is an external traffic generator that is
> configured to generate packets of above mentioned sizes and to measure
> the throughput correspondingly.
> 
> Please let me know if you need any more information.

It would be good to include mention of the CPU utilization of the system 
under test, even if it is just to say "the CPU was 100% utilized.

rick jones
http://www.netperf.org/

^ permalink raw reply

* Re: [RFT 0/5] sky2: suspend/resume patchlets
From: Linus Torvalds @ 2006-06-13 16:38 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Jeff Garzik, netdev, David S. Miller
In-Reply-To: <20060613081726.695812000@localhost.localdomain>


[ Davem - see the final conclusion: this might not be a driver bug as much 
  as a netconsole problem, where netconsole might perhaps continue sendign 
  on a device that really can't take it any more? ]

On Tue, 13 Jun 2006, Stephen Hemminger wrote:
>
> There were a several problems buried in suspend/resume. The real
> failure was caused by the idle timer not being stopped/restarted.
> But several other races, and cleanups were needed.
> 
> Since I don't have a machine that will suspend successfully with
> that hardware, I can't test it.

With this, I get a page-fault in sky2_tx_complete+0x91 (with traceback to 
sky2_poll, net_rx_action, do_softirq, do_IRQ, skb_release_data, kfree_skb, 
sky2_rx_clean, sky2_down, sky2_suspend, pci_device_suspend, all the way 
down to suspend_device()).

So an IRQ happened while the sky2 driver was doign sky2_rx_clean, which is 
just _after_ it did "sky2_tx_clean()", and then the TX side was unhappy 
for some reason.

Again, the driver has actually tried to disable its _own_ irq, but that 
doesn't much help. Also, with write posting, even its own irq might have 
gotten delayed (ie if you really want to synchronize irq's, you need to 
read from the device, and then also wait a bit to see that the irq isn't 
being posted int he _other_ direction), but in the presense of shared 
irq's, it just doesn't do anything at all.

I can't seem to get a bigger VGA console on the Mac mini, so I'm unable to 
see the exact register values.

Btw, this probably happens with my patch too, and is likely 
timing-related.

Oh, and to make matters worse, I also enabled netconsole (in order to see 
what goes wrong), which is probably what brought on the horrid timing 
issue (ie packets going out _just_ at the right time saying "shutting 
down sky2")

Btw, that "sky2_tx_complete+0x91" seems to be 

	loop:
		inc    %edx
		mov    0x9c(%ecx),%eax
	**	movzwl 0x4(%eax),%eax	**
		cmp    %eax,%edx
		jb loop

which in turn is:

                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                        struct tx_ring_info *fre;
                        fre = sky2->tx_ring + RING_NEXT(put + i, TX_RING_SIZE);
                        pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr),
                                       skb_shinfo(skb)->frags[i].size,
                                       PCI_DMA_TODEVICE);
                }

since pci_unmap_page() is a no-op here ;)

So it looks like it's the "skb_shinfo(skb)->nr_frags" access that oopses.

Which probably means that

	skb = re->skb;

just got garbage (rememebr: the pci_unmap_single() directly after it is 
_also_ a no-op, so it wouldn't oops there).

I dunno the details. I'd have _expected_ tx_cons to be equal to tx_prod 
here (since we just did a sky2_tx_clean() before), and the loop to not 
have been entered at all, but I wonder if maybe it's the netconsole that 
doesn't honor "netif_stop_queue()"?

Dunno.

			Linus

^ permalink raw reply

* Re: [IPV6]: Fix RTNLGRP_IPV6_IFINFO netlink notifications
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2006-06-13 16:39 UTC (permalink / raw)
  To: kaber, davem; +Cc: netdev, yoshfuji
In-Reply-To: <448EE1CA.7020603@trash.net>

In article <448EE1CA.7020603@trash.net> (at Tue, 13 Jun 2006 18:03:22 +0200), Patrick McHardy <kaber@trash.net> says:

> Yes, thats better. I also thing we shouldn't return -EINVAL but
> -ENOSPC or something like that, -EINVAL usually indicated that
> the user sent an invalid message, which isn't the case here.
> Maybe a WARN_ON would also be appropriate, since this condition
> always means there is a bug.

Yes, but that's another issue.
Of course, you can cook up patch for it.


> > How about this?
> > 
> > +/* Maximum length of ifinfomsg attributes */
> > +#define INET6_IFINFO_RTA_SPACE \
> > +		RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \
:
> This doesn't seem to account for IFLA_LINK. Other than that it looks
> fine too me.

[IPV6]: Sum real space for RTAs.

This patch fixes RTNLGRP_IPV6_IFINFO netlink notifications.
Issue pointed out by Patrick McHardy <kaber@trash.net>.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 445006e..c2c26fa 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2860,6 +2860,11 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
 	return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
 }
 
+/* Maximum length of ifa_cacheinfo attributes */
+#define INET6_IFADDR_RTA_SPACE \
+		RTA_SPACE(16) /* IFA_ADDRESS */ + \
+		RTA_SPACE(sizeof(struct ifa_cacheinfo)) /* CACHEINFO */
+
 static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
 			     u32 pid, u32 seq, int event, unsigned int flags)
 {
@@ -3092,7 +3097,7 @@ static int inet6_dump_ifacaddr(struct sk
 static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
 {
 	struct sk_buff *skb;
-	int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
+	int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
 
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb) {
@@ -3142,6 +3147,17 @@ #endif
 #endif
 }
 
+/* Maximum length of ifinfomsg attributes */
+#define INET6_IFINFO_RTA_SPACE \
+		RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \
+		RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ +	\
+		RTA_SPACE(sizeof(u32)) /* MTU */ + \
+		RTA_SPACE(sizeof(int)) /* LINK */ + \
+		RTA_SPACE(0) /* PROTINFO */ + \
+		RTA_SPACE(sizeof(u32)) /* FLAGS */ + \
+		RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \
+		RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */
+
 static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 
 			     u32 pid, u32 seq, int event, unsigned int flags)
 {
@@ -3235,8 +3251,7 @@ static int inet6_dump_ifinfo(struct sk_b
 void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
 {
 	struct sk_buff *skb;
-	/* 128 bytes ?? */
-	int size = NLMSG_SPACE(sizeof(struct ifinfomsg)+128);
+	int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE);
 	
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb) {
@@ -3252,6 +3267,11 @@ void inet6_ifinfo_notify(int event, stru
 	netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC);
 }
 
+/* Maximum length of prefix_cacheinfo attributes */
+#define INET6_PREFIX_RTA_SPACE \
+		RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \
+		RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */
+
 static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
 			struct prefix_info *pinfo, u32 pid, u32 seq, 
 			int event, unsigned int flags)
@@ -3296,7 +3316,7 @@ static void inet6_prefix_notify(int even
 			 struct prefix_info *pinfo)
 {
 	struct sk_buff *skb;
-	int size = NLMSG_SPACE(sizeof(struct prefixmsg)+128);
+	int size = NLMSG_SPACE(sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE);
 
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb) {

^ permalink raw reply related

* Re: [PATCH 03/16] 64bit resource: fix up printks for resources in networks drivers
From: Greg KH @ 2006-06-13 16:30 UTC (permalink / raw)
  To: Jesse Brandeburg; +Cc: Greg KH, linux-kernel, NetDEV list
In-Reply-To: <4807377b0606130924i4b5ea36aq83b8db050831bea4@mail.gmail.com>

On Tue, Jun 13, 2006 at 09:24:55AM -0700, Jesse Brandeburg wrote:
> First, added netdev,
> 
> On 6/12/06, Greg KH <greg@kroah.com> wrote:
> >From: Greg Kroah-Hartman <gregkh@suse.de>
> >
> >This is needed if we wish to change the size of the resource structures.
> >
> >Based on an original patch from Vivek Goyal <vgoyal@in.ibm.com>
> >
> >Cc: Vivek Goyal <vgoyal@in.ibm.com>
> >Cc: Andrew Morton <akpm@osdl.org>
> >Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
> >---
> > drivers/net/3c59x.c            |    6 ++++--
> > drivers/net/8139cp.c           |    9 +++++----
> > drivers/net/8139too.c          |    6 +++---
> > drivers/net/e100.c             |    4 ++--
> > drivers/net/skge.c             |    4 ++--
> > drivers/net/sky2.c             |    6 +++---
> > drivers/net/tulip/de2104x.c    |    9 +++++----
> > drivers/net/tulip/tulip_core.c |    6 +++---
> > drivers/net/typhoon.c          |    5 +++--
> > drivers/net/wan/dscc4.c        |   12 ++++++------
> > drivers/net/wan/pc300_drv.c    |    4 ++--
> > 11 files changed, 38 insertions(+), 33 deletions(-)
> >
> >diff --git a/drivers/net/e100.c b/drivers/net/e100.c
> >index 31ac001..0c0bd67 100644
> >--- a/drivers/net/e100.c
> >+++ b/drivers/net/e100.c
> >@@ -2678,9 +2678,9 @@ #endif
> >                goto err_out_free;
> >        }
> >
> >-       DPRINTK(PROBE, INFO, "addr 0x%lx, irq %d, "
> >+       DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, "
> >                "MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n",
> >-               pci_resource_start(pdev, 0), pdev->irq,
> >+               (unsigned long long)pci_resource_start(pdev, 0), pdev->irq,
> >                netdev->dev_addr[0], netdev->dev_addr[1], 
> >                netdev->dev_addr[2],
> >                netdev->dev_addr[3], netdev->dev_addr[4], 
> >                netdev->dev_addr[5]);
> 
> color me confused, but why is this change necessary for e100?  e100
> can not support 64 bit BARs, so it seems to me to make little sense to
> cast to unsigned long long.  e100 is 32 bit the whole way through.

Because the result of pci_resource_start() just became either u32 or u64
depending on a config option, and so, to keep everything sane, we just
always cast it to unsigned long long, which makes everyone happy.

Hope this helps,

greg k-h

^ 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