Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: Current status of rt2800usb and staging/rt2870
From: Bartlomiej Zolnierkiewicz @ 2009-10-14 20:10 UTC (permalink / raw)
  To: Ivo van Doorn
  Cc: John W. Linville, Dan Williams, Ozan Çağlayan,
	linux-wireless, linux-kernel
In-Reply-To: <200910142056.18295.IvDoorn@gmail.com>

On Wednesday 14 October 2009 20:56:17 Ivo van Doorn wrote:
> Hi,
> 
> > > On Wed, Oct 14, 2009 at 05:28:21PM +0200, Bartlomiej Zolnierkiewicz wrote:
> > > 
> > > > I don't have a have a problem with it personally as long as people accept
> > > > the competition..  but instead of working on _their_ projects they go around
> > > > screaming at everybody who does not want to spin inside the great process
> > > > designed by them..
> > > 
> > > Please whine somewhere else.  You have the freedom to work in
> > > drivers/staging all you want.  You do not have the power to force us to
> > > like it -- especially in a case where you are diverting attention from
> > > the community-maintained drivers instead of cooperating with them.
> > 
> > Cooperating you say.
> > 
> > rtl8187 -- before starting the work on rtl8187se I've pinged the maintainer
> > to coordinate the effort and hear his opinion on how to progress..
> > 
> > I've never heard back.
> > 
> > rt2x00 -- I know that people have datasheets for some chipsets but I've
> > never heard "How can we help you" etc. thing.
> 
> The rt2x00 members received the specsheets under the condition that we didn't
> distribute them further.
> 
> So everybody which requested the datasheets from the rt2x00 project were presented
> with a choice:
> 1) We provide the email address of the Ralink contact person which can device if you
> can get the specsheet or not (possibly under NDA, but this isn't always the case).
> 2) Specific questions about the registers can be asked and we give all the information we
> know from our work on the rt2x00 project plus additional information from the specsheet.
> Seeing that the specsheet doesn't always match reality, you get the better answers with
> this option, but some people just hate it when they need to ask other people for stuff.
> 
> > All I've ever heard was _lies_ about current state of affairs or that
> > my work is in the way.
> 
> I have encounterd your email address in only 2 rt2x00 related discussions
> (yes I have checked my entire email archive). Both cases were regarding
> staging vs rt2x00.
> 
> So far I never said rt2800usb or rt2800pci were high quality, I never said they were in a good
> shape. On the other hand, I often talked about the problems with the drivers, requesting help
> to improve the drivers, etc etc.
> 
> So are you basing this "I am hearing lies" about a random person talking on the street
> about rt2x00 which is telling the lie?

Maybe I've used a bit too strong wording but the fact is that vendor drivers
are useful for providing users with *unsupported* and *temporary* solution
until the proper drivers are in place have been questioned a lot in the past,
and sorry but it is a fact (it may be hard to swallow but it shouldn't be
discussed about).

The staging is a new game in town and provides real benefit for end-users
to use their hardware early while proper solutions are being worked on (not
like most of distributions weren't shipping crap drivers anyway -- now at
least we have some control over it).

This is extremely important in segments where Linux is still not the leading
OS.  We cannot tell users to go hike -- they are our users! Moreover they
are quite smart so they will use what works best for their needs anyway,
not necessarily what is the easiest for us to maintain in the long-term or
work on.

Staging also helps companies involved to transform their software offerings
in a more smooth way.  Often such transition requires long process and much
work on the company side to adapt to our model of doing things so patience
is recommended.  (Lets not forget that staging provides also a stick part,
drivers are removed from staging if nobody cares about them and even if
there are volunteers caring about support for certain hardware the company
will still get a bad publicity if it doesn't participate in the process)..

So staging is here to stay and it is up to particular maintainers how they
are going to it use this "tool" and integrate it into their current mode of
operation..

I'm sorry if my words were offending to you or other wireless developers.
I kind of feel the frustration of people who had put years of effort into
providing the proper wireless infrastructure + drivers and are ignored
by vendors.  However we have to keep the ball rolling and cannot dismiss
valid user complaints or ignore other possibilities of doing things.

Bartlomiej

^ permalink raw reply

* Re: Current status of rt2800usb and staging/rt2870
From: Bartlomiej Zolnierkiewicz @ 2009-10-14 20:41 UTC (permalink / raw)
  To: Luis Correia
  Cc: John W. Linville, Dan Williams, Ivo van Doorn,
	Ozan Çağlayan, linux-wireless, linux-kernel
In-Reply-To: <efe7343f0910141126o54ea2e31r5327e0db06a8b7ec@mail.gmail.com>

On Wednesday 14 October 2009 20:26:49 Luis Correia wrote:
> On Wed, Oct 14, 2009 at 18:33, Bartlomiej Zolnierkiewicz
> <bzolnier@gmail.com> wrote:
> > On Wednesday 14 October 2009 18:47:11 John W. Linville wrote:
> >> On Wed, Oct 14, 2009 at 05:28:21PM +0200, Bartlomiej Zolnierkiewicz wrote:
> >>
> >> > I don't have a have a problem with it personally as long as people accept
> >> > the competition..  but instead of working on _their_ projects they go around
> >> > screaming at everybody who does not want to spin inside the great process
> >> > designed by them..
> >>
> >> Please whine somewhere else.  You have the freedom to work in
> >> drivers/staging all you want.  You do not have the power to force us to
> >> like it -- especially in a case where you are diverting attention from
> >> the community-maintained drivers instead of cooperating with them.
> >
> > Cooperating you say.
> >
> > rtl8187 -- before starting the work on rtl8187se I've pinged the maintainer
> > to coordinate the effort and hear his opinion on how to progress..
> >
> > I've never heard back.
> >
> > rt2x00 -- I know that people have datasheets for some chipsets but I've
> > never heard "How can we help you" etc. thing.
> 
> I have all the datasheets that Ralink supplied to us.
> All of them are PRELIMINARY and most have errors, and therefore useless.
> 
> All useful information is in the crap drivers.
> 
> Ralink never provide better ones, and even our 'inside guy' says the
> hardware documentation guys are always very late in providing more
> info.
> 
> So, for me, it isn't lack of documentation that will ever help, believe me.
> 
> >
> > All I've ever heard was _lies_ about current state of affairs or that
> > my work is in the way.
> 
> AFAICS, your work was never questioned, at least by me.
> You are welcome to work on rt2x00 , that was also never a problem. All
> you would need is join in.
> 
> Ralink also said they were commited to present drivers for new chipset
> to be mac80211 compliant, we're waiting on that.
> 
> So, you're really welcome to join the rt2x00 team Bartlomiej, the only
> thing we ask is that all work should be done using the existing
> rt2x00lib, rt2x00pci and rt2x00usb base 'libraries'.

Well, I will still continue to work on staging drivers:

- I need to understand vendor drivers better before doing any larger rt2x00
  modifications.  Cleaning it up is just an added value while reading it..

- I feel quite comfortable working on de-convoluting crappy code and has years
  of experience of doing it.

- I'm still using Ralink hardware personally so I need something that provides
  the basic usability _now_.

but since I'm also going to start adding some missing bits to rt2x00 soon
I would be happy to join rt2x00 project..

^ permalink raw reply

* Re: AP: ath5k + hostapd occasionally sulks
From: Marin Glibic @ 2009-10-14 20:24 UTC (permalink / raw)
  To: linux-wireless

I've also been hit by this bug, mentioned last month - but he guy had no 
additional info. This is with compat-wireless 2009-10-09 and linux 
2.6.31.3, all in master mode, using recent hostapd from git.
Might also be two bugs... first one being module warning and "ath5k 
phy0: no further txbuf available, dropping packet" the other.


Oct 14 18:18:28 machinename kernel: ------------[ cut here ]------------
Oct 14 18:18:28 machinename kernel: WARNING: at 
/source/compat/compat-wireless-2009-10-09/net/mac80211/rc80211_minstrel.c:69 
minstrel_tx_status+0xdf/0x100 [mac80211]()
Oct 14 18:18:28 machinename kernel: Hardware name: KT600-8237
Oct 14 18:18:28 machinename kernel: Modules linked in: lp fuse ppdev 
parport_pc rtc_cmos parport rtc_core rtc_lib fan ath5k mac80211 ath 
processor uhci_hcd thermal thermal_sys cfg80211 hwmon button i2c_viapro rfk
ill i2c_core 3c59x led_class ehci_hcd shpchp via_agp evdev mii agpgart sg
Oct 14 18:18:28 machinename kernel: Pid: 0, comm: swapper Not tainted 
2.6.31.3-smp #2
Oct 14 18:18:28 machinename kernel: Call Trace:
Oct 14 18:18:28 machinename kernel:  [<c13cd9c0>] ? printk+0x18/0x20
Oct 14 18:18:28 machinename kernel:  [<e0a8ce2f>] ? 
minstrel_tx_status+0xdf/0x100 [mac80211]
Oct 14 18:18:28 machinename kernel:  [<c1032afc>] 
warn_slowpath_common+0x6c/0xc0
Oct 14 18:18:28 machinename kernel:  [<e0a8ce2f>] ? 
minstrel_tx_status+0xdf/0x100 [mac80211]
Oct 14 18:18:28 machinename kernel:  [<c1032b65>] 
warn_slowpath_null+0x15/0x20
Oct 14 18:18:28 machinename kernel:  [<e0a8ce2f>] 
minstrel_tx_status+0xdf/0x100 [mac80211]
Oct 14 18:18:28 machinename kernel:  [<e0a6fc8c>] 
ieee80211_tx_status+0x47c/0x4d0 [mac80211]
Oct 14 18:18:28 machinename kernel:  [<e0ad1293>] 
ath5k_tasklet_tx+0x203/0x3b0 [ath5k]
Oct 14 18:18:28 machinename kernel:  [<e0ac5883>] ? 
ath5k_hw_get_isr+0x223/0x3a0 [ath5k]
Oct 14 18:18:28 machinename kernel:  [<c1037430>] tasklet_action+0x50/0xb0
Oct 14 18:18:28 machinename kernel:  [<c10382aa>] __do_softirq+0xba/0x180
Oct 14 18:18:28 machinename kernel:  [<c10660c8>] ? 
handle_IRQ_event+0x58/0x140
Oct 14 18:18:28 machinename kernel:  [<c1018dce>] ? 
ack_apic_level+0x7e/0x270
Oct 14 18:18:28 machinename kernel:  [<c103839d>] do_softirq+0x2d/0x40
Oct 14 18:18:28 machinename kernel:  [<c10384f5>] irq_exit+0x65/0x90
Oct 14 18:18:28 machinename kernel:  [<c1004d3f>] do_IRQ+0x4f/0xc0
Oct 14 18:18:28 machinename kernel:  [<c104c7a9>] ? ktime_get+0x19/0x40
Oct 14 18:18:28 machinename kernel:  [<c10034e9>] common_interrupt+0x29/0x30
Oct 14 18:18:28 machinename kernel:  [<e0a1f381>] ? 
acpi_idle_enter_simple+0x132/0x15d [processor]
Oct 14 18:18:28 machinename kernel:  [<c1324c7f>] 
cpuidle_idle_call+0x6f/0xc0
Oct 14 18:18:28 machinename kernel:  [<c1001efd>] cpu_idle+0x4d/0x80
Oct 14 18:18:28 machinename kernel:  [<c13bd835>] rest_init+0x55/0x60
Oct 14 18:18:28 machinename kernel:  [<c15498a5>] start_kernel+0x2d5/0x338
Oct 14 18:18:28 machinename kernel:  [<c1549386>] ? 
unknown_bootoption+0x0/0x1f9
Oct 14 18:18:28 machinename kernel:  [<c1549079>] 
i386_start_kernel+0x79/0x81
Oct 14 18:18:28 machinename kernel: ---[ end trace 86949b8386bc65bb ]---

and then bit later:

Oct 14 20:22:02 machinename kernel: ath5k phy0: no further txbuf 
available, dropping packet
Oct 14 20:22:32 machinename last message repeated 4 times
Oct 14 20:23:33 machinename last message repeated 8 times
Oct 14 20:24:35 machinename last message repeated 8 times
Oct 14 20:25:33 machinename last message repeated 7 times
Oct 14 20:26:33 machinename last message repeated 8 times
Oct 14 20:27:33 machinename last message repeated 8 times
Oct 14 20:28:33 machinename last message repeated 8 times
and lot of these. Network traffic goes down. And even when it works, 
network traffic is very slow (<50kB/s)



some hw info:

2.6.31.3-smp #2 SMP Sat Oct 10 22:25:14 CEST 2009 i686 AMD Athlon(tm) XP 
2000+ AuthenticAMD GNU/Linux

00:0a.0 Ethernet controller [0200]: Atheros Communications Inc. Atheros 
AR5001X+ Wireless Network Adapter [168c:0013] (rev 01)
         Subsystem: Wistron NeWeb Corp. CM9 Wireless a/b/g MiniPCI 
Adapter [185f:1012]
         Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- 
ParErr- Stepping- SERR- FastB2B- DisINTx-
         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium 
 >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
         Latency: 168 (2500ns min, 7000ns max), Cache Line Size: 32 bytes
         Interrupt: pin A routed to IRQ 17
         Region 0: Memory at dd000000 (32-bit, non-prefetchable) [size=64K]
         Capabilities: [44] Power Management version 2
                 Flags: PMEClk- DSI- D1- D2- AuxCurrent=375mA 
PME(D0-,D1-,D2-,D3hot-,D3cold-)
                 Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME-
         Kernel driver in use: ath5k
         Kernel modules: ath5k

Hopefully somebody will catch this. Thanks.

^ permalink raw reply

* Re: [PATCH] cfg80211: no  cookies in cfg80211_send_ABCD()
From: John W. Linville @ 2009-10-14 20:08 UTC (permalink / raw)
  To: Holger Schurig; +Cc: linux-wireless, Johannes Berg
In-Reply-To: <200910140906.16111.hs4233@mail.mn-solutions.de>

This doesn't appear to be any different (other than the subject)
than the previous version?

John

On Wed, Oct 14, 2009 at 09:06:16AM +0200, Holger Schurig wrote:
> Get rid of cookies in cfg80211_send_XXX() functions.
> 
> Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>
> 
> --- linux-wl.orig/include/net/cfg80211.h
> +++ linux-wl/include/net/cfg80211.h
> @@ -1809,30 +1809,45 @@
>   * @dev: network device
>   * @buf: deauthentication frame (header + body)
>   * @len: length of the frame data
> - * @cookie: cookie from ->deauth if called within that callback,
> - *	%NULL otherwise
>   *
>   * This function is called whenever deauthentication has been processed in
>   * station mode. This includes both received deauthentication frames and
>   * locally generated ones. This function may sleep.
>   */
> -void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
> -			  void *cookie);
> +void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
> +
> +/**
> + * __cfg80211_send_deauth - notification of processed deauthentication
> + * @dev: network device
> + * @buf: deauthentication frame (header + body)
> + * @len: length of the frame data
> + *
> + * Like cfg80211_send_deauth(), but doesn't take the wdev lock.
> + */
> +void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
>  
>  /**
>   * cfg80211_send_disassoc - notification of processed disassociation
>   * @dev: network device
>   * @buf: disassociation response frame (header + body)
>   * @len: length of the frame data
> - * @cookie: cookie from ->disassoc if called within that callback,
> - *	%NULL otherwise
>   *
>   * This function is called whenever disassociation has been processed in
>   * station mode. This includes both received disassociation frames and locally
>   * generated ones. This function may sleep.
>   */
> -void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len,
> -			    void *cookie);
> +void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);
> +
> +/**
> + * __cfg80211_send_disassoc - notification of processed disassociation
> + * @dev: network device
> + * @buf: disassociation response frame (header + body)
> + * @len: length of the frame data
> + *
> + * Like cfg80211_send_disassoc(), but doesn't take the wdev lock.
> + */
> +void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf,
> +	size_t len);
>  
>  /**
>   * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP)
> --- linux-wl.orig/net/wireless/mlme.c
> +++ linux-wl/net/wireless/mlme.c
> @@ -121,7 +121,7 @@
>  }
>  EXPORT_SYMBOL(cfg80211_send_rx_assoc);
>  
> -static void __cfg80211_send_deauth(struct net_device *dev,
> +void __cfg80211_send_deauth(struct net_device *dev,
>  				   const u8 *buf, size_t len)
>  {
>  	struct wireless_dev *wdev = dev->ieee80211_ptr;
> @@ -177,27 +177,19 @@
>  					  false, NULL);
>  	}
>  }
> +EXPORT_SYMBOL(__cfg80211_send_deauth);
>  
> -
> -void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
> -			  void *cookie)
> +void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
>  {
>  	struct wireless_dev *wdev = dev->ieee80211_ptr;
>  
> -	BUG_ON(cookie && wdev != cookie);
> -
> -	if (cookie) {
> -		/* called within callback */
> -		__cfg80211_send_deauth(dev, buf, len);
> -	} else {
> -		wdev_lock(wdev);
> -		__cfg80211_send_deauth(dev, buf, len);
> -		wdev_unlock(wdev);
> -	}
> +	wdev_lock(wdev);
> +	__cfg80211_send_deauth(dev, buf, len);
> +	wdev_unlock(wdev);
>  }
>  EXPORT_SYMBOL(cfg80211_send_deauth);
>  
> -static void __cfg80211_send_disassoc(struct net_device *dev,
> +void __cfg80211_send_disassoc(struct net_device *dev,
>  				     const u8 *buf, size_t len)
>  {
>  	struct wireless_dev *wdev = dev->ieee80211_ptr;
> @@ -238,22 +230,15 @@
>  	from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
>  	__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
>  }
> +EXPORT_SYMBOL(__cfg80211_send_disassoc);
>  
> -void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len,
> -			    void *cookie)
> +void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
>  {
>  	struct wireless_dev *wdev = dev->ieee80211_ptr;
>  
> -	BUG_ON(cookie && wdev != cookie);
> -
> -	if (cookie) {
> -		/* called within callback */
> -		__cfg80211_send_disassoc(dev, buf, len);
> -	} else {
> -		wdev_lock(wdev);
> -		__cfg80211_send_disassoc(dev, buf, len);
> -		wdev_unlock(wdev);
> -	}
> +	wdev_lock(wdev);
> +	__cfg80211_send_disassoc(dev, buf, len);
> +	wdev_unlock(wdev);
>  }
>  EXPORT_SYMBOL(cfg80211_send_disassoc);
>  
> --- linux-wl.orig/net/mac80211/mlme.c
> +++ linux-wl/net/mac80211/mlme.c
> @@ -458,9 +458,15 @@
>  	mgmt->u.deauth.reason_code = cpu_to_le16(reason);
>  
>  	if (stype == IEEE80211_STYPE_DEAUTH)
> -		cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, cookie);
> +		if (cookie)
> +			__cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
> +		else
> +			cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
>  	else
> -		cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len, cookie);
> +		if (cookie)
> +			__cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
> +		else
> +			cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
>  	ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
>  }
>  
> @@ -1959,12 +1965,10 @@
>  			/* no action */
>  			break;
>  		case RX_MGMT_CFG80211_DEAUTH:
> -			cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len,
> -					     NULL);
> +			cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
>  			break;
>  		case RX_MGMT_CFG80211_DISASSOC:
> -			cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len,
> -					       NULL);
> +			cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
>  			break;
>  		default:
>  			WARN(1, "unexpected: %d", rma);
> @@ -2019,7 +2023,7 @@
>  		cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len);
>  		break;
>  	case RX_MGMT_CFG80211_DEAUTH:
> -		cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, NULL);
> +		cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
>  		break;
>  	default:
>  		WARN(1, "unexpected: %d", rma);
> 
> -- 
> http://www.holgerschurig.de
> 

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: Moving drivers into staging (was Re: [GIT PULL] SCSI fixes for 2.6.32-rc3)
From: Greg KH @ 2009-10-14 19:11 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Joe Perches, Luis R. Rodriguez, James Bottomley, Linus Torvalds,
	Theodore Tso, Andrew Morton, linux-scsi, linux-kernel, Jing Huang,
	netdev, linux-wireless
In-Reply-To: <20091014063308.GE784@elte.hu>

On Wed, Oct 14, 2009 at 08:33:08AM +0200, Ingo Molnar wrote:
> 
> * Joe Perches <joe@perches.com> wrote:
> 
> > On Tue, 2009-10-13 at 21:45 -0700, Greg KH wrote:
> > > How about when it was scheduled to be removed, we put it in staging and
> > > I'll add it to my announcements about the staging tree every release?
> > > Unless you can think of a better way?
> > 
> > staging/to_be_removed_unless_fixed_by/v.x.y ?
> 
> Yes, that's a real worry. Some time ago i suggested:
> 
>   drivers/staging/good/
>   drivers/staging/bad/
>   drivers/staging/ugly/
> 
>  good:  drivers that are to go upstream in the next cycle 
>  bad:   outgoing drivers being obsoleted or abandoned
>  ugly:  incoming messy drivers with active developers
> 
> The messaging of this looks nice and the names are short and obvious.

Yeah, but they make my life much harder than it needs to be.

I'd prefer to stick with the directory naming scheme we have today, it
seems to work well so far.

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH V3] iwlwifi: use paged Rx
From: Sedat Dilek @ 2009-10-14 19:04 UTC (permalink / raw)
  To: Zhu Yi; +Cc: linville, linux-wireless
In-Reply-To: <1255079985-17282-1-git-send-email-yi.zhu@intel.com>

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

Hi,

you are using ieee80211_rx() in
* drivers/net/wireless/iwlwifi/iwl-3945.c
* drivers/net/wireless/iwlwifi/iwl-rx.c
files.
Kalle posted "mac80211: add ieee80211_rx_ni()" patch [1] and I applied
on top of master 2009-10-13.
wl1251 driver uses ieee80211_rx_ni() [2].
My question:
Is iwlagn/iwl3945 using workqueues - means shall/can it use
ieee80211_rx_ni() instead?
Out of curiosity, I substituted ieee80211_rx() by ieee80211_rx_ni()
and it seems to work.
(Patch attached).

Kind Regards,
- Sedat -

[1] http://patchwork.kernel.org/patch/53466/
[2] http://patchwork.kernel.org/patch/53465/

On Fri, Oct 9, 2009 at 11:19 AM, Zhu Yi <yi.zhu@intel.com> wrote:
> This switches the iwlwifi driver to use paged skb from linear skb for Rx
> buffer. So that it relieves some Rx buffer allocation pressure for the
> memory subsystem. Currently iwlwifi (4K for 3945) requests 8K bytes for
> Rx buffer. Due to the trailing skb_shared_info in the skb->data,
> alloc_skb() will do the next order allocation, which is 16K bytes. This
> is suboptimal and more likely to fail when the system is under memory
> usage pressure. Switching to paged Rx skb lets us allocate the RXB
> directly by alloc_pages(), so that only order 1 allocation is required.
>
> It also adjusts the area spin_lock (with IRQ disabled) protected in the
> tasklet because tasklet guarentees to run only on one CPU and the new
> unprotected code can be preempted by the IRQ handler. This saves us from
> spawning another workqueue to make skb_linearize/__pskb_pull_tail happy
> (which cannot be called in hard irq context).
>
> Finally, mac80211 doesn't support paged Rx yet. So we linearize the skb
> for all the management frames and software decryption or defragmentation
> required data frames before handed to mac80211. For all the other frames,
> we __pskb_pull_tail 64 bytes in the linear area of the skb for mac80211
> to handle them properly.
>
> Signed-off-by: Zhu Yi <yi.zhu@intel.com>
> ---
> V2: fix 3945 problem and linearize skb for fragemented frames
> V3: fix a 3945 pci_unmap_page bug
>
>  drivers/net/wireless/iwlwifi/iwl-3945.c     |   67 ++++++++++-----
>  drivers/net/wireless/iwlwifi/iwl-4965.c     |    2 +-
>  drivers/net/wireless/iwlwifi/iwl-5000.c     |    4 +-
>  drivers/net/wireless/iwlwifi/iwl-agn.c      |   42 ++++-----
>  drivers/net/wireless/iwlwifi/iwl-commands.h |   10 ++
>  drivers/net/wireless/iwlwifi/iwl-core.c     |   13 ++--
>  drivers/net/wireless/iwlwifi/iwl-core.h     |    2 +-
>  drivers/net/wireless/iwlwifi/iwl-dev.h      |   27 ++++--
>  drivers/net/wireless/iwlwifi/iwl-hcmd.c     |   21 ++----
>  drivers/net/wireless/iwlwifi/iwl-rx.c       |  122 +++++++++++++++++----------
>  drivers/net/wireless/iwlwifi/iwl-scan.c     |   20 ++--
>  drivers/net/wireless/iwlwifi/iwl-spectrum.c |    2 +-
>  drivers/net/wireless/iwlwifi/iwl-sta.c      |   62 +++++--------
>  drivers/net/wireless/iwlwifi/iwl-tx.c       |   10 +-
>  drivers/net/wireless/iwlwifi/iwl3945-base.c |  120 +++++++++++++-------------
>  15 files changed, 284 insertions(+), 240 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
> index 8012381..b188a02 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-3945.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
> @@ -293,7 +293,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
>  static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
>                            struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
>        int txq_id = SEQ_TO_QUEUE(sequence);
>        int index = SEQ_TO_INDEX(sequence);
> @@ -353,7 +353,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
>  void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
>                struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
>                     (int)sizeof(struct iwl3945_notif_statistics),
>                     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
> @@ -543,14 +543,17 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
>                                   struct iwl_rx_mem_buffer *rxb,
>                                   struct ieee80211_rx_status *stats)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
>        struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
>        struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
> -       short len = le16_to_cpu(rx_hdr->len);
> +       u16 len = le16_to_cpu(rx_hdr->len);
> +       struct sk_buff *skb;
> +       int ret;
>
>        /* We received data from the HW, so stop the watchdog */
> -       if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
> +       if (unlikely(len + IWL39_RX_FRAME_SIZE >
> +                    PAGE_SIZE << priv->hw_params.rx_page_order)) {
>                IWL_DEBUG_DROP(priv, "Corruption detected!\n");
>                return;
>        }
> @@ -562,20 +565,45 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
>                return;
>        }
>
> -       skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt);
> -       /* Set the size of the skb to the size of the frame */
> -       skb_put(rxb->skb, le16_to_cpu(rx_hdr->len));
> +       skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
> +       if (!skb) {
> +               IWL_ERR(priv, "alloc_skb failed\n");
> +               return;
> +       }
>
>        if (!iwl3945_mod_params.sw_crypto)
>                iwl_set_decrypted_flag(priv,
> -                                      (struct ieee80211_hdr *)rxb->skb->data,
> +                                      (struct ieee80211_hdr *)rxb_addr(rxb),
>                                       le32_to_cpu(rx_end->status), stats);
>
> +       skb_add_rx_frag(skb, 0, rxb->page,
> +                       (void *)rx_hdr->payload - (void *)pkt, len);
> +
> +       /* mac80211 currently doesn't support paged SKB. Convert it to
> +        * linear SKB for management frame and data frame requires
> +        * software decryption or software defragementation. */
> +       if (ieee80211_is_mgmt(hdr->frame_control) ||
> +           ieee80211_has_protected(hdr->frame_control) ||
> +           ieee80211_has_morefrags(hdr->frame_control) ||
> +           le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
> +               ret = skb_linearize(skb);
> +       else
> +               ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
> +                       0 : -ENOMEM;
> +
> +       if (ret) {
> +               kfree_skb(skb);
> +               goto out;
> +       }
> +
>        iwl_update_stats(priv, false, hdr->frame_control, len);
>
> -       memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
> -       ieee80211_rx_irqsafe(priv->hw, rxb->skb);
> -       rxb->skb = NULL;
> +       memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
> +       ieee80211_rx(priv->hw, skb);
> +
> + out:
> +       priv->alloc_rxb_page--;
> +       rxb->page = NULL;
>  }
>
>  #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
> @@ -585,7 +613,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
>  {
>        struct ieee80211_hdr *header;
>        struct ieee80211_rx_status rx_status;
> -       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
>        struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
>        struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
> @@ -1811,7 +1839,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
>  static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
>  {
>        int rc = 0;
> -       struct iwl_rx_packet *res = NULL;
> +       struct iwl_rx_packet *pkt;
>        struct iwl3945_rxon_assoc_cmd rxon_assoc;
>        struct iwl_host_cmd cmd = {
>                .id = REPLY_RXON_ASSOC,
> @@ -1840,14 +1868,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
>        if (rc)
>                return rc;
>
> -       res = (struct iwl_rx_packet *)cmd.reply_skb->data;
> -       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
> +       pkt = (struct iwl_rx_packet *)cmd.reply_page;
> +       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
>                IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
>                rc = -EIO;
>        }
>
> -       priv->alloc_rxb_skb--;
> -       dev_kfree_skb_any(cmd.reply_skb);
> +       priv->alloc_rxb_page--;
> +       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
>
>        return rc;
>  }
> @@ -2513,8 +2541,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
>        priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
>
>        priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
> -       priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K;
> -       priv->hw_params.max_pkt_size = 2342;
> +       priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
>        priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
>        priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
>        priv->hw_params.max_stations = IWL3945_STATION_COUNT;
> diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
> index 6d77039..1a622aa 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-4965.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
> @@ -1999,7 +1999,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
>  static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
>                                struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
>        int txq_id = SEQ_TO_QUEUE(sequence);
>        int index = SEQ_TO_INDEX(sequence);
> diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
> index ab5b9d8..17555c7 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-5000.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
> @@ -423,7 +423,7 @@ static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
>  static void iwl5000_rx_calib_result(struct iwl_priv *priv,
>                             struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
>        int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
>        int index;
> @@ -1143,7 +1143,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
>  static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
>                                struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
>        int txq_id = SEQ_TO_QUEUE(sequence);
>        int index = SEQ_TO_INDEX(sequence);
> diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
> index 0878b34..fc7a511 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-agn.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
> @@ -524,7 +524,7 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv,
>  static void iwl_rx_reply_alive(struct iwl_priv *priv,
>                                struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_alive_resp *palive;
>        struct delayed_work *pwork;
>
> @@ -610,7 +610,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
>                                struct iwl_rx_mem_buffer *rxb)
>  {
>  #ifdef CONFIG_IWLWIFI_DEBUG
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl4965_beacon_notif *beacon =
>                (struct iwl4965_beacon_notif *)pkt->u.raw;
>        u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
> @@ -634,7 +634,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
>  static void iwl_rx_card_state_notif(struct iwl_priv *priv,
>                                    struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
>        unsigned long status = priv->status;
>
> @@ -786,10 +786,10 @@ void iwl_rx_handle(struct iwl_priv *priv)
>
>                rxq->queue[i] = NULL;
>
> -               pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
> -                                priv->hw_params.rx_buf_size + 256,
> -                                PCI_DMA_FROMDEVICE);
> -               pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +               pci_unmap_page(priv->pci_dev, rxb->page_dma,
> +                              PAGE_SIZE << priv->hw_params.rx_page_order,
> +                              PCI_DMA_FROMDEVICE);
> +               pkt = rxb_addr(rxb);
>
>                trace_iwlwifi_dev_rx(priv, pkt,
>                        le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
> @@ -825,10 +825,10 @@ void iwl_rx_handle(struct iwl_priv *priv)
>                }
>
>                if (reclaim) {
> -                       /* Invoke any callbacks, transfer the skb to caller, and
> -                        * fire off the (possibly) blocking iwl_send_cmd()
> +                       /* Invoke any callbacks, transfer the buffer to caller,
> +                        * and fire off the (possibly) blocking iwl_send_cmd()
>                         * as we reclaim the driver command queue */
> -                       if (rxb && rxb->skb)
> +                       if (rxb && rxb->page)
>                                iwl_tx_cmd_complete(priv, rxb);
>                        else
>                                IWL_WARN(priv, "Claim null rxb?\n");
> @@ -837,10 +837,10 @@ void iwl_rx_handle(struct iwl_priv *priv)
>                /* For now we just don't re-use anything.  We can tweak this
>                 * later to try and re-use notification packets and SKBs that
>                 * fail to Rx correctly */
> -               if (rxb->skb != NULL) {
> -                       priv->alloc_rxb_skb--;
> -                       dev_kfree_skb_any(rxb->skb);
> -                       rxb->skb = NULL;
> +               if (rxb->page != NULL) {
> +                       priv->alloc_rxb_page--;
> +                       __free_pages(rxb->page, priv->hw_params.rx_page_order);
> +                       rxb->page = NULL;
>                }
>
>                spin_lock_irqsave(&rxq->lock, flags);
> @@ -907,6 +907,8 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
>        }
>  #endif
>
> +       spin_unlock_irqrestore(&priv->lock, flags);
> +
>        /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
>         * atomic, make sure that inta covers all the interrupts that
>         * we've discovered, even if FH interrupt came in just after
> @@ -928,8 +930,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
>
>                handled |= CSR_INT_BIT_HW_ERR;
>
> -               spin_unlock_irqrestore(&priv->lock, flags);
> -
>                return;
>        }
>
> @@ -1056,7 +1056,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
>                        "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
>        }
>  #endif
> -       spin_unlock_irqrestore(&priv->lock, flags);
>  }
>
>  /* tasklet for iwlagn interrupt */
> @@ -1086,6 +1085,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
>                                inta, inta_mask);
>        }
>  #endif
> +
> +       spin_unlock_irqrestore(&priv->lock, flags);
> +
>        /* saved interrupt in inta variable now we can reset priv->inta */
>        priv->inta = 0;
>
> @@ -1101,8 +1103,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
>
>                handled |= CSR_INT_BIT_HW_ERR;
>
> -               spin_unlock_irqrestore(&priv->lock, flags);
> -
>                return;
>        }
>
> @@ -1242,14 +1242,10 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
>                         inta & ~priv->inta_mask);
>        }
>
> -
>        /* Re-enable all interrupts */
>        /* only Re-enable if diabled by irq */
>        if (test_bit(STATUS_INT_ENABLED, &priv->status))
>                iwl_enable_interrupts(priv);
> -
> -       spin_unlock_irqrestore(&priv->lock, flags);
> -
>  }
>
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
> index cc4e912..7d4f131 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-commands.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
> @@ -3544,6 +3544,16 @@ struct iwl_wimax_coex_cmd {
>  *****************************************************************************/
>
>  struct iwl_rx_packet {
> +       /*
> +        * The first 4 bytes of the RX frame header contain both the RX frame
> +        * size and some flags.
> +        * Bit fields:
> +        * 31:    flag flush RB request
> +        * 30:    flag ignore TC (terminal counter) request
> +        * 29:    flag fast IRQ request
> +        * 28-14: Reserved
> +        * 13-00: RX frame size
> +        */
>        __le32 len_n_flags;
>        struct iwl_cmd_header hdr;
>        union {
> diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
> index 2ae168a..3e6ce5c 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-core.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-core.c
> @@ -1281,7 +1281,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
>
>  void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
>        struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
>        IWL_DEBUG_11H(priv, "CSA notif: channel %d, status %d\n",
> @@ -1492,10 +1492,9 @@ int iwl_set_hw_params(struct iwl_priv *priv)
>        priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
>        priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
>        if (priv->cfg->mod_params->amsdu_size_8K)
> -               priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;
> +               priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
>        else
> -               priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
> -       priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
> +               priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
>
>        priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
>
> @@ -2176,7 +2175,7 @@ void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
>                           struct iwl_rx_mem_buffer *rxb)
>  {
>  #ifdef CONFIG_IWLWIFI_DEBUG
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
>        IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
>                     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
> @@ -2187,7 +2186,7 @@ EXPORT_SYMBOL(iwl_rx_pm_sleep_notif);
>  void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
>                                      struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
>        IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
>                        "notification for %s:\n", len,
> @@ -2199,7 +2198,7 @@ EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
>  void iwl_rx_reply_error(struct iwl_priv *priv,
>                        struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>
>        IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
>                "seq 0x%04X ser 0x%08X\n",
> diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
> index cec673b..b877f88 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-core.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-core.h
> @@ -531,7 +531,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
>                           const void *data,
>                           void (*callback)(struct iwl_priv *priv,
>                                            struct iwl_device_cmd *cmd,
> -                                           struct sk_buff *skb));
> +                                           struct iwl_rx_packet *pkt));
>
>  int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
> index 451aa65..35d5794 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-dev.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
> @@ -146,12 +146,13 @@ extern void iwl5000_temperature(struct iwl_priv *priv);
>  #define        DEFAULT_LONG_RETRY_LIMIT  4U
>
>  struct iwl_rx_mem_buffer {
> -       dma_addr_t real_dma_addr;
> -       dma_addr_t aligned_dma_addr;
> -       struct sk_buff *skb;
> +       dma_addr_t page_dma;
> +       struct page *page;
>        struct list_head list;
>  };
>
> +#define rxb_addr(r) page_address(r->page)
> +
>  /* defined below */
>  struct iwl_device_cmd;
>
> @@ -167,7 +168,7 @@ struct iwl_cmd_meta {
>         */
>        void (*callback)(struct iwl_priv *priv,
>                         struct iwl_device_cmd *cmd,
> -                        struct sk_buff *skb);
> +                        struct iwl_rx_packet *pkt);
>
>        /* The CMD_SIZE_HUGE flag bit indicates that the command
>         * structure is stored at the end of the shared queue memory. */
> @@ -366,6 +367,13 @@ enum {
>
>  #define IWL_CMD_MAX_PAYLOAD 320
>
> +/*
> + * IWL_LINK_HDR_MAX should include ieee80211_hdr, radiotap header,
> + * SNAP header and alignment. It should also be big enough for 802.11
> + * control frames.
> + */
> +#define IWL_LINK_HDR_MAX 64
> +
>  /**
>  * struct iwl_device_cmd
>  *
> @@ -390,10 +398,10 @@ struct iwl_device_cmd {
>
>  struct iwl_host_cmd {
>        const void *data;
> -       struct sk_buff *reply_skb;
> +       unsigned long reply_page;
>        void (*callback)(struct iwl_priv *priv,
>                         struct iwl_device_cmd *cmd,
> -                        struct sk_buff *skb);
> +                        struct iwl_rx_packet *pkt);
>        u32 flags;
>        u16 len;
>        u8 id;
> @@ -650,7 +658,7 @@ struct iwl_sensitivity_ranges {
>  * @valid_tx/rx_ant: usable antennas
>  * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
>  * @max_rxq_log: Log-base-2 of max_rxq_size
> - * @rx_buf_size: Rx buffer size
> + * @rx_page_order: Rx buffer page order
>  * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
>  * @max_stations:
>  * @bcast_sta_id:
> @@ -673,9 +681,8 @@ struct iwl_hw_params {
>        u8  valid_rx_ant;
>        u16 max_rxq_size;
>        u16 max_rxq_log;
> -       u32 rx_buf_size;
> +       u32 rx_page_order;
>        u32 rx_wrt_ptr_reg;
> -       u32 max_pkt_size;
>        u8  max_stations;
>        u8  bcast_sta_id;
>        u8  ht40_channel;
> @@ -987,7 +994,7 @@ struct iwl_priv {
>        int frames_count;
>
>        enum ieee80211_band band;
> -       int alloc_rxb_skb;
> +       int alloc_rxb_page;
>
>        void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
>                                       struct iwl_rx_mem_buffer *rxb);
> diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
> index 532c8d6..22a21a1 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
> @@ -103,17 +103,8 @@ EXPORT_SYMBOL(get_cmd_string);
>
>  static void iwl_generic_cmd_callback(struct iwl_priv *priv,
>                                     struct iwl_device_cmd *cmd,
> -                                    struct sk_buff *skb)
> +                                    struct iwl_rx_packet *pkt)
>  {
> -       struct iwl_rx_packet *pkt = NULL;
> -
> -       if (!skb) {
> -               IWL_ERR(priv, "Error: Response NULL in %s.\n",
> -                               get_cmd_string(cmd->hdr.cmd));
> -               return;
> -       }
> -
> -       pkt = (struct iwl_rx_packet *)skb->data;
>        if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
>                IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
>                        get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
> @@ -215,7 +206,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
>                ret = -EIO;
>                goto fail;
>        }
> -       if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) {
> +       if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
>                IWL_ERR(priv, "Error: Response NULL in '%s'\n",
>                          get_cmd_string(cmd->id));
>                ret = -EIO;
> @@ -237,9 +228,9 @@ cancel:
>                                                        ~CMD_WANT_SKB;
>        }
>  fail:
> -       if (cmd->reply_skb) {
> -               dev_kfree_skb_any(cmd->reply_skb);
> -               cmd->reply_skb = NULL;
> +       if (cmd->reply_page) {
> +               free_pages(cmd->reply_page, priv->hw_params.rx_page_order);
> +               cmd->reply_page = 0;
>        }
>  out:
>        clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
> @@ -272,7 +263,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
>                           u8 id, u16 len, const void *data,
>                           void (*callback)(struct iwl_priv *priv,
>                                            struct iwl_device_cmd *cmd,
> -                                           struct sk_buff *skb))
> +                                           struct iwl_rx_packet *pkt))
>  {
>        struct iwl_host_cmd cmd = {
>                .id = id,
> diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
> index 7ad327e..0a407f7 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-rx.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
> @@ -200,7 +200,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
>                list_del(element);
>
>                /* Point to Rx buffer via next RBD in circular buffer */
> -               rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr);
> +               rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma);
>                rxq->queue[rxq->write] = rxb;
>                rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
>                rxq->free_count--;
> @@ -239,7 +239,7 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
>        struct iwl_rx_queue *rxq = &priv->rxq;
>        struct list_head *element;
>        struct iwl_rx_mem_buffer *rxb;
> -       struct sk_buff *skb;
> +       struct page *page;
>        unsigned long flags;
>
>        while (1) {
> @@ -252,29 +252,34 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
>
>                if (rxq->free_count > RX_LOW_WATERMARK)
>                        priority |= __GFP_NOWARN;
> -               /* Alloc a new receive buffer */
> -               skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
> -                                               priority);
>
> -               if (!skb) {
> +               if (priv->hw_params.rx_page_order > 0)
> +                       priority |= __GFP_COMP;
> +
> +               /* Alloc a new receive buffer */
> +               page = alloc_pages(priority, priv->hw_params.rx_page_order);
> +               if (!page) {
>                        if (net_ratelimit())
> -                               IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
> +                               IWL_DEBUG_INFO(priv, "alloc_pages failed, "
> +                                              "order: %d\n",
> +                                              priv->hw_params.rx_page_order);
> +
>                        if ((rxq->free_count <= RX_LOW_WATERMARK) &&
>                            net_ratelimit())
> -                               IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
> +                               IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n",
>                                         priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
>                                         rxq->free_count);
>                        /* We don't reschedule replenish work here -- we will
>                         * call the restock method and if it still needs
>                         * more buffers it will schedule replenish */
> -                       break;
> +                       return;
>                }
>
>                spin_lock_irqsave(&rxq->lock, flags);
>
>                if (list_empty(&rxq->rx_used)) {
>                        spin_unlock_irqrestore(&rxq->lock, flags);
> -                       dev_kfree_skb_any(skb);
> +                       __free_pages(page, priv->hw_params.rx_page_order);
>                        return;
>                }
>                element = rxq->rx_used.next;
> @@ -283,24 +288,21 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
>
>                spin_unlock_irqrestore(&rxq->lock, flags);
>
> -               rxb->skb = skb;
> -               /* Get physical address of RB/SKB */
> -               rxb->real_dma_addr = pci_map_single(
> -                                       priv->pci_dev,
> -                                       rxb->skb->data,
> -                                       priv->hw_params.rx_buf_size + 256,
> -                                       PCI_DMA_FROMDEVICE);
> +               rxb->page = page;
> +               /* Get physical address of the RB */
> +               rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
> +                               PAGE_SIZE << priv->hw_params.rx_page_order,
> +                               PCI_DMA_FROMDEVICE);
>                /* dma address must be no more than 36 bits */
> -               BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36));
> +               BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
>                /* and also 256 byte aligned! */
> -               rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256);
> -               skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr);
> +               BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
>
>                spin_lock_irqsave(&rxq->lock, flags);
>
>                list_add_tail(&rxb->list, &rxq->rx_free);
>                rxq->free_count++;
> -               priv->alloc_rxb_skb++;
> +               priv->alloc_rxb_page++;
>
>                spin_unlock_irqrestore(&rxq->lock, flags);
>        }
> @@ -336,12 +338,14 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
>  {
>        int i;
>        for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
> -               if (rxq->pool[i].skb != NULL) {
> -                       pci_unmap_single(priv->pci_dev,
> -                                        rxq->pool[i].real_dma_addr,
> -                                        priv->hw_params.rx_buf_size + 256,
> -                                        PCI_DMA_FROMDEVICE);
> -                       dev_kfree_skb(rxq->pool[i].skb);
> +               if (rxq->pool[i].page != NULL) {
> +                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
> +                               PAGE_SIZE << priv->hw_params.rx_page_order,
> +                               PCI_DMA_FROMDEVICE);
> +                       __free_pages(rxq->pool[i].page,
> +                                    priv->hw_params.rx_page_order);
> +                       rxq->pool[i].page = NULL;
> +                       priv->alloc_rxb_page--;
>                }
>        }
>
> @@ -405,14 +409,14 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
>        for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
>                /* In the reset function, these buffers may have been allocated
>                 * to an SKB, so we need to unmap and free potential storage */
> -               if (rxq->pool[i].skb != NULL) {
> -                       pci_unmap_single(priv->pci_dev,
> -                                        rxq->pool[i].real_dma_addr,
> -                                        priv->hw_params.rx_buf_size + 256,
> -                                        PCI_DMA_FROMDEVICE);
> -                       priv->alloc_rxb_skb--;
> -                       dev_kfree_skb(rxq->pool[i].skb);
> -                       rxq->pool[i].skb = NULL;
> +               if (rxq->pool[i].page != NULL) {
> +                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
> +                               PAGE_SIZE << priv->hw_params.rx_page_order,
> +                               PCI_DMA_FROMDEVICE);
> +                       priv->alloc_rxb_page--;
> +                       __free_pages(rxq->pool[i].page,
> +                                    priv->hw_params.rx_page_order);
> +                       rxq->pool[i].page = NULL;
>                }
>                list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
>        }
> @@ -491,7 +495,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
>                                struct iwl_rx_mem_buffer *rxb)
>
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_missed_beacon_notif *missed_beacon;
>
>        missed_beacon = &pkt->u.missed_beacon;
> @@ -592,7 +596,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
>                              struct iwl_rx_mem_buffer *rxb)
>  {
>        int change;
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>
>        IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
>                     (int)sizeof(priv->statistics),
> @@ -919,6 +923,9 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
>                                        struct iwl_rx_mem_buffer *rxb,
>                                        struct ieee80211_rx_status *stats)
>  {
> +       struct sk_buff *skb;
> +       int ret = 0;
> +
>        /* We only process data packets if the interface is open */
>        if (unlikely(!priv->is_open)) {
>                IWL_DEBUG_DROP_LIMIT(priv,
> @@ -931,15 +938,38 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
>            iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
>                return;
>
> -       /* Resize SKB from mac header to end of packet */
> -       skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data);
> -       skb_put(rxb->skb, len);
> +       skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
> +       if (!skb) {
> +               IWL_ERR(priv, "alloc_skb failed\n");
> +               return;
> +       }
> +
> +       skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
> +
> +       /* mac80211 currently doesn't support paged SKB. Convert it to
> +        * linear SKB for management frame and data frame requires
> +        * software decryption or software defragementation. */
> +       if (ieee80211_is_mgmt(hdr->frame_control) ||
> +           ieee80211_has_protected(hdr->frame_control) ||
> +           ieee80211_has_morefrags(hdr->frame_control) ||
> +           le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
> +               ret = skb_linearize(skb);
> +       else
> +               ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
> +                        0 : -ENOMEM;
> +
> +       if (ret) {
> +               kfree_skb(skb);
> +               goto out;
> +       }
>
>        iwl_update_stats(priv, false, hdr->frame_control, len);
> -       memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
> -       ieee80211_rx_irqsafe(priv->hw, rxb->skb);
> -       priv->alloc_rxb_skb--;
> -       rxb->skb = NULL;
> +       memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
> +
> +       ieee80211_rx(priv->hw, skb);
> + out:
> +       priv->alloc_rxb_page--;
> +       rxb->page = NULL;
>  }
>
>  /* This is necessary only for a number of statistics, see the caller. */
> @@ -967,7 +997,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
>  {
>        struct ieee80211_hdr *header;
>        struct ieee80211_rx_status rx_status;
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_rx_phy_res *phy_res;
>        __le32 rx_pkt_status;
>        struct iwl4965_rx_mpdu_res_start *amsdu;
> @@ -1128,7 +1158,7 @@ EXPORT_SYMBOL(iwl_rx_reply_rx);
>  void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
>                                    struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        priv->last_phy_res[0] = 1;
>        memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
>               sizeof(struct iwl_rx_phy_res));
> diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
> index 41f9a06..4fca65a 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-scan.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
> @@ -111,7 +111,7 @@ EXPORT_SYMBOL(iwl_scan_cancel_timeout);
>  static int iwl_send_scan_abort(struct iwl_priv *priv)
>  {
>        int ret = 0;
> -       struct iwl_rx_packet *res;
> +       struct iwl_rx_packet *pkt;
>        struct iwl_host_cmd cmd = {
>                .id = REPLY_SCAN_ABORT_CMD,
>                .flags = CMD_WANT_SKB,
> @@ -131,21 +131,21 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
>                return ret;
>        }
>
> -       res = (struct iwl_rx_packet *)cmd.reply_skb->data;
> -       if (res->u.status != CAN_ABORT_STATUS) {
> +       pkt = (struct iwl_rx_packet *)cmd.reply_page;
> +       if (pkt->u.status != CAN_ABORT_STATUS) {
>                /* The scan abort will return 1 for success or
>                 * 2 for "failure".  A failure condition can be
>                 * due to simply not being in an active scan which
>                 * can occur if we send the scan abort before we
>                 * the microcode has notified us that a scan is
>                 * completed. */
> -               IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", res->u.status);
> +               IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status);
>                clear_bit(STATUS_SCAN_ABORTING, &priv->status);
>                clear_bit(STATUS_SCAN_HW, &priv->status);
>        }
>
> -       priv->alloc_rxb_skb--;
> -       dev_kfree_skb_any(cmd.reply_skb);
> +       priv->alloc_rxb_page--;
> +       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
>
>        return ret;
>  }
> @@ -155,7 +155,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
>                              struct iwl_rx_mem_buffer *rxb)
>  {
>  #ifdef CONFIG_IWLWIFI_DEBUG
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_scanreq_notification *notif =
>            (struct iwl_scanreq_notification *)pkt->u.raw;
>
> @@ -167,7 +167,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
>  static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
>                                    struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_scanstart_notification *notif =
>            (struct iwl_scanstart_notification *)pkt->u.raw;
>        priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
> @@ -186,7 +186,7 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
>                                      struct iwl_rx_mem_buffer *rxb)
>  {
>  #ifdef CONFIG_IWLWIFI_DEBUG
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_scanresults_notification *notif =
>            (struct iwl_scanresults_notification *)pkt->u.raw;
>
> @@ -213,7 +213,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
>                                       struct iwl_rx_mem_buffer *rxb)
>  {
>  #ifdef CONFIG_IWLWIFI_DEBUG
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
>
>        IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
> diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c
> index 022bcf1..1ea5cd3 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c
> @@ -177,7 +177,7 @@ static int iwl_get_measurement(struct iwl_priv *priv,
>  static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
>                                          struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
>
>        if (!report->state) {
> diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
> index c6633fe..dc74c16 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-sta.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
> @@ -99,32 +99,25 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
>
>  static void iwl_add_sta_callback(struct iwl_priv *priv,
>                                 struct iwl_device_cmd *cmd,
> -                                struct sk_buff *skb)
> +                                struct iwl_rx_packet *pkt)
>  {
> -       struct iwl_rx_packet *res = NULL;
>        struct iwl_addsta_cmd *addsta =
>                (struct iwl_addsta_cmd *)cmd->cmd.payload;
>        u8 sta_id = addsta->sta.sta_id;
>
> -       if (!skb) {
> -               IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n");
> -               return;
> -       }
> -
> -       res = (struct iwl_rx_packet *)skb->data;
> -       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
> +       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
>                IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
> -                         res->hdr.flags);
> +                         pkt->hdr.flags);
>                return;
>        }
>
> -       switch (res->u.add_sta.status) {
> +       switch (pkt->u.add_sta.status) {
>        case ADD_STA_SUCCESS_MSK:
>                iwl_sta_ucode_activate(priv, sta_id);
>                 /* fall through */
>        default:
>                IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
> -                            res->u.add_sta.status);
> +                            pkt->u.add_sta.status);
>                break;
>        }
>  }
> @@ -132,7 +125,7 @@ static void iwl_add_sta_callback(struct iwl_priv *priv,
>  int iwl_send_add_sta(struct iwl_priv *priv,
>                     struct iwl_addsta_cmd *sta, u8 flags)
>  {
> -       struct iwl_rx_packet *res = NULL;
> +       struct iwl_rx_packet *pkt = NULL;
>        int ret = 0;
>        u8 data[sizeof(*sta)];
>        struct iwl_host_cmd cmd = {
> @@ -152,15 +145,15 @@ int iwl_send_add_sta(struct iwl_priv *priv,
>        if (ret || (flags & CMD_ASYNC))
>                return ret;
>
> -       res = (struct iwl_rx_packet *)cmd.reply_skb->data;
> -       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
> +       pkt = (struct iwl_rx_packet *)cmd.reply_page;
> +       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
>                IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
> -                         res->hdr.flags);
> +                         pkt->hdr.flags);
>                ret = -EIO;
>        }
>
>        if (ret == 0) {
> -               switch (res->u.add_sta.status) {
> +               switch (pkt->u.add_sta.status) {
>                case ADD_STA_SUCCESS_MSK:
>                        iwl_sta_ucode_activate(priv, sta->sta.sta_id);
>                        IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
> @@ -172,8 +165,8 @@ int iwl_send_add_sta(struct iwl_priv *priv,
>                }
>        }
>
> -       priv->alloc_rxb_skb--;
> -       dev_kfree_skb_any(cmd.reply_skb);
> +       priv->alloc_rxb_page--;
> +       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
>
>        return ret;
>  }
> @@ -324,26 +317,19 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
>
>  static void iwl_remove_sta_callback(struct iwl_priv *priv,
>                                    struct iwl_device_cmd *cmd,
> -                                   struct sk_buff *skb)
> +                                   struct iwl_rx_packet *pkt)
>  {
> -       struct iwl_rx_packet *res = NULL;
>        struct iwl_rem_sta_cmd *rm_sta =
> -                (struct iwl_rem_sta_cmd *)cmd->cmd.payload;
> +                       (struct iwl_rem_sta_cmd *)cmd->cmd.payload;
>        const char *addr = rm_sta->addr;
>
> -       if (!skb) {
> -               IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n");
> -               return;
> -       }
> -
> -       res = (struct iwl_rx_packet *)skb->data;
> -       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
> +       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
>                IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
> -               res->hdr.flags);
> +               pkt->hdr.flags);
>                return;
>        }
>
> -       switch (res->u.rem_sta.status) {
> +       switch (pkt->u.rem_sta.status) {
>        case REM_STA_SUCCESS_MSK:
>                iwl_sta_ucode_deactivate(priv, addr);
>                break;
> @@ -356,7 +342,7 @@ static void iwl_remove_sta_callback(struct iwl_priv *priv,
>  static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
>                                   u8 flags)
>  {
> -       struct iwl_rx_packet *res = NULL;
> +       struct iwl_rx_packet *pkt;
>        int ret;
>
>        struct iwl_rem_sta_cmd rm_sta_cmd;
> @@ -381,15 +367,15 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
>        if (ret || (flags & CMD_ASYNC))
>                return ret;
>
> -       res = (struct iwl_rx_packet *)cmd.reply_skb->data;
> -       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
> +       pkt = (struct iwl_rx_packet *)cmd.reply_page;
> +       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
>                IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
> -                         res->hdr.flags);
> +                         pkt->hdr.flags);
>                ret = -EIO;
>        }
>
>        if (!ret) {
> -               switch (res->u.rem_sta.status) {
> +               switch (pkt->u.rem_sta.status) {
>                case REM_STA_SUCCESS_MSK:
>                        iwl_sta_ucode_deactivate(priv, addr);
>                        IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
> @@ -401,8 +387,8 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
>                }
>        }
>
> -       priv->alloc_rxb_skb--;
> -       dev_kfree_skb_any(cmd.reply_skb);
> +       priv->alloc_rxb_page--;
> +       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
>
>        return ret;
>  }
> diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
> index d0bd7cd..5c43d7c 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-tx.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
> @@ -1153,7 +1153,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
>  */
>  void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
>        int txq_id = SEQ_TO_QUEUE(sequence);
>        int index = SEQ_TO_INDEX(sequence);
> @@ -1180,10 +1180,10 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
>
>        /* Input error checking is done when commands are added to queue. */
>        if (meta->flags & CMD_WANT_SKB) {
> -               meta->source->reply_skb = rxb->skb;
> -               rxb->skb = NULL;
> +               meta->source->reply_page = (unsigned long)rxb_addr(rxb);
> +               rxb->page = NULL;
>        } else if (meta->callback)
> -               meta->callback(priv, cmd, rxb->skb);
> +               meta->callback(priv, cmd, pkt);
>
>        iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
>
> @@ -1442,7 +1442,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
>  void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
>                                           struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
>        struct iwl_tx_queue *txq = NULL;
>        struct iwl_ht_agg *agg;
> diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> index 515f29b..5977a57 100644
> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> @@ -745,7 +745,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
>                               u8 type)
>  {
>        struct iwl_spectrum_cmd spectrum;
> -       struct iwl_rx_packet *res;
> +       struct iwl_rx_packet *pkt;
>        struct iwl_host_cmd cmd = {
>                .id = REPLY_SPECTRUM_MEASUREMENT_CMD,
>                .data = (void *)&spectrum,
> @@ -790,18 +790,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
>        if (rc)
>                return rc;
>
> -       res = (struct iwl_rx_packet *)cmd.reply_skb->data;
> -       if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
> +       pkt = (struct iwl_rx_packet *)cmd.reply_page;
> +       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
>                IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
>                rc = -EIO;
>        }
>
> -       spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
> +       spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
>        switch (spectrum_resp_status) {
>        case 0:         /* Command will be handled */
> -               if (res->u.spectrum.id != 0xff) {
> +               if (pkt->u.spectrum.id != 0xff) {
>                        IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
> -                                               res->u.spectrum.id);
> +                                               pkt->u.spectrum.id);
>                        priv->measurement_status &= ~MEASUREMENT_READY;
>                }
>                priv->measurement_status |= MEASUREMENT_ACTIVE;
> @@ -813,7 +813,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
>                break;
>        }
>
> -       dev_kfree_skb_any(cmd.reply_skb);
> +       free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
>
>        return rc;
>  }
> @@ -822,7 +822,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
>  static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
>                               struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl_alive_resp *palive;
>        struct delayed_work *pwork;
>
> @@ -859,7 +859,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
>                                 struct iwl_rx_mem_buffer *rxb)
>  {
>  #ifdef CONFIG_IWLWIFI_DEBUG
> -       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>  #endif
>
>        IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
> @@ -895,7 +895,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
>                                struct iwl_rx_mem_buffer *rxb)
>  {
>  #ifdef CONFIG_IWLWIFI_DEBUG
> -       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
>        u8 rate = beacon->beacon_notify_hdr.rate;
>
> @@ -918,7 +918,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
>  static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
>                                    struct iwl_rx_mem_buffer *rxb)
>  {
> -       struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
> +       struct iwl_rx_packet *pkt = rxb_addr(rxb);
>        u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
>        unsigned long status = priv->status;
>
> @@ -1082,7 +1082,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
>                list_del(element);
>
>                /* Point to Rx buffer via next RBD in circular buffer */
> -               rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr);
> +               rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma);
>                rxq->queue[rxq->write] = rxb;
>                rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
>                rxq->free_count--;
> @@ -1122,7 +1122,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
>        struct iwl_rx_queue *rxq = &priv->rxq;
>        struct list_head *element;
>        struct iwl_rx_mem_buffer *rxb;
> -       struct sk_buff *skb;
> +       struct page *page;
>        unsigned long flags;
>
>        while (1) {
> @@ -1136,9 +1136,13 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
>
>                if (rxq->free_count > RX_LOW_WATERMARK)
>                        priority |= __GFP_NOWARN;
> +
> +               if (priv->hw_params.rx_page_order > 0)
> +                       priority |= __GFP_COMP;
> +
>                /* Alloc a new receive buffer */
> -               skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
> -               if (!skb) {
> +               page = alloc_pages(priority, priv->hw_params.rx_page_order);
> +               if (!page) {
>                        if (net_ratelimit())
>                                IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
>                        if ((rxq->free_count <= RX_LOW_WATERMARK) &&
> @@ -1155,7 +1159,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
>                spin_lock_irqsave(&rxq->lock, flags);
>                if (list_empty(&rxq->rx_used)) {
>                        spin_unlock_irqrestore(&rxq->lock, flags);
> -                       dev_kfree_skb_any(skb);
> +                       __free_pages(page, priv->hw_params.rx_page_order);
>                        return;
>                }
>                element = rxq->rx_used.next;
> @@ -1163,26 +1167,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
>                list_del(element);
>                spin_unlock_irqrestore(&rxq->lock, flags);
>
> -               rxb->skb = skb;
> -
> -               /* If radiotap head is required, reserve some headroom here.
> -                * The physical head count is a variable rx_stats->phy_count.
> -                * We reserve 4 bytes here. Plus these extra bytes, the
> -                * headroom of the physical head should be enough for the
> -                * radiotap head that iwl3945 supported. See iwl3945_rt.
> -                */
> -               skb_reserve(rxb->skb, 4);
> -
> +               rxb->page = page;
>                /* Get physical address of RB/SKB */
> -               rxb->real_dma_addr = pci_map_single(priv->pci_dev,
> -                                               rxb->skb->data,
> -                                               priv->hw_params.rx_buf_size,
> -                                               PCI_DMA_FROMDEVICE);
> +               rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
> +                               PAGE_SIZE << priv->hw_params.rx_page_order,
> +                               PCI_DMA_FROMDEVICE);
>
>                spin_lock_irqsave(&rxq->lock, flags);
> +
>                list_add_tail(&rxb->list, &rxq->rx_free);
> -               priv->alloc_rxb_skb++;
>                rxq->free_count++;
> +               priv->alloc_rxb_page++;
> +
>                spin_unlock_irqrestore(&rxq->lock, flags);
>        }
>  }
> @@ -1198,14 +1194,14 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
>        for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
>                /* In the reset function, these buffers may have been allocated
>                 * to an SKB, so we need to unmap and free potential storage */
> -               if (rxq->pool[i].skb != NULL) {
> -                       pci_unmap_single(priv->pci_dev,
> -                                        rxq->pool[i].real_dma_addr,
> -                                        priv->hw_params.rx_buf_size,
> -                                        PCI_DMA_FROMDEVICE);
> -                       priv->alloc_rxb_skb--;
> -                       dev_kfree_skb(rxq->pool[i].skb);
> -                       rxq->pool[i].skb = NULL;
> +               if (rxq->pool[i].page != NULL) {
> +                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
> +                               PAGE_SIZE << priv->hw_params.rx_page_order,
> +                               PCI_DMA_FROMDEVICE);
> +                       priv->alloc_rxb_page--;
> +                       __free_pages(rxq->pool[i].page,
> +                                    priv->hw_params.rx_page_order);
> +                       rxq->pool[i].page = NULL;
>                }
>                list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
>        }
> @@ -1213,8 +1209,8 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
>        /* Set us so that we have processed and used all buffers, but have
>         * not restocked the Rx queue with fresh buffers */
>        rxq->read = rxq->write = 0;
> -       rxq->free_count = 0;
>        rxq->write_actual = 0;
> +       rxq->free_count = 0;
>        spin_unlock_irqrestore(&rxq->lock, flags);
>  }
>
> @@ -1247,12 +1243,14 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
>  {
>        int i;
>        for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
> -               if (rxq->pool[i].skb != NULL) {
> -                       pci_unmap_single(priv->pci_dev,
> -                                        rxq->pool[i].real_dma_addr,
> -                                        priv->hw_params.rx_buf_size,
> -                                        PCI_DMA_FROMDEVICE);
> -                       dev_kfree_skb(rxq->pool[i].skb);
> +               if (rxq->pool[i].page != NULL) {
> +                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
> +                               PAGE_SIZE << priv->hw_params.rx_page_order,
> +                               PCI_DMA_FROMDEVICE);
> +                       __free_pages(rxq->pool[i].page,
> +                                    priv->hw_params.rx_page_order);
> +                       rxq->pool[i].page = NULL;
> +                       priv->alloc_rxb_page--;
>                }
>        }
>
> @@ -1388,10 +1386,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
>
>                rxq->queue[i] = NULL;
>
> -               pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
> -                               priv->hw_params.rx_buf_size,
> -                               PCI_DMA_FROMDEVICE);
> -               pkt = (struct iwl_rx_packet *)rxb->skb->data;
> +               pci_unmap_page(priv->pci_dev, rxb->page_dma,
> +                              PAGE_SIZE << priv->hw_params.rx_page_order,
> +                              PCI_DMA_FROMDEVICE);
> +               pkt = rxb_addr(rxb);
>
>                trace_iwlwifi_dev_rx(priv, pkt,
>                        le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
> @@ -1416,16 +1414,17 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
>                        priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
>                } else {
>                        /* No handling needed */
> -                       IWL_DEBUG_RX(priv, "r %d i %d No handler needed for %s, 0x%02x\n",
> +                       IWL_DEBUG_RX(priv,
> +                               "r %d i %d No handler needed for %s, 0x%02x\n",
>                                r, i, get_cmd_string(pkt->hdr.cmd),
>                                pkt->hdr.cmd);
>                }
>
>                if (reclaim) {
> -                       /* Invoke any callbacks, transfer the skb to caller, and
> -                        * fire off the (possibly) blocking iwl_send_cmd()
> +                       /* Invoke any callbacks, transfer the buffer to caller,
> +                        * and fire off the (possibly) blocking iwl_send_cmd()
>                         * as we reclaim the driver command queue */
> -                       if (rxb && rxb->skb)
> +                       if (rxb && rxb->page)
>                                iwl_tx_cmd_complete(priv, rxb);
>                        else
>                                IWL_WARN(priv, "Claim null rxb?\n");
> @@ -1434,10 +1433,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
>                /* For now we just don't re-use anything.  We can tweak this
>                 * later to try and re-use notification packets and SKBs that
>                 * fail to Rx correctly */
> -               if (rxb->skb != NULL) {
> -                       priv->alloc_rxb_skb--;
> -                       dev_kfree_skb_any(rxb->skb);
> -                       rxb->skb = NULL;
> +               if (rxb->page != NULL) {
> +                       priv->alloc_rxb_page--;
> +                       __free_pages(rxb->page, priv->hw_params.rx_page_order);
> +                       rxb->page = NULL;
>                }
>
>                spin_lock_irqsave(&rxq->lock, flags);
> @@ -1678,6 +1677,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
>        }
>  #endif
>
> +       spin_unlock_irqrestore(&priv->lock, flags);
> +
>        /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
>         * atomic, make sure that inta covers all the interrupts that
>         * we've discovered, even if FH interrupt came in just after
> @@ -1699,8 +1700,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
>
>                handled |= CSR_INT_BIT_HW_ERR;
>
> -               spin_unlock_irqrestore(&priv->lock, flags);
> -
>                return;
>        }
>
> @@ -1792,7 +1791,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
>                        "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
>        }
>  #endif
> -       spin_unlock_irqrestore(&priv->lock, flags);
>  }
>
>  static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
> --
> 1.6.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

[-- Attachment #2: 0001-iwl3945-and-iwlagn-use-ieee80211_rx_ni.patch --]
[-- Type: text/x-diff, Size: 1431 bytes --]

From b0ef3780e9562dd00447bb56d1792f05dd1edb66 Mon Sep 17 00:00:00 2001
From: Sedat Dilek <sedat.dilek@gmail.com>
Date: Wed, 14 Oct 2009 17:12:03 +0200
Subject: [PATCH] iwl3945 and iwlagn: use ieee80211_rx_ni()

---
 drivers/net/wireless/iwlwifi/iwl-3945.c |    2 +-
 drivers/net/wireless/iwlwifi/iwl-rx.c   |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index afe19f2..c365a9d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -600,7 +600,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
 	iwl_update_stats(priv, false, hdr->frame_control, len);
 
 	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-	ieee80211_rx(priv->hw, skb);
+	ieee80211_rx_ni(priv->hw, skb);
 
  out:
 	priv->alloc_rxb_page--;
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 0a407f7..1e12a09 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -966,7 +966,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
 	iwl_update_stats(priv, false, hdr->frame_control, len);
 	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
 
-	ieee80211_rx(priv->hw, skb);
+	ieee80211_rx_ni(priv->hw, skb);
  out:
 	priv->alloc_rxb_page--;
 	rxb->page = NULL;
-- 
1.6.3.1


^ permalink raw reply related

* Re: Moving drivers into staging (was Re: [GIT PULL] SCSI fixes for 2.6.32-rc3)
From: Stefan Richter @ 2009-10-14 19:00 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Joe Perches, Greg KH, Luis R. Rodriguez, James Bottomley,
	Linus Torvalds, Theodore Tso, Andrew Morton, linux-scsi,
	linux-kernel, Jing Huang, netdev, linux-wireless
In-Reply-To: <20091014183657.GB5133@elte.hu>

On 14 Oct, Ingo Molnar wrote:
> * Stefan Richter <stefanr@s5r6.in-berlin.de> wrote:
>> How well do "git am", "quilt import" and friends cope with ever 
>> changing directories?

[Perhaps the -p option does the trick.  And git-am could be done on a
temporary branch from before the move of the files.]

> Once a driver is in a tree it's in Git and git mv is easy. People 
> working with Linux better familiarize themselves with Git workflow - the 
> sooner the better.

Even if author and committer both work with git, they often use e-mail
to transfer patches.

> If it's not in tree then it will adopt to whatever layout there is once 
> it gets into Greg's tree.

Many "good" drivers will start as "ugly" or "bad" ones.

>> How about using drivers/staging/this_driver/TODO and (or) its Kconfig 
>> help text to leave a note about the plans for this driver?
> 
> Well, the answer is obvious i think. Tell me, at a glance, if you see a 
> patch on lkml, which one is for a staging driver to be obsoleted, and 
> which one is the one going upstream real soon? The patches say:
> 
>  +++ a/drivers/staging/foo/x.c
> 
>  +++ a/drivers/staging/bar/y.c
> 
> Then tell me the same at a glance if you see patches for:
> 
>  +++ a/drivers/staging/wip/x.c
> 
>  +++ a/drivers/staging/bad/y.c

Does this information matter much?

What's more interesting is whether development activity will _lead_ to a
driver being moved from bad or ugly to good.
-- 
Stefan Richter
-=====-==--= =-=- -===-
http://arcgraph.de/sr/



^ permalink raw reply

* Re: Current status of rt2800usb and staging/rt2870
From: Ivo van Doorn @ 2009-10-14 18:56 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: John W. Linville, Dan Williams, Ozan Çağlayan,
	linux-wireless, linux-kernel
In-Reply-To: <200910141933.09374.bzolnier@gmail.com>

Hi,

> > On Wed, Oct 14, 2009 at 05:28:21PM +0200, Bartlomiej Zolnierkiewicz wrote:
> > 
> > > I don't have a have a problem with it personally as long as people accept
> > > the competition..  but instead of working on _their_ projects they go around
> > > screaming at everybody who does not want to spin inside the great process
> > > designed by them..
> > 
> > Please whine somewhere else.  You have the freedom to work in
> > drivers/staging all you want.  You do not have the power to force us to
> > like it -- especially in a case where you are diverting attention from
> > the community-maintained drivers instead of cooperating with them.
> 
> Cooperating you say.
> 
> rtl8187 -- before starting the work on rtl8187se I've pinged the maintainer
> to coordinate the effort and hear his opinion on how to progress..
> 
> I've never heard back.
> 
> rt2x00 -- I know that people have datasheets for some chipsets but I've
> never heard "How can we help you" etc. thing.

The rt2x00 members received the specsheets under the condition that we didn't
distribute them further.

So everybody which requested the datasheets from the rt2x00 project were presented
with a choice:
1) We provide the email address of the Ralink contact person which can device if you
can get the specsheet or not (possibly under NDA, but this isn't always the case).
2) Specific questions about the registers can be asked and we give all the information we
know from our work on the rt2x00 project plus additional information from the specsheet.
Seeing that the specsheet doesn't always match reality, you get the better answers with
this option, but some people just hate it when they need to ask other people for stuff.

> All I've ever heard was _lies_ about current state of affairs or that
> my work is in the way.

I have encounterd your email address in only 2 rt2x00 related discussions
(yes I have checked my entire email archive). Both cases were regarding
staging vs rt2x00.

So far I never said rt2800usb or rt2800pci were high quality, I never said they were in a good
shape. On the other hand, I often talked about the problems with the drivers, requesting help
to improve the drivers, etc etc.

So are you basing this "I am hearing lies" about a random person talking on the street
about rt2x00 which is telling the lie?

Ivo

^ permalink raw reply

* Re: Moving drivers into staging (was Re: [GIT PULL] SCSI fixes for 2.6.32-rc3)
From: Ingo Molnar @ 2009-10-14 18:36 UTC (permalink / raw)
  To: Stefan Richter
  Cc: Joe Perches, Greg KH, Luis R. Rodriguez, James Bottomley,
	Linus Torvalds, Theodore Tso, Andrew Morton, linux-scsi,
	linux-kernel, Jing Huang, netdev, linux-wireless
In-Reply-To: <4AD60FF9.40200@s5r6.in-berlin.de>


* Stefan Richter <stefanr@s5r6.in-berlin.de> wrote:

> Ingo Molnar wrote:
> > * Joe Perches <joe@perches.com> wrote:
> > 
> >> On Tue, 2009-10-13 at 21:45 -0700, Greg KH wrote:
> >> > How about when it was scheduled to be removed, we put it in staging and
> >> > I'll add it to my announcements about the staging tree every release?
> >> > Unless you can think of a better way?
> >> 
> >> staging/to_be_removed_unless_fixed_by/v.x.y ?
> > 
> > Yes, that's a real worry. Some time ago i suggested:
> > 
> >   drivers/staging/good/
> >   drivers/staging/bad/
> >   drivers/staging/ugly/
> 
> How well do "git am", "quilt import" and friends cope with ever 
> changing directories?

Once a driver is in a tree it's in Git and git mv is easy. People 
working with Linux better familiarize themselves with Git workflow - the 
sooner the better.

If it's not in tree then it will adopt to whatever layout there is once 
it gets into Greg's tree. I dont see the problem.

> How about using drivers/staging/this_driver/TODO and (or) its Kconfig 
> help text to leave a note about the plans for this driver?

Well, the answer is obvious i think. Tell me, at a glance, if you see a 
patch on lkml, which one is for a staging driver to be obsoleted, and 
which one is the one going upstream real soon? The patches say:

 +++ a/drivers/staging/foo/x.c

 +++ a/drivers/staging/bar/y.c

Then tell me the same at a glance if you see patches for:

 +++ a/drivers/staging/wip/x.c

 +++ a/drivers/staging/bad/y.c

> The worry that these will be ignored like 
> Documentation/feature-removal-schedule.txt is being ignored may apply 
> to the path name based solution too, I'm afraid.

It wont be 'ignored', as it's in every patch, it's in every commit, it's 
in every substantial communication about that driver.

The problem with feature-removal-schedule.txt is that it's too much out 
of sight and not part of the regular patch workflow. Same goes for any 
TODO file. Experience has shown that the actual _path_ were drivers end 
up does matter quite a bit, to general visibility and to mindset.

That's one of the reasons why we have _half a thousand_ directories in 
drivers/ to begin with. The directory namespace is very powerful, and we 
use it to convey all sorts of information about the logical category a 
driver is in.

Using it in drivers/staging/ instead of the current flat hierarchy would 
thus be pretty natural.

	Ingo

^ permalink raw reply

* Re: Current status of rt2800usb and staging/rt2870
From: Luis Correia @ 2009-10-14 18:26 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: John W. Linville, Dan Williams, Ivo van Doorn,
	Ozan Çağlayan, linux-wireless, linux-kernel
In-Reply-To: <200910141933.09374.bzolnier@gmail.com>

On Wed, Oct 14, 2009 at 18:33, Bartlomiej Zolnierkiewicz
<bzolnier@gmail.com> wrote:
> On Wednesday 14 October 2009 18:47:11 John W. Linville wrote:
>> On Wed, Oct 14, 2009 at 05:28:21PM +0200, Bartlomiej Zolnierkiewicz wrote:
>>
>> > I don't have a have a problem with it personally as long as people accept
>> > the competition..  but instead of working on _their_ projects they go around
>> > screaming at everybody who does not want to spin inside the great process
>> > designed by them..
>>
>> Please whine somewhere else.  You have the freedom to work in
>> drivers/staging all you want.  You do not have the power to force us to
>> like it -- especially in a case where you are diverting attention from
>> the community-maintained drivers instead of cooperating with them.
>
> Cooperating you say.
>
> rtl8187 -- before starting the work on rtl8187se I've pinged the maintainer
> to coordinate the effort and hear his opinion on how to progress..
>
> I've never heard back.
>
> rt2x00 -- I know that people have datasheets for some chipsets but I've
> never heard "How can we help you" etc. thing.

I have all the datasheets that Ralink supplied to us.
All of them are PRELIMINARY and most have errors, and therefore useless.

All useful information is in the crap drivers.

Ralink never provide better ones, and even our 'inside guy' says the
hardware documentation guys are always very late in providing more
info.

So, for me, it isn't lack of documentation that will ever help, believe me.

>
> All I've ever heard was _lies_ about current state of affairs or that
> my work is in the way.

AFAICS, your work was never questioned, at least by me.
You are welcome to work on rt2x00 , that was also never a problem. All
you would need is join in.

Ralink also said they were commited to present drivers for new chipset
to be mac80211 compliant, we're waiting on that.

So, you're really welcome to join the rt2x00 team Bartlomiej, the only
thing we ask is that all work should be done using the existing
rt2x00lib, rt2x00pci and rt2x00usb base 'libraries'.

Luis Correia,
rt2x00 project admin

^ permalink raw reply

* [PATCH] ath5k: use noise calibration from madwifi hal
From: Bob Copeland @ 2009-10-14 18:16 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ath5k-devel, jirislaby, mickflemm, lrodriguez,
	Bob Copeland

This updates ath5k to calibrate the noise floor similar to the
way it is done in the madwifi hal and ath9k.  Of note:

- we start NF measurement at the same time as AGC calibration,
  but do not actually read the value until the periodic (long)
  calibration
- we keep a history of the last few values read and write the
  median back to the hardware for CCA
- we do not complain if NF calibration isn't complete, instead
  we keep the last read value.

Signed-off-by: Bob Copeland <me@bobcopeland.com>
---
 drivers/net/wireless/ath/ath5k/ath5k.h  |   13 ++
 drivers/net/wireless/ath/ath5k/attach.c |    2 +
 drivers/net/wireless/ath/ath5k/phy.c    |  185 +++++++++++++++++++++----------
 drivers/net/wireless/ath/ath5k/reg.h    |   11 +-
 drivers/net/wireless/ath/ath5k/reset.c  |   17 +---
 5 files changed, 148 insertions(+), 80 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 6cd5efc..1c90d6b 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -204,6 +204,7 @@
 #define AR5K_TUNE_CWMAX_11B			1023
 #define AR5K_TUNE_CWMAX_XR			7
 #define AR5K_TUNE_NOISE_FLOOR			-72
+#define AR5K_TUNE_CCA_MAX_GOOD_VALUE		-95
 #define AR5K_TUNE_MAX_TXPOWER			63
 #define AR5K_TUNE_DEFAULT_TXPOWER		25
 #define AR5K_TUNE_TPC_TXPOWER			false
@@ -1012,6 +1013,14 @@ struct ath5k_capabilities {
 	} cap_queues;
 };
 
+/* size of noise floor history (keep it a power of two) */
+#define ATH5K_NF_CAL_HIST_MAX	8
+struct ath5k_nfcal_hist
+{
+	s16 index;				/* current index into nfval */
+	s16 nfval[ATH5K_NF_CAL_HIST_MAX];	/* last few noise floors */
+};
+
 
 /***************************************\
   HARDWARE ABSTRACTION LAYER STRUCTURE
@@ -1125,6 +1134,8 @@ struct ath5k_hw {
 		struct ieee80211_channel r_last_channel;
 	} ah_radar;
 
+	struct ath5k_nfcal_hist ah_nfcal_hist;
+
 	/* noise floor from last periodic calibration */
 	s32			ah_noise_floor;
 
@@ -1288,8 +1299,10 @@ extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
 extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
 extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
 /* PHY calibration */
+void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
 extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
 extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
+extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah);
 extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah);
 /* Spur mitigation */
 bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index 71a1bd2..1ec85af 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -342,6 +342,8 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc)
 
 	ath5k_hw_rfgain_opt_init(ah);
 
+	ath5k_hw_init_nfcal_hist(ah);
+
 	/* turn on HW LEDs */
 	ath5k_hw_set_ledstate(ah, AR5K_LED_INIT);
 
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 1a039f2..8959907 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1124,77 +1124,148 @@ ath5k_hw_calibration_poll(struct ath5k_hw *ah)
 		ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION;
 		AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI);
 	}
+}
 
+static int sign_extend(int val, const int nbits)
+{
+	int order = BIT(nbits-1);
+	return (val ^ order) - order;
 }
 
-/**
- * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
- *
- * @ah: struct ath5k_hw pointer we are operating on
- * @freq: the channel frequency, just used for error logging
- *
- * This function performs a noise floor calibration of the PHY and waits for
- * it to complete. Then the noise floor value is compared to some maximum
- * noise floor we consider valid.
- *
- * Note that this is different from what the madwifi HAL does: it reads the
- * noise floor and afterwards initiates the calibration. Since the noise floor
- * calibration can take some time to finish, depending on the current channel
- * use, that avoids the occasional timeout warnings we are seeing now.
- *
- * See the following link for an Atheros patent on noise floor calibration:
- * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
- * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
+static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah)
+{
+	s32 val;
+
+	val = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
+	return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9);
+}
+
+void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
+{
+	int i;
+
+	ah->ah_nfcal_hist.index = 0;
+	for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++)
+		ah->ah_nfcal_hist.nfval[i] = AR5K_TUNE_CCA_MAX_GOOD_VALUE;
+}
+
+static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor)
+{
+	struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist;
+	hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1);
+	hist->nfval[hist->index] = noise_floor;
+}
+
+static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
+{
+	s16 sort[ATH5K_NF_CAL_HIST_MAX];
+	s16 tmp;
+	int i, j;
+
+	memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort));
+	for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) {
+		for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) {
+			if (sort[j] > sort[j-1]) {
+				tmp = sort[j];
+				sort[j] = sort[j-1];
+				sort[j-1] = tmp;
+			}
+		}
+	}
+	for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) {
+		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+			"cal %d:%d\n", i, sort[i]);
+	}
+	return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2];
+}
+
+/*
+ * When we tell the hardware to perform a noise floor calibration
+ * by setting the AR5K_PHY_AGCCTL_NF bit, it will periodically
+ * sample-and-hold the minimum noise level seen at the antennas.
+ * This value is then stored in a ring buffer of recently measured
+ * noise floor values so we have a moving window of the last few
+ * samples.
  *
- * XXX: Since during noise floor calibration antennas are detached according to
- * the patent, we should stop tx queues here.
+ * The median of the values in the history is then loaded into the
+ * hardware for its own use for RSSI and CCA measurements.
  */
-int
-ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
+void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
 {
-	int ret;
-	unsigned int i;
-	s32 noise_floor;
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u32 val;
+	s16 nf, threshold;
+	u8 ee_mode;
 
-	/*
-	 * Enable noise floor calibration
-	 */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
-				AR5K_PHY_AGCCTL_NF);
+	/* keep last value if calibration hasn't completed */
+	if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) {
+		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+			"NF did not complete in calibration window\n");
 
-	ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
-			AR5K_PHY_AGCCTL_NF, 0, false);
-	if (ret) {
-		ATH5K_ERR(ah->ah_sc,
-			"noise floor calibration timeout (%uMHz)\n", freq);
-		return -EAGAIN;
+		return;
 	}
 
-	/* Wait until the noise floor is calibrated and read the value */
-	for (i = 20; i > 0; i--) {
-		mdelay(1);
-		noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
-		noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
-		if (noise_floor & AR5K_PHY_NF_ACTIVE) {
-			noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
-
-			if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
-				break;
-		}
+	switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) {
+	case CHANNEL_A:
+	case CHANNEL_T:
+	case CHANNEL_XR:
+		ee_mode = AR5K_EEPROM_MODE_11A;
+		break;
+	case CHANNEL_G:
+	case CHANNEL_TG:
+		ee_mode = AR5K_EEPROM_MODE_11G;
+		break;
+	default:
+	case CHANNEL_B:
+		ee_mode = AR5K_EEPROM_MODE_11B;
+		break;
 	}
 
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
-		"noise floor %d\n", noise_floor);
 
-	if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
-		ATH5K_ERR(ah->ah_sc,
-			"noise floor calibration failed (%uMHz)\n", freq);
-		return -EAGAIN;
+	/* completed NF calibration, test threshold */
+	nf = ath5k_hw_read_measured_noise_floor(ah);
+	threshold = ee->ee_noise_floor_thr[ee_mode];
+
+	if (nf > threshold) {
+		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+			"noise floor failure detected; "
+			"read %d, threshold %d\n",
+			nf, threshold);
+
+		nf = AR5K_TUNE_CCA_MAX_GOOD_VALUE;
 	}
 
-	ah->ah_noise_floor = noise_floor;
+	ath5k_hw_update_nfcal_hist(ah, nf);
+	nf = ath5k_hw_get_median_noise_floor(ah);
 
-	return 0;
+	/* load noise floor (in .5 dBm) so the hardware will use it */
+	val = ath5k_hw_reg_read(ah, AR5K_PHY_NF) & ~AR5K_PHY_NF_M;
+	val |= (nf * 2) & AR5K_PHY_NF_M;
+	ath5k_hw_reg_write(ah, val, AR5K_PHY_NF);
+
+	AR5K_REG_MASKED_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF,
+		~(AR5K_PHY_AGCCTL_NF_EN | AR5K_PHY_AGCCTL_NF_NOUPDATE));
+
+	ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF,
+		0, false);
+
+	/*
+	 * Load a high max CCA Power value (-50 dBm in .5 dBm units)
+	 * so that we're not capped by the median we just loaded.
+	 * This will be used as the initial value for the next noise
+	 * floor calibration.
+	 */
+	val = (val & ~AR5K_PHY_NF_M) | ((-50 * 2) & AR5K_PHY_NF_M);
+	ath5k_hw_reg_write(ah, val, AR5K_PHY_NF);
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+		AR5K_PHY_AGCCTL_NF_EN |
+		AR5K_PHY_AGCCTL_NF_NOUPDATE |
+		AR5K_PHY_AGCCTL_NF);
+
+	ah->ah_noise_floor = nf;
+
+	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+		"noise floor calibrated: %d\n", nf);
 }
 
 /*
@@ -1287,7 +1358,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
 		return ret;
 	}
 
-	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+	ath5k_hw_update_noise_floor(ah);
 
 	/*
 	 * Re-enable RX/TX and beacons
@@ -1360,7 +1431,7 @@ done:
 	 * since noise floor calibration interrupts rx path while I/Q
 	 * calibration doesn't. We don't need to run noise floor calibration
 	 * as often as I/Q calibration.*/
-	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+	ath5k_hw_update_noise_floor(ah);
 
 	/* Initiate a gain_F calibration */
 	ath5k_hw_request_rfgain_probe(ah);
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index debad07..7486da6 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -2039,17 +2039,14 @@
 #define	AR5K_PHY_AGCCTL_NF_NOUPDATE	0x00020000	/* Don't update nf automaticaly */
 
 /*
- * PHY noise floor status register
+ * PHY noise floor status register (CCA = Clear Channel Assessment)
  */
 #define AR5K_PHY_NF			0x9864			/* Register address */
-#define AR5K_PHY_NF_M			0x000001ff	/* Noise floor mask */
-#define AR5K_PHY_NF_ACTIVE		0x00000100	/* Noise floor calibration still active */
-#define AR5K_PHY_NF_RVAL(_n)		(((_n) >> 19) & AR5K_PHY_NF_M)
-#define AR5K_PHY_NF_AVAL(_n)		(-((_n) ^ AR5K_PHY_NF_M) + 1)
-#define AR5K_PHY_NF_SVAL(_n)		(((_n) & AR5K_PHY_NF_M) | (1 << 9))
+#define AR5K_PHY_NF_M			0x000001ff	/* Noise floor, written to hardware in 1/2 dBm units */
+#define AR5K_PHY_NF_SVAL(_n)           (((_n) & AR5K_PHY_NF_M) | (1 << 9))
 #define	AR5K_PHY_NF_THRESH62		0x0007f000	/* Thresh62 -check ANI patent- (field) */
 #define	AR5K_PHY_NF_THRESH62_S		12
-#define	AR5K_PHY_NF_MINCCA_PWR		0x0ff80000	/* ??? */
+#define	AR5K_PHY_NF_MINCCA_PWR		0x0ff80000	/* Minimum measured noise level, read from hardware in 1 dBm units */
 #define	AR5K_PHY_NF_MINCCA_PWR_S	19
 
 /*
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 34e13c7..aa05cf3 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -1289,7 +1289,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	 * out and/or noise floor calibration might timeout.
 	 */
 	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
-				AR5K_PHY_AGCCTL_CAL);
+				AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF);
 
 	/* At the same time start I/Q calibration for QAM constellation
 	 * -no need for CCK- */
@@ -1310,21 +1310,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 			channel->center_freq);
 	}
 
-	/*
-	 * If we run NF calibration before AGC, it always times out.
-	 * Binary HAL starts NF and AGC calibration at the same time
-	 * and only waits for AGC to finish. Also if AGC or NF cal.
-	 * times out, reset doesn't fail on binary HAL. I believe
-	 * that's wrong because since rx path is routed to a detector,
-	 * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
-	 * enables noise floor calibration after offset calibration and if noise
-	 * floor calibration fails, reset fails. I believe that's
-	 * a better approach, we just need to find a polling interval
-	 * that suits best, even if reset continues we need to make
-	 * sure that rx path is ready.
-	 */
-	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
-
 	/* Restore antenna mode */
 	ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
 
-- 
1.6.2.5



^ permalink raw reply related

* Re: Wifi Alliance announces peer-to-peer specification is in the works
From: Luis R. Rodriguez @ 2009-10-14 17:56 UTC (permalink / raw)
  To: austinxxh-linux; +Cc: linux-wireless
In-Reply-To: <122696.42074.qm@web55302.mail.re4.yahoo.com>

On Wed, Oct 14, 2009 at 10:14 AM, X Xiao <austinxxh-linux@yahoo.com> wrote:
> isn't this just encouraging vendors to provide universal ibss/adhoc support in the software?

No, its more like making AP mode of operation ubiquitous. Letting you
simultaneously start AP mode while keeping your other existing
connection alive and sometimes even on different channels. See ath9k
virtual wiphy implementation [1] as a simple example using legacy
modes of operation (no peer-to-peer stuff yet included). Obviously
there is a lot more to this though but since the specification is not
yet released more details cannot be provided yet.

[1] http://wireless.kernel.org/en/users/Drivers/ath9k/debug#wiphy

  Luis

^ permalink raw reply

* Re: Moving drivers into staging (was Re: [GIT PULL] SCSI fixes for 2.6.32-rc3)
From: Stefan Richter @ 2009-10-14 17:52 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Joe Perches, Greg KH, Luis R. Rodriguez, James Bottomley,
	Linus Torvalds, Theodore Tso, Andrew Morton, linux-scsi,
	linux-kernel, Jing Huang, netdev, linux-wireless
In-Reply-To: <20091014063308.GE784@elte.hu>

Ingo Molnar wrote:
> * Joe Perches <joe@perches.com> wrote:
> 
>> On Tue, 2009-10-13 at 21:45 -0700, Greg KH wrote:
>> > How about when it was scheduled to be removed, we put it in staging and
>> > I'll add it to my announcements about the staging tree every release?
>> > Unless you can think of a better way?
>> 
>> staging/to_be_removed_unless_fixed_by/v.x.y ?
> 
> Yes, that's a real worry. Some time ago i suggested:
> 
>   drivers/staging/good/
>   drivers/staging/bad/
>   drivers/staging/ugly/

How well do "git am", "quilt import" and friends cope with ever changing
directories?

How about using drivers/staging/this_driver/TODO and (or) its Kconfig
help text to leave a note about the plans for this driver?

The worry that these will be ignored like
Documentation/feature-removal-schedule.txt is being ignored may apply to
the path name based solution too, I'm afraid.

(Besides, Greg's release announcements are a good channel for this.
These announcements are actually picked up by the specialized press.)
-- 
Stefan Richter
-=====-==--= =-=- -===-
http://arcgraph.de/sr/

^ permalink raw reply

* Re: Current status of rt2800usb and staging/rt2870
From: Bartlomiej Zolnierkiewicz @ 2009-10-14 17:33 UTC (permalink / raw)
  To: John W. Linville
  Cc: Dan Williams, Ivo van Doorn, Ozan Çağlayan,
	linux-wireless, linux-kernel
In-Reply-To: <20091014164710.GF2890@tuxdriver.com>

On Wednesday 14 October 2009 18:47:11 John W. Linville wrote:
> On Wed, Oct 14, 2009 at 05:28:21PM +0200, Bartlomiej Zolnierkiewicz wrote:
> 
> > I don't have a have a problem with it personally as long as people accept
> > the competition..  but instead of working on _their_ projects they go around
> > screaming at everybody who does not want to spin inside the great process
> > designed by them..
> 
> Please whine somewhere else.  You have the freedom to work in
> drivers/staging all you want.  You do not have the power to force us to
> like it -- especially in a case where you are diverting attention from
> the community-maintained drivers instead of cooperating with them.

Cooperating you say.

rtl8187 -- before starting the work on rtl8187se I've pinged the maintainer
to coordinate the effort and hear his opinion on how to progress..

I've never heard back.

rt2x00 -- I know that people have datasheets for some chipsets but I've
never heard "How can we help you" etc. thing.

All I've ever heard was _lies_ about current state of affairs or that
my work is in the way.

> Your insults, jeers, and general bad attitude is unlikely to change
> our mind about it...

Well, when faced with real facts and technical arguments some people
go into "you are a social problem" mode...  nothing new here..

^ permalink raw reply

* Re: [2.6.32-rc3] iwlagn lost connection after s2ram (with warnings)
From: Carlos R. Mafra @ 2009-10-14 17:22 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: reinette chatre, linux-wireless@vger.kernel.org,
	linux-kernel@vger.kernel.org, johannes
In-Reply-To: <43e72e890910140944y23399b71sf20cd37e003c9729@mail.gmail.com>

On Wed 14.Oct'09 at  9:44:10 -0700, Luis R. Rodriguez wrote:

> > [15443.032706] ------------[ cut here ]------------
> > [15443.032723] WARNING: at net/wireless/sme.c:620 __cfg80211_disconnected+0x232/0x240()
> > [15443.032728] Hardware name: VGN-FZ240E
> > [15443.032732] deauth failed: -67
> 
> Can you reproduce ? 

Unfortunately I can not reproduce it reliably (I think today's warning
was ~4 days after the last one). If I could, I would have bisected it
already.

> If so then please try my patch titled:
> [PATCH] mac80211: fix SME warning by removing stale BSS upon assoc failure
> 
> and see if that still happens.

I will apply it, just in case. Thanks.

^ permalink raw reply

* Re: Wifi Alliance announces peer-to-peer specification is in the works
From: X Xiao @ 2009-10-14 17:14 UTC (permalink / raw)
  To: linux-wireless, Luis R. Rodriguez
In-Reply-To: <43e72e890910140749y43583f8av4c2885c3f22ac987@mail.gmail.com>

isn't this just encouraging vendors to provide universal ibss/adhoc support in the software?

-xxiao

--- On Wed, 10/14/09, Luis R. Rodriguez <mcgrof@gmail.com> wrote:

> From: Luis R. Rodriguez <mcgrof@gmail.com>
> Subject: Wifi Alliance announces peer-to-peer specification is in the works
> To: "linux-wireless" <linux-wireless@vger.kernel.org>
> Date: Wednesday, October 14, 2009, 9:49 AM
> Thought I'd share this:
> 
> http://www.wi-fiplanet.com/news/article.php/3843576
> 
>   Luis
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* Re: Current status of rt2800usb and staging/rt2870
From: John W. Linville @ 2009-10-14 16:47 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Dan Williams, Ivo van Doorn, Ozan Çağlayan,
	linux-wireless, linux-kernel
In-Reply-To: <200910141728.21491.bzolnier@gmail.com>

On Wed, Oct 14, 2009 at 05:28:21PM +0200, Bartlomiej Zolnierkiewicz wrote:

> I don't have a have a problem with it personally as long as people accept
> the competition..  but instead of working on _their_ projects they go around
> screaming at everybody who does not want to spin inside the great process
> designed by them..

Please whine somewhere else.  You have the freedom to work in
drivers/staging all you want.  You do not have the power to force us to
like it -- especially in a case where you are diverting attention from
the community-maintained drivers instead of cooperating with them.

Your insults, jeers, and general bad attitude is unlikely to change
our mind about it...

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: Current status of rt2800usb and staging/rt2870
From: Luis R. Rodriguez @ 2009-10-14 16:55 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: John W. Linville, Dan Williams, Ivo van Doorn,
	Ozan Çağlayan, linux-wireless, linux-kernel
In-Reply-To: <200910141728.21491.bzolnier@gmail.com>

On Wed, Oct 14, 2009 at 8:28 AM, Bartlomiej Zolnierkiewicz
<bzolnier@gmail.com> wrote:
> On Wednesday 14 October 2009 16:56:05 John W. Linville wrote:
>> On Wed, Oct 14, 2009 at 04:52:40PM +0200, Bartlomiej Zolnierkiewicz wrote:
>> > On Wednesday 14 October 2009 16:09:24 John W. Linville wrote:
>> > > On Tue, Oct 13, 2009 at 11:57:57PM +0200, Bartlomiej Zolnierkiewicz wrote:
>> > >
>> > > > Several months later (after all current users are happy with the improved
>> > > > drivers) the old drivers will be removed from staging..
>> > >
>> > > I _really_ hope this isn't the standard.  By that measure, nothing
>> > > will ever leave staging as _someone_ will always have some use case
>> > > that makes the other driver better for them.
>> >
>> > Doesn't seem to be the case with all other drivers except wireless ones
>> > and the only real reason why wireless ones are so special is because of:
>> >
>> > "But then there's the users, who bitch about everything and simply do
>> > not understand what it is at stake.
>> >
>> > And all this is becoming way too messy for us to handle.
>> >
>> > Personally all I see around me is people bitching and complaining, and
>> > no code being ported."
>> >
>> > attitude which pretty much explains the problem..
>> >
>> > Please adjust the process to fix the problem yourself or if you do not
>> > want to do it just make the room for people who do.
>>
>> Alright Bartlomiej, you've had your say.  Perhaps you should go about
>> your business now.
>>
>> John
>>
>> P.S. For the record, the "But then there's the users..." quote is
>> from someone else...
>
> ..but you're still fine with its content, right?
>
> I also wonder who is really taking advantage of who here (your other mail)..
>
> You're holding users as hostages to pressure vendors to fund your projects
> and try to lure outside developers with the lovely perspective of doing
> the hardest parts of said projects.
>
> I don't have a have a problem with it personally as long as people accept
> the competition..  but instead of working on _their_ projects they go around
> screaming at everybody who does not want to spin inside the great process
> designed by them..

I hear fishing in Poland is great this time of year.

  Luis

^ permalink raw reply

* Re: Stable compat-wireless 2.6.32-rc4 released
From: Luis R. Rodriguez @ 2009-10-14 16:51 UTC (permalink / raw)
  To: tim.gardner; +Cc: Kunal Gangakhedkar, linux-wireless
In-Reply-To: <4AD5EDA4.6090303@canonical.com>

On Wed, Oct 14, 2009 at 8:26 AM, Tim Gardner <tim.gardner@canonical.com> wrote:
> Luis R. Rodriguez wrote:
>> On Tue, Oct 13, 2009 at 11:01 PM, Kunal Gangakhedkar
>> <kunal.gangakhedkar@gmail.com> wrote:
>>> Isn't this the whole purpose of linux-backports-modules in ubuntu as well?
>>
>> Yes, but lbm currently relies on the bleeding edge compat-wireless
>> which is exactly that -- bleeding edge, it may or may not work. The
>> stable compat-wireless releases are based on the latest stable kernel
>> releases and latest rc kernel release so they are deemed to be stable
>> snapshots following the kernel release cycle.
>>
>>   Luis
>>
>
> I am currently in the process of adopting compat-wireless-2.6.32-rc4 in
> Karmic LBM.

Oh nice.

> Luis - Have I remembered to thank you for all your hard work?

I think so :) Fortunately Hauke Mehrtens and others are also
contributing to maintaining it as well. But I'll accept single malt
whiskey next time we see each other though :)

  Luis

^ permalink raw reply

* Re: [2.6.32-rc3] iwlagn lost connection after s2ram (with warnings)
From: Luis R. Rodriguez @ 2009-10-14 16:44 UTC (permalink / raw)
  To: Carlos R. Mafra
  Cc: reinette chatre, linux-wireless@vger.kernel.org,
	linux-kernel@vger.kernel.org, johannes
In-Reply-To: <20091014151529.GA6602@Pilar.aei.mpg.de>

On Wed, Oct 14, 2009 at 8:15 AM, Carlos R. Mafra <crmafra2@gmail.com> wrote:
> On Thu  8.Oct'09 at 10:44:43 -0700, reinette chatre wrote:
>> Hi Carlos,
>>
>> On Wed, 2009-10-07 at 07:20 -0700, Carlos R. Mafra wrote:
>> > I just got these warnings after resuming from a suspend to RAM, and
>> > the wireless connection was not resumed (now I am connected via eth0).
>> > This is the first time I had a failed wireless resume since 2.6.32-rc1.
>> >
>> > The full dmesg is here: http://www.aei.mpg.de/~crmafra/dmesg-2.6.32-rc3-wifi.txt
>> >
>> > [ 3427.570113] Restarting tasks ...
>> > [ 3427.585827] wlan0: deauthenticated from 00:0b:86:26:36:f1 (Reason: 6)
>> > [ 3427.589451] done.
>> > [ 3428.503203] input: PS/2 Mouse as /devices/platform/i8042/serio4/input/input15
>> > [ 3428.521064] input: AlpsPS/2 ALPS GlidePoint as /devices/platform/i8042/serio4/input/input16
>> > [ 3434.504175] wlan0: direct probe to AP 00:0b:86:26:36:f1 (try 1)
>> > [ 3434.507058] wlan0: direct probe responded
>> > [ 3434.507062] wlan0: authenticate with AP 00:0b:86:26:36:f1 (try 1)
>> > [ 3434.509000] wlan0: authenticated
>> > [ 3434.509022] wlan0: associate with AP 00:0b:86:26:36:f1 (try 1)
>> > [ 3434.512778] wlan0: RX ReassocResp from 00:0b:86:26:36:f1 (capab=0x431 status=0 aid=2)
>> > [ 3434.512782] wlan0: associated
>> > [ 3434.563942] wlan0: deauthenticating from 00:0b:86:26:36:f1 by local choice (reason=3)
>>
>> You mention you are trying to connect again after a resume. The message
>> above indicates that userspace (maybe wpa_supplicant ?) requested that
>> the connection be closed. Do you maybe know how this could have been
>> triggered?
>>
>> > [ 3434.564023] ------------[ cut here ]------------
>> > [ 3434.564039] WARNING: at net/wireless/mlme.c:96 cfg80211_send_rx_assoc+0x193/0x230()
>>
>> This warning and the one below indicates that there is no information
>> available for this BSS. Maybe Johannes knows why this can be?
>>
>> > [ 3434.564045] Hardware name: VGN-FZ240E
>> > [ 3434.564049] Modules linked in: usbhid nvram dvb_usb_dib0700 dib7000p dib7000m dib0070 dvb_usb dib3000mc dib8000 dibx000_common snd_hda_codec_idt uvcvideo snd_hda_intel snd_hda_codec ehci_hcd sg uhci_hcd snd_hwdep sky2 iwlagn i2c_i801 sr_mod evdev ata_piix ahci libata sd_mod scsi_mod
>> > [ 3434.564104] Pid: 2319, comm: phy0 Not tainted 2.6.32-rc3 #204
>> > [ 3434.564109] Call Trace:
>> > [ 3434.564119]  [<ffffffff81420dd3>] ? cfg80211_send_rx_assoc+0x193/0x230
>> > [ 3434.564131]  [<ffffffff81047cb8>] warn_slowpath_common+0x78/0xd0
>> > [ 3434.564139]  [<ffffffff81047d1f>] warn_slowpath_null+0xf/0x20
>> > [ 3434.564147]  [<ffffffff81420dd3>] cfg80211_send_rx_assoc+0x193/0x230
>> > [ 3434.564156]  [<ffffffff814316cb>] ieee80211_sta_work+0x2fb/0x1100
>> > [ 3434.564166]  [<ffffffff81453b1f>] ? _spin_unlock_bh+0xf/0x20
>> > [ 3434.564175]  [<ffffffff8142802a>] ? ieee80211_configure_filter+0x11a/0x170
>> > [ 3434.564183]  [<ffffffff814313d0>] ? ieee80211_sta_work+0x0/0x1100
>> > [ 3434.564193]  [<ffffffff8105e9e2>] worker_thread+0x182/0x260
>> > [ 3434.564203]  [<ffffffff81063320>] ? autoremove_wake_function+0x0/0x40
>> > [ 3434.564211]  [<ffffffff8105e860>] ? worker_thread+0x0/0x260
>> > [ 3434.564219]  [<ffffffff81062f06>] kthread+0x96/0xb0
>> > [ 3434.564229]  [<ffffffff8100cd1a>] child_rip+0xa/0x20
>> > [ 3434.564237]  [<ffffffff81062e70>] ? kthread+0x0/0xb0
>> > [ 3434.564245]  [<ffffffff8100cd10>] ? child_rip+0x0/0x20
>> > [ 3434.564250] ---[ end trace 99d6122abfa316f7 ]---
>> > [ 3434.564272] ------------[ cut here ]------------
>> > [ 3434.564280] WARNING: at net/wireless/sme.c:417 __cfg80211_connect_result+0x343/0x380()
>> > [ 3434.564285] Hardware name: VGN-FZ240E
>> > [ 3434.564289] Modules linked in: usbhid nvram dvb_usb_dib0700 dib7000p dib7000m dib0070 dvb_usb dib3000mc dib8000 dibx000_common snd_hda_codec_idt uvcvideo snd_hda_intel snd_hda_codec ehci_hcd sg uhci_hcd snd_hwdep sky2 iwlagn i2c_i801 sr_mod evdev ata_piix ahci libata sd_mod scsi_mod
>> > [ 3434.564335] Pid: 2319, comm: phy0 Tainted: G        W  2.6.32-rc3 #204
>> > [ 3434.564340] Call Trace:
>> > [ 3434.564347]  [<ffffffff81453b1f>] ? _spin_unlock_bh+0xf/0x20
>> > [ 3434.564355]  [<ffffffff814236e3>] ? __cfg80211_connect_result+0x343/0x380
>> > [ 3434.564364]  [<ffffffff81047cb8>] warn_slowpath_common+0x78/0xd0
>> > [ 3434.564373]  [<ffffffff81047d1f>] warn_slowpath_null+0xf/0x20
>> > [ 3434.564381]  [<ffffffff814236e3>] __cfg80211_connect_result+0x343/0x380
>> > [ 3434.564389]  [<ffffffff814509a2>] ? dump_stack+0x72/0x7b
>> > [ 3434.564397]  [<ffffffff81420e10>] cfg80211_send_rx_assoc+0x1d0/0x230
>> > [ 3434.564405]  [<ffffffff814316cb>] ieee80211_sta_work+0x2fb/0x1100
>> > [ 3434.564413]  [<ffffffff81453b1f>] ? _spin_unlock_bh+0xf/0x20
>> > [ 3434.564421]  [<ffffffff8142802a>] ? ieee80211_configure_filter+0x11a/0x170
>> > [ 3434.564429]  [<ffffffff814313d0>] ? ieee80211_sta_work+0x0/0x1100
>> > [ 3434.564438]  [<ffffffff8105e9e2>] worker_thread+0x182/0x260
>> > [ 3434.564447]  [<ffffffff81063320>] ? autoremove_wake_function+0x0/0x40
>> > [ 3434.564455]  [<ffffffff8105e860>] ? worker_thread+0x0/0x260
>> > [ 3434.564463]  [<ffffffff81062f06>] kthread+0x96/0xb0
>> > [ 3434.564471]  [<ffffffff8100cd1a>] child_rip+0xa/0x20
>> > [ 3434.564479]  [<ffffffff81062e70>] ? kthread+0x0/0xb0
>> > [ 3434.564487]  [<ffffffff8100cd10>] ? child_rip+0x0/0x20
>> > [ 3434.564492] ---[ end trace 99d6122abfa316f8 ]---
>> > [ 3434.962611] Registered led device: iwl-phy0::radio
>> > [ 3434.962629] Registered led device: iwl-phy0::assoc
>> > [ 3434.962645] Registered led device: iwl-phy0::RX
>> > [ 3434.962661] Registered led device: iwl-phy0::TX
>> > [ 3435.000526] ADDRCONF(NETDEV_UP): wlan0: link is not ready
>
> Now I got a similar warning and the connection went down. But this
> time it was not closely related to a suspend to RAM, as can be noticed
> in the dmesg
>
> [  624.603365] wlan0: direct probe responded
> [  624.603373] wlan0: authenticate with AP 00:0b:86:26:36:f1 (try 1)
> [  624.605285] wlan0: authenticated
> [  624.605316] wlan0: associate with AP 00:0b:86:26:36:f1 (try 1)
> [  624.608055] wlan0: RX ReassocResp from 00:0b:86:26:36:f1 (capab=0x21 status=10 aid=0)
> [  624.608061] wlan0: AP denied association (code=10)
> [  640.704549] wlan0: direct probe to AP 00:0b:86:3e:10:31 (try 1)
> [  640.708848] wlan0: direct probe responded
> [  640.708857] wlan0: authenticate with AP 00:0b:86:3e:10:31 (try 1)
> [  640.710857] wlan0: authenticated
> [  640.710888] wlan0: associate with AP 00:0b:86:3e:10:31 (try 1)
> [  640.719800] wlan0: RX AssocResp from 00:0b:86:3e:10:31 (capab=0x431 status=0 aid=1)
> [  640.719807] wlan0: associated
> [  640.746298] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> [  650.899995] wlan0: no IPv6 routers present
> [  706.797508] CE: hpet increasing min_delta_ns to 15000 nsec
> [ 9523.640903] process `skype' is using obsolete setsockopt SO_BSDCOMPAT
> [ 9546.622398] hda-intel: azx_get_response timeout, switching to polling mode: last cmd=0x00af0900
> [15443.026527] wlan0: deauthenticated from 00:0b:86:3e:10:31 (Reason: 3)
> [15443.032706] ------------[ cut here ]------------
> [15443.032723] WARNING: at net/wireless/sme.c:620 __cfg80211_disconnected+0x232/0x240()
> [15443.032728] Hardware name: VGN-FZ240E
> [15443.032732] deauth failed: -67

Can you reproduce ? If so then please try my patch titled:

[PATCH] mac80211: fix SME warning by removing stale BSS upon assoc failure

and see if that still happens.

  Luis

^ permalink raw reply

* Re: iwl3945: page allocation failure. order:5, mode:0x8020
From: reinette chatre @ 2009-10-14 16:36 UTC (permalink / raw)
  To: John W. Linville; +Cc: Kalle Valo, linux-wireless@vger.kernel.org
In-Reply-To: <20091014143347.GD2890@tuxdriver.com>

On Wed, 2009-10-14 at 07:33 -0700, John W. Linville wrote:
> On Wed, Oct 14, 2009 at 04:14:32PM +0300, Kalle Valo wrote:
> 
> > I didn't reboot during update, I only did 'modprobe -r iwl3945;
> > modprobe iwl3945', so there's a small chance that something went wrong
> > during update. But I still suspect something else is wrong because I
> > have never seen this error before. 
> 
> This sounds a lot like the ongoing iwlagn allocation thread...
> 

Could also be a duplicate of http://lkml.org/lkml/2009/9/15/163, which
is a order-5 allocation failure during reload of e100.

Even so, yes, that email thread John refers to considers this case as
well as the iwlagn ones that have been popping up. I added this report
to that thread and added Kalle to the cc list.

See http://thread.gmane.org/gmane.linux.drivers.ipw3945.devel/5313 and
also kernel bug 14141.

Reinette



^ permalink raw reply

* Re: Current status of rt2800usb and staging/rt2870
From: Bartlomiej Zolnierkiewicz @ 2009-10-14 15:28 UTC (permalink / raw)
  To: John W. Linville
  Cc: Dan Williams, Ivo van Doorn, Ozan Çağlayan,
	linux-wireless, linux-kernel
In-Reply-To: <20091014145605.GE2890@tuxdriver.com>

On Wednesday 14 October 2009 16:56:05 John W. Linville wrote:
> On Wed, Oct 14, 2009 at 04:52:40PM +0200, Bartlomiej Zolnierkiewicz wrote:
> > On Wednesday 14 October 2009 16:09:24 John W. Linville wrote:
> > > On Tue, Oct 13, 2009 at 11:57:57PM +0200, Bartlomiej Zolnierkiewicz wrote:
> > > 
> > > > Several months later (after all current users are happy with the improved
> > > > drivers) the old drivers will be removed from staging..
> > > 
> > > I _really_ hope this isn't the standard.  By that measure, nothing
> > > will ever leave staging as _someone_ will always have some use case
> > > that makes the other driver better for them.
> > 
> > Doesn't seem to be the case with all other drivers except wireless ones
> > and the only real reason why wireless ones are so special is because of:
> > 
> > "But then there's the users, who bitch about everything and simply do
> > not understand what it is at stake.
> > 
> > And all this is becoming way too messy for us to handle.
> > 
> > Personally all I see around me is people bitching and complaining, and
> > no code being ported."
> > 
> > attitude which pretty much explains the problem..
> > 
> > Please adjust the process to fix the problem yourself or if you do not
> > want to do it just make the room for people who do.
> 
> Alright Bartlomiej, you've had your say.  Perhaps you should go about
> your business now.
> 
> John
> 
> P.S. For the record, the "But then there's the users..." quote is
> from someone else...

..but you're still fine with its content, right?

I also wonder who is really taking advantage of who here (your other mail)..

You're holding users as hostages to pressure vendors to fund your projects
and try to lure outside developers with the lovely perspective of doing
the hardest parts of said projects.

I don't have a have a problem with it personally as long as people accept
the competition..  but instead of working on _their_ projects they go around
screaming at everybody who does not want to spin inside the great process
designed by them..

^ permalink raw reply

* Re: Stable compat-wireless 2.6.32-rc4 released
From: Tim Gardner @ 2009-10-14 15:26 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: Kunal Gangakhedkar, linux-wireless
In-Reply-To: <43e72e890910140734j196a06f2y8905d3eb1ba1abc8@mail.gmail.com>

Luis R. Rodriguez wrote:
> On Tue, Oct 13, 2009 at 11:01 PM, Kunal Gangakhedkar
> <kunal.gangakhedkar@gmail.com> wrote:
>> On Wednesday 14 Oct 2009 6:20:33 am Luis R. Rodriguez wrote:
>>> On Tue, Oct 13, 2009 at 5:25 PM, Tim Gardner <tim.gardner@canonical.com>
>> wrote:
>>>> Speaking as a distro, what advantage does the stable wireless backport
>>>> offer for the currently released kernel if we are already consumers of
>>>> stable updates?
>>> Well if you are a distro stuck on the 2.6.31 kernel the stable
>>> compat-wireless-2.6.32 gets you 2.6.32 wireless bits on 2.6.31 and
>>> that means any features/drivers/large fixes/enhancements that didn't
>>> make it to 2.6.31.
>>>
>> Isn't this the whole purpose of linux-backports-modules in ubuntu as well?
> 
> Yes, but lbm currently relies on the bleeding edge compat-wireless
> which is exactly that -- bleeding edge, it may or may not work. The
> stable compat-wireless releases are based on the latest stable kernel
> releases and latest rc kernel release so they are deemed to be stable
> snapshots following the kernel release cycle.
> 
>   Luis
> 

I am currently in the process of adopting compat-wireless-2.6.32-rc4 in
Karmic LBM.

Luis - Have I remembered to thank you for all your hard work?

rtg
-- 
Tim Gardner tim.gardner@canonical.com

^ permalink raw reply

* Re: [2.6.32-rc3] iwlagn lost connection after s2ram (with warnings)
From: Carlos R. Mafra @ 2009-10-14 15:15 UTC (permalink / raw)
  To: reinette chatre
  Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
	johannes
In-Reply-To: <1255023883.26521.13298.camel@rc-desk>

On Thu  8.Oct'09 at 10:44:43 -0700, reinette chatre wrote:
> Hi Carlos,
> 
> On Wed, 2009-10-07 at 07:20 -0700, Carlos R. Mafra wrote:
> > I just got these warnings after resuming from a suspend to RAM, and
> > the wireless connection was not resumed (now I am connected via eth0).
> > This is the first time I had a failed wireless resume since 2.6.32-rc1.
> > 
> > The full dmesg is here: http://www.aei.mpg.de/~crmafra/dmesg-2.6.32-rc3-wifi.txt
> > 
> > [ 3427.570113] Restarting tasks ... 
> > [ 3427.585827] wlan0: deauthenticated from 00:0b:86:26:36:f1 (Reason: 6)
> > [ 3427.589451] done.
> > [ 3428.503203] input: PS/2 Mouse as /devices/platform/i8042/serio4/input/input15
> > [ 3428.521064] input: AlpsPS/2 ALPS GlidePoint as /devices/platform/i8042/serio4/input/input16
> > [ 3434.504175] wlan0: direct probe to AP 00:0b:86:26:36:f1 (try 1)
> > [ 3434.507058] wlan0: direct probe responded
> > [ 3434.507062] wlan0: authenticate with AP 00:0b:86:26:36:f1 (try 1)
> > [ 3434.509000] wlan0: authenticated
> > [ 3434.509022] wlan0: associate with AP 00:0b:86:26:36:f1 (try 1)
> > [ 3434.512778] wlan0: RX ReassocResp from 00:0b:86:26:36:f1 (capab=0x431 status=0 aid=2)
> > [ 3434.512782] wlan0: associated
> > [ 3434.563942] wlan0: deauthenticating from 00:0b:86:26:36:f1 by local choice (reason=3)
> 
> You mention you are trying to connect again after a resume. The message
> above indicates that userspace (maybe wpa_supplicant ?) requested that
> the connection be closed. Do you maybe know how this could have been
> triggered?
> 
> > [ 3434.564023] ------------[ cut here ]------------
> > [ 3434.564039] WARNING: at net/wireless/mlme.c:96 cfg80211_send_rx_assoc+0x193/0x230()
> 
> This warning and the one below indicates that there is no information
> available for this BSS. Maybe Johannes knows why this can be?
> 
> > [ 3434.564045] Hardware name: VGN-FZ240E
> > [ 3434.564049] Modules linked in: usbhid nvram dvb_usb_dib0700 dib7000p dib7000m dib0070 dvb_usb dib3000mc dib8000 dibx000_common snd_hda_codec_idt uvcvideo snd_hda_intel snd_hda_codec ehci_hcd sg uhci_hcd snd_hwdep sky2 iwlagn i2c_i801 sr_mod evdev ata_piix ahci libata sd_mod scsi_mod
> > [ 3434.564104] Pid: 2319, comm: phy0 Not tainted 2.6.32-rc3 #204
> > [ 3434.564109] Call Trace:
> > [ 3434.564119]  [<ffffffff81420dd3>] ? cfg80211_send_rx_assoc+0x193/0x230
> > [ 3434.564131]  [<ffffffff81047cb8>] warn_slowpath_common+0x78/0xd0
> > [ 3434.564139]  [<ffffffff81047d1f>] warn_slowpath_null+0xf/0x20
> > [ 3434.564147]  [<ffffffff81420dd3>] cfg80211_send_rx_assoc+0x193/0x230
> > [ 3434.564156]  [<ffffffff814316cb>] ieee80211_sta_work+0x2fb/0x1100
> > [ 3434.564166]  [<ffffffff81453b1f>] ? _spin_unlock_bh+0xf/0x20
> > [ 3434.564175]  [<ffffffff8142802a>] ? ieee80211_configure_filter+0x11a/0x170
> > [ 3434.564183]  [<ffffffff814313d0>] ? ieee80211_sta_work+0x0/0x1100
> > [ 3434.564193]  [<ffffffff8105e9e2>] worker_thread+0x182/0x260
> > [ 3434.564203]  [<ffffffff81063320>] ? autoremove_wake_function+0x0/0x40
> > [ 3434.564211]  [<ffffffff8105e860>] ? worker_thread+0x0/0x260
> > [ 3434.564219]  [<ffffffff81062f06>] kthread+0x96/0xb0
> > [ 3434.564229]  [<ffffffff8100cd1a>] child_rip+0xa/0x20
> > [ 3434.564237]  [<ffffffff81062e70>] ? kthread+0x0/0xb0
> > [ 3434.564245]  [<ffffffff8100cd10>] ? child_rip+0x0/0x20
> > [ 3434.564250] ---[ end trace 99d6122abfa316f7 ]---
> > [ 3434.564272] ------------[ cut here ]------------
> > [ 3434.564280] WARNING: at net/wireless/sme.c:417 __cfg80211_connect_result+0x343/0x380()
> > [ 3434.564285] Hardware name: VGN-FZ240E
> > [ 3434.564289] Modules linked in: usbhid nvram dvb_usb_dib0700 dib7000p dib7000m dib0070 dvb_usb dib3000mc dib8000 dibx000_common snd_hda_codec_idt uvcvideo snd_hda_intel snd_hda_codec ehci_hcd sg uhci_hcd snd_hwdep sky2 iwlagn i2c_i801 sr_mod evdev ata_piix ahci libata sd_mod scsi_mod
> > [ 3434.564335] Pid: 2319, comm: phy0 Tainted: G        W  2.6.32-rc3 #204
> > [ 3434.564340] Call Trace:
> > [ 3434.564347]  [<ffffffff81453b1f>] ? _spin_unlock_bh+0xf/0x20
> > [ 3434.564355]  [<ffffffff814236e3>] ? __cfg80211_connect_result+0x343/0x380
> > [ 3434.564364]  [<ffffffff81047cb8>] warn_slowpath_common+0x78/0xd0
> > [ 3434.564373]  [<ffffffff81047d1f>] warn_slowpath_null+0xf/0x20
> > [ 3434.564381]  [<ffffffff814236e3>] __cfg80211_connect_result+0x343/0x380
> > [ 3434.564389]  [<ffffffff814509a2>] ? dump_stack+0x72/0x7b
> > [ 3434.564397]  [<ffffffff81420e10>] cfg80211_send_rx_assoc+0x1d0/0x230
> > [ 3434.564405]  [<ffffffff814316cb>] ieee80211_sta_work+0x2fb/0x1100
> > [ 3434.564413]  [<ffffffff81453b1f>] ? _spin_unlock_bh+0xf/0x20
> > [ 3434.564421]  [<ffffffff8142802a>] ? ieee80211_configure_filter+0x11a/0x170
> > [ 3434.564429]  [<ffffffff814313d0>] ? ieee80211_sta_work+0x0/0x1100
> > [ 3434.564438]  [<ffffffff8105e9e2>] worker_thread+0x182/0x260
> > [ 3434.564447]  [<ffffffff81063320>] ? autoremove_wake_function+0x0/0x40
> > [ 3434.564455]  [<ffffffff8105e860>] ? worker_thread+0x0/0x260
> > [ 3434.564463]  [<ffffffff81062f06>] kthread+0x96/0xb0
> > [ 3434.564471]  [<ffffffff8100cd1a>] child_rip+0xa/0x20
> > [ 3434.564479]  [<ffffffff81062e70>] ? kthread+0x0/0xb0
> > [ 3434.564487]  [<ffffffff8100cd10>] ? child_rip+0x0/0x20
> > [ 3434.564492] ---[ end trace 99d6122abfa316f8 ]---
> > [ 3434.962611] Registered led device: iwl-phy0::radio
> > [ 3434.962629] Registered led device: iwl-phy0::assoc
> > [ 3434.962645] Registered led device: iwl-phy0::RX
> > [ 3434.962661] Registered led device: iwl-phy0::TX
> > [ 3435.000526] ADDRCONF(NETDEV_UP): wlan0: link is not ready

Now I got a similar warning and the connection went down. But this
time it was not closely related to a suspend to RAM, as can be noticed
in the dmesg

[  624.603365] wlan0: direct probe responded
[  624.603373] wlan0: authenticate with AP 00:0b:86:26:36:f1 (try 1)
[  624.605285] wlan0: authenticated
[  624.605316] wlan0: associate with AP 00:0b:86:26:36:f1 (try 1)
[  624.608055] wlan0: RX ReassocResp from 00:0b:86:26:36:f1 (capab=0x21 status=10 aid=0)
[  624.608061] wlan0: AP denied association (code=10)
[  640.704549] wlan0: direct probe to AP 00:0b:86:3e:10:31 (try 1)
[  640.708848] wlan0: direct probe responded
[  640.708857] wlan0: authenticate with AP 00:0b:86:3e:10:31 (try 1)
[  640.710857] wlan0: authenticated
[  640.710888] wlan0: associate with AP 00:0b:86:3e:10:31 (try 1)
[  640.719800] wlan0: RX AssocResp from 00:0b:86:3e:10:31 (capab=0x431 status=0 aid=1)
[  640.719807] wlan0: associated
[  640.746298] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
[  650.899995] wlan0: no IPv6 routers present
[  706.797508] CE: hpet increasing min_delta_ns to 15000 nsec
[ 9523.640903] process `skype' is using obsolete setsockopt SO_BSDCOMPAT
[ 9546.622398] hda-intel: azx_get_response timeout, switching to polling mode: last cmd=0x00af0900
[15443.026527] wlan0: deauthenticated from 00:0b:86:3e:10:31 (Reason: 3)
[15443.032706] ------------[ cut here ]------------
[15443.032723] WARNING: at net/wireless/sme.c:620 __cfg80211_disconnected+0x232/0x240()
[15443.032728] Hardware name: VGN-FZ240E
[15443.032732] deauth failed: -67
[15443.032736] Modules linked in: usbhid nvram snd_hda_codec_idt uvcvideo snd_hda_intel snd_hda_codec evdev i2c_i801 sn                                                            d_hwdep uhci_hcd ehci_hcd sr_mod sky2 iwlagn sg ata_piix ahci libata sd_mod scsi_mod
[15443.032779] Pid: 2260, comm: phy0 Not tainted 2.6.32-rc4-dmitry2-00002-g5ce9513 #229
[15443.032784] Call Trace:
[15443.032794]  [<ffffffff81421902>] ? __cfg80211_disconnected+0x232/0x240
[15443.032805]  [<ffffffff81047cd8>] warn_slowpath_common+0x78/0xd0
[15443.032814]  [<ffffffff81047db4>] warn_slowpath_fmt+0x64/0x70
[15443.032823]  [<ffffffff81433e99>] ? ieee80211_deauth+0x19/0x20
[15443.032833]  [<ffffffff8141e3ad>] ? __cfg80211_mlme_deauth+0xed/0x140
[15443.032842]  [<ffffffff81421902>] __cfg80211_disconnected+0x232/0x240
[15443.032851]  [<ffffffff8141f35a>] __cfg80211_send_deauth+0x23a/0x270
[15443.032861]  [<ffffffff8142d064>] ? ieee80211_set_disassoc+0x1b4/0x230
[15443.032870]  [<ffffffff8141f3fa>] cfg80211_send_deauth+0x6a/0x80
[15443.032879]  [<ffffffff8142fe82>] ieee80211_sta_work+0x2e2/0x1100
[15443.032888]  [<ffffffff8142e175>] ? ieee80211_mgd_probe_ap_send+0x65/0x70
[15443.032897]  [<ffffffff8142fba0>] ? ieee80211_sta_work+0x0/0x1100
[15443.032907]  [<ffffffff8105e9e2>] worker_thread+0x182/0x260
[15443.032916]  [<ffffffff810630d0>] ? autoremove_wake_function+0x0/0x40
[15443.032925]  [<ffffffff8105e860>] ? worker_thread+0x0/0x260
[15443.032933]  [<ffffffff81062cb6>] kthread+0x96/0xb0
[15443.032944]  [<ffffffff8100cd1a>] child_rip+0xa/0x20
[15443.032952]  [<ffffffff81062c20>] ? kthread+0x0/0xb0
[15443.032960]  [<ffffffff8100cd10>] ? child_rip+0x0/0x20
[15443.032965] ---[ end trace 0c4814007354915e ]---
[15444.898782] wlan0: direct probe to AP 00:0b:86:3e:10:31 (try 1)
[15445.098540] wlan0: direct probe to AP 00:0b:86:3e:10:31 (try 2)
[15445.299332] wlan0: direct probe to AP 00:0b:86:3e:10:31 (try 3)
[15445.498601] wlan0: direct probe to AP 00:0b:86:3e:10:31 timed out
[15449.715917] Registered led device: iwl-phy0::radio
[15449.716554] Registered led device: iwl-phy0::assoc
[15449.717107] Registered led device: iwl-phy0::RX
[15449.717603] Registered led device: iwl-phy0::TX
[15449.749228] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[15449.794402] wlan0: direct probe to AP 00:0b:86:28:21:11 (try 1)
[15449.992691] wlan0: direct probe to AP 00:0b:86:28:21:11 (try 2)
[15450.191950] wlan0: direct probe to AP 00:0b:86:28:21:11 (try 3)
[15450.392681] wlan0: direct probe to AP 00:0b:86:28:21:11 timed out


But after ~7 minutes the connection was recovered (but in the mean time
I had already started eth0), see here the continuation:


[15824.443480] sky2 eth0: enabling interface
[15824.443735] ADDRCONF(NETDEV_UP): eth0: link is not ready
[15826.108242] sky2 eth0: Link is up at 100 Mbps, full duplex, flow control rx
[15826.108864] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[15836.731786] eth0: no IPv6 routers present
[15924.423010] wlan0: direct probe to AP 00:0b:86:26:36:f1 (try 1)
[15924.426094] wlan0: direct probe responded
[15924.426113] wlan0: authenticate with AP 00:0b:86:26:36:f1 (try 1)
[15924.427981] wlan0: authenticated
[15924.428017] wlan0: associate with AP 00:0b:86:26:36:f1 (try 1)
[15924.434504] wlan0: RX ReassocResp from 00:0b:86:26:36:f1 (capab=0x431 status=0 aid=1)
[15924.434511] wlan0: associated
[15924.458575] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
[15934.491760] wlan0: no IPv6 routers present

^ permalink raw reply

* Re: [WIP, RFC] libertas: allow scanning via "iw"
From: Holger Schurig @ 2009-10-14 15:13 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <200910141652.11203.hs4233@mail.mn-solutions.de>

Oops, didn't change the subject. Of course it can now do more 
than just scanning ...

^ 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