Netdev List
 help / color / mirror / Atom feed
* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Chase Venters @ 2006-06-13 22:00 UTC (permalink / raw)
  To: Brian F. G. Bidulock
  Cc: Daniel Phillips, Stephen Hemminger, Sridhar Samudrala, netdev,
	linux-kernel
In-Reply-To: <20060613154031.A6276@openss7.org>

On Tue, 13 Jun 2006, Brian F. G. Bidulock wrote:

> Daniel,
>
> On Tue, 13 Jun 2006, Daniel Phillips wrote:
>>
>> 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?
>
> Why not?  Not all non-GPL modules are proprietary.  Do we lose
> something by making a nice stable api available to non-derived
> modules?

Look out for that word (stable). Judging from history (and sanity), 
arguing /in favor of/ any kind of stable module API is asking for it.

At least some of us feel like stable module APIs should be explicitly 
discouraged, because we don't want to offer comfort for code 
that refuses to live in the tree (since getting said code into the tree is 
often a goal).

I'm curious now too - can you name some non-GPL non-proprietary modules we 
should be concerned about? I'd think most of the possible examples (not 
sure what they are) would be better off dual-licensed (one license 
being GPL) and in-kernel.

Thanks,
Chase

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: Mark Lord @ 2006-06-13 21:49 UTC (permalink / raw)
  To: David Miller; +Cc: jheffner, torvalds, linux-kernel, netdev
In-Reply-To: <20060613.142603.48825062.davem@davemloft.net>



David Miller wrote:
>..
> 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".
..

Unilaterally following the standard is all well and good
for those who know how to get around it when a site becomes
inaccessible, but not for Joe User.

If it always fails, or always works, that's not such a big problem.
I would never have complained if I had never been able to access
the web sites in question.  But since it IS working in 2.6.16,
and got broken in 2.6.17, I'm bloody well going to complain.

I suppose the most important objection to our current behaviour
is that this behaviour *changes* when something totally unrelated
(to Joe User) happens:  adding or removing a stick of RAM.

So I'm not against the window scaling, just against it's apparent
randomness (to the vast majority who are not "in the know").

We should perhaps just have a fixed upper memory setting, as we
currently do in 2.6.16, so that the behaviour is predictable.

On a related note.. I wonder if we can choose better values for
the window size, so that if the scale factor is ignored, we still
end up with reasonably sized packets?  So that the other box
will not think our window is a mere "94" when the scale factor
is lost?

-ml


^ permalink raw reply

* RE: [openib-general] [PATCH v2 1/2] iWARP Connection Manager.
From: Steve Wise @ 2006-06-13 21:46 UTC (permalink / raw)
  To: Sean Hefty
  Cc: Tom Tucker, Andrew Morton, netdev, rdreier, linux-kernel,
	openib-general
In-Reply-To: <000001c68f31$78910fe0$24268686@amr.corp.intel.com>

On Tue, 2006-06-13 at 14:36 -0700, Sean Hefty wrote:
> >> 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.
> 

hmm.  Ok.  I see.  I misunderstood the code in cm_recv_handler().

Tom and I have been talking about what we can do to not drop the event.
Stay tuned.

Steve.


^ permalink raw reply

* How can we make more use of memory for TCP properly?
From: Kumiko Ono @ 2006-06-13 21:46 UTC (permalink / raw)
  To: netdev

Hi all,

Although I tried to find similar topics in the maling list, I found no 
useful clue. If I overlooked, please let me know the pointer.

I need to increase the value of sysctl_tcp_mem[2] that limit the total 
amount of memory allocated for TCP in order to maintain a number of 
simultateous TCP connections at a server, especially as a TCP server, 
like a web server.

Accorting to TCP man page, the kernel calculates the values of 
sysctl_tcp_mem depending on available physical memory at boot time.
I added 2GB RAM to a machine that had 2GB, and then it has 4GB RAM now. 
However, the value of sysctl_tcp_mem[2] has not changed from 196608 
(pages). The machine is running at Linux 2.6.16.5 i686 Intel(R) 
Pentium(R) 4 CPU 3.06GHz.

When looking through the tcp_init() in tcp.c, I found the value are 
determined with the tcp bind hash size, which reaches a upper cap of 
65536. I understand this upper cap is derived from the maximum of local 
port numbers, which are related to the behavior of TCP client, not that 
of TCP server.

When I manually increased the sysctl_tcp_mem to the double, 393216, and 
tried to establish over 30K TCP connections, the server hung up without 
any error messages of syslog.

Could anbody tell me how to make more use of memory for TCP connections 
properly, without replacing the machine to 64-bit arch.?

Regards,
Kumiko

^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Brian F. G. Bidulock @ 2006-06-13 21:40 UTC (permalink / raw)
  To: Daniel Phillips
  Cc: Stephen Hemminger, Sridhar Samudrala, netdev, linux-kernel
In-Reply-To: <448F2A49.5020809@google.com>

Daniel,

On Tue, 13 Jun 2006, Daniel Phillips wrote:
> 
> 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?

Why not?  Not all non-GPL modules are proprietary.  Do we lose
something by making a nice stable api available to non-derived
modules?

^ permalink raw reply

* Re: http://bugzilla.kernel.org/show_bug.cgi?id=6197
From: Michael Tokarev @ 2006-06-13 21:38 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netdev
In-Reply-To: <448EE065.9060207@trash.net>

Patrick McHardy wrote:
[]
> He patched his kernel with the IMQ device, which is known to cause all
> kinds of weird problems.

Wich problems?  Known to whom?

I was considering using imq for our needs (not done yet), and from the
FAQ at http://www.linuximq.net/faq.html (item #3, "Is it stable?") it
seems there's no problems except of gre tunnels and locally generated
traffic...

Googling for "imq linux problem" shows usual pile of various user
support questions (how to configure.. what did I do wrong.. etc),
but nothing relevant.

So... I'm curious whenever the claim on linuximq.net site about the
stability is true, or there in fact are some real issue...

Thanks.

/mjt

^ permalink raw reply

* 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


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