* Re: [PATCH] b43: Fix locking problem when stopping rfkill polling
From: John W. Linville @ 2009-10-08 22:31 UTC (permalink / raw)
To: Larry Finger; +Cc: linux-wireless, Greg Kroah-Hartman
In-Reply-To: <4ACE4A48.9070901@lwfinger.net>
On Thu, Oct 08, 2009 at 03:23:36PM -0500, Larry Finger wrote:
> On 10/07/2009 02:01 PM, John W. Linville wrote:
>> OK, but why do we start polling under the lock but stop polling without
>> the lock? Should we start polling without holding the lock too?
>
> I see that this patch was committed. I hope that you will be sending it
> upstream for 2.6.32. The correct version has been sent to stable for
> inclusion in 2.6.31, but as usual, a mainline commit ID will be needed.
I've folded this into "b43: Fix PPC crash in rfkill polling on unload"
for sending upstream.
Thanks!
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: pull request: wireless-2.6 2009-10-08
From: Michael Buesch @ 2009-10-08 23:08 UTC (permalink / raw)
To: John W. Linville; +Cc: davem, linux-wireless, netdev, linux-kernel
In-Reply-To: <20091008223454.GB2798@tuxdriver.com>
On Friday 09 October 2009 00:34:54 John W. Linville wrote:
> Albert Herranz (1):
> b43: do not stack-allocate pio rx/tx header and tail buffers
Come on, this is _not_ funny anymore. I did _not_ ack this patch, because I do _not_ like it.
I was planning to do a better solution, but I didn't have the time, yet.
Can you _please_ either:
- Wait for my ack before you apply random b43 patches
or
- Remove me from MAINTAINERS
--
Greetings, Michael.
^ permalink raw reply
* Re: pull request: wireless-2.6 2009-10-08
From: Michael Buesch @ 2009-10-08 23:16 UTC (permalink / raw)
To: John W. Linville; +Cc: davem, linux-wireless, netdev, linux-kernel
In-Reply-To: <200910090108.08838.mb@bu3sch.de>
On Friday 09 October 2009 01:08:06 Michael Buesch wrote:
> On Friday 09 October 2009 00:34:54 John W. Linville wrote:
> > Albert Herranz (1):
> > b43: do not stack-allocate pio rx/tx header and tail buffers
>
> Come on, this is _not_ funny anymore. I did _not_ ack this patch, because I do _not_ like it.
> I was planning to do a better solution, but I didn't have the time, yet.
> Can you _please_ either:
> - Wait for my ack before you apply random b43 patches
> or
> - Remove me from MAINTAINERS
>
And there's no reason to rush this fix into mainline. We currently do not even
have a supported device which would require this fix. The Wii, which uses the SDIO bus,
does not require this fix. So the only supported device (as of now) does not need the fix
to work properly.
So it can as well go into the next merge window.
--
Greetings, Michael.
^ permalink raw reply
* Re: NULL pointer deref at wext ioctl (Re: [PATCH] compat-2.6: adding ethtool.h to compat-2.6.31.h)
From: Hin-Tak Leung @ 2009-10-08 23:22 UTC (permalink / raw)
To: Luis R. Rodriguez; +Cc: Johannes Berg, John W. Linville, linux-wireless
In-Reply-To: <43e72e890910080643h282c4bf1xf972f15f13eae755@mail.gmail.com>
On Thu, Oct 8, 2009 at 2:43 PM, Luis R. Rodriguez
<lrodriguez@atheros.com> wrote:
> On Thu, Oct 8, 2009 at 7:50 AM, Johannes Berg <johannes@sipsolutions.net> wrote:
>> On Thu, 2009-10-08 at 11:51 +0200, Johannes Berg wrote:
>>
>>> Ok, that's odd. Is it possible that somehow cfg80211 is picking up an
>>> #ifdef'ed copy of "struct iw_handler_def", and thus the struct it is
>>> defining is simply too small?
>>
>> That is apparently what is happening since compat-wireless ships
>> iw_handler.h. This is wrong, as wext functionality is built into the
>> kernel image so you can't use a newer header file with it.
>
> Dah, thanks for looking into this! This must've been there this way
> for ages and we hadn't noticed until now. This is now fixed, and a new
> tarball pushed out. I'll fix on the stable stuff as well, although I
> doubt the header has changed much except now.
>
> Luis
>
Thanks everybody! Works alright now, after 'compat-2.6: stop shipping
bleeding edge iw_handler.h' .
There are some harmless warnings from using the old header, but
otherwise it is working as it should:
CC [M] /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.o
/home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c: In
function ‘__cfg80211_connect_result’:
/home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c:370:
warning: passing argument 4 of ‘wireless_send_event’ discards
qualifiers from pointer target type
include/net/iw_handler.h:443: note: expected ‘char *’ but argument is
of type ‘const u8 *’
/home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c:376:
warning: passing argument 4 of ‘wireless_send_event’ discards
qualifiers from pointer target type
include/net/iw_handler.h:443: note: expected ‘char *’ but argument is
of type ‘const u8 *’
/home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c: In
function ‘__cfg80211_roamed’:
/home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c:520:
warning: passing argument 4 of ‘wireless_send_event’ discards
qualifiers from pointer target type
include/net/iw_handler.h:443: note: expected ‘char *’ but argument is
of type ‘const u8 *’
/home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c:527:
warning: passing argument 4 of ‘wireless_send_event’ discards
qualifiers from pointer target type
include/net/iw_handler.h:443: note: expected ‘char *’ but argument is
of type ‘const u8 *’
Hin-Tak
^ permalink raw reply
* Re: NULL pointer deref at wext ioctl (Re: [PATCH] compat-2.6: adding ethtool.h to compat-2.6.31.h)
From: Luis R. Rodriguez @ 2009-10-09 0:14 UTC (permalink / raw)
To: Hin-Tak Leung; +Cc: Johannes Berg, John W. Linville, linux-wireless
In-Reply-To: <3ace41890910081622k7c86453dm72e5584f4adbb763@mail.gmail.com>
On Thu, Oct 8, 2009 at 7:22 PM, Hin-Tak Leung <hintak.leung@gmail.com> wrote:
> On Thu, Oct 8, 2009 at 2:43 PM, Luis R. Rodriguez
> <lrodriguez@atheros.com> wrote:
>> On Thu, Oct 8, 2009 at 7:50 AM, Johannes Berg <johannes@sipsolutions.net> wrote:
>>> On Thu, 2009-10-08 at 11:51 +0200, Johannes Berg wrote:
>>>
>>>> Ok, that's odd. Is it possible that somehow cfg80211 is picking up an
>>>> #ifdef'ed copy of "struct iw_handler_def", and thus the struct it is
>>>> defining is simply too small?
>>>
>>> That is apparently what is happening since compat-wireless ships
>>> iw_handler.h. This is wrong, as wext functionality is built into the
>>> kernel image so you can't use a newer header file with it.
>>
>> Dah, thanks for looking into this! This must've been there this way
>> for ages and we hadn't noticed until now. This is now fixed, and a new
>> tarball pushed out. I'll fix on the stable stuff as well, although I
>> doubt the header has changed much except now.
>>
>> Luis
>>
>
> Thanks everybody! Works alright now, after 'compat-2.6: stop shipping
> bleeding edge iw_handler.h' .
>
> There are some harmless warnings from using the old header, but
> otherwise it is working as it should:
> CC [M] /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.o
> /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c: In
> function ‘__cfg80211_connect_result’:
> /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c:370:
> warning: passing argument 4 of ‘wireless_send_event’ discards
> qualifiers from pointer target type
> include/net/iw_handler.h:443: note: expected ‘char *’ but argument is
> of type ‘const u8 *’
> /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c:376:
> warning: passing argument 4 of ‘wireless_send_event’ discards
> qualifiers from pointer target type
> include/net/iw_handler.h:443: note: expected ‘char *’ but argument is
> of type ‘const u8 *’
> /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c: In
> function ‘__cfg80211_roamed’:
> /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c:520:
> warning: passing argument 4 of ‘wireless_send_event’ discards
> qualifiers from pointer target type
> include/net/iw_handler.h:443: note: expected ‘char *’ but argument is
> of type ‘const u8 *’
> /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c:527:
> warning: passing argument 4 of ‘wireless_send_event’ discards
> qualifiers from pointer target type
> include/net/iw_handler.h:443: note: expected ‘char *’ but argument is
> of type ‘const u8 *’
The last argument to wireless_send_event() was changed to be const on
2.6.32, cant think of a way to avoid this warning.
Luis
^ permalink raw reply
* Re: pull request: wireless-2.6 2009-10-08
From: David Miller @ 2009-10-09 0:52 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20091008223454.GB2798@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Thu, 8 Oct 2009 18:34:54 -0400
> Here is another batch of fixes intended for 2.6.32. Most of them are
> short, self-contained and more-or-less obvious. Most of them have been
> baking in -next for several days.
>
> The b43 patch from Albert Herranz looks big, but most of it is moving a
> structure definition within a header file. It also changes some DMA
> buffers from stack to heap allocation.
>
> Please let me know if there are problems!
Pulled, thanks a lot John!
^ permalink raw reply
* Re: pull request: wireless-2.6 2009-10-08
From: David Miller @ 2009-10-09 0:55 UTC (permalink / raw)
To: mb; +Cc: linville, linux-wireless, netdev, linux-kernel
In-Reply-To: <200910090116.46513.mb@bu3sch.de>
From: Michael Buesch <mb@bu3sch.de>
Date: Fri, 9 Oct 2009 01:16:44 +0200
> And there's no reason to rush this fix into mainline.
I think it's worthwhile because people turn the DMA API debugger on
and it's going to spit out warnings that "don't matter" until you guys
fix this.
I looked at the patch you guys are so up in arms about, and frankly it
looks perfectly fine to me.
If you want to implement the fix "perfectly", and "to your standards",
then fine. But do it in net-next-2.6 as a follow-on patch to this
one.
I'm not undoing John's pull request just for this. :-)
^ permalink raw reply
* Re: pull request: wireless-2.6 2009-10-08
From: David Miller @ 2009-10-09 1:01 UTC (permalink / raw)
To: mb; +Cc: linville, linux-wireless, netdev, linux-kernel
In-Reply-To: <200910090108.08838.mb@bu3sch.de>
From: Michael Buesch <mb@bu3sch.de>
Date: Fri, 9 Oct 2009 01:08:06 +0200
> I was planning to do a better solution, but I didn't have the time, yet.
The change is harmless while we're twiddling our thumbs waiting
for you to implement the fix "properly."
Not having the fix in is a developer burdon because people turn
on the DMA API debugger and are going to keep reporting it's
complaints here and elsewhere.
Get over your Napoleon complex, and let reasonable working fixes
get into the tree even if you don't find them optimal. You can
always improve them later, "when you get around to it."
People put fixes in without my ACK in my areas of expertiece all
the time. I got over it a long time ago, it's OK, and not worth
stressing out over.
Thanks.
^ permalink raw reply
* [PATCH] libertas: Check return status of command functions
From: Bing Zhao @ 2009-10-09 2:38 UTC (permalink / raw)
To: libertas-dev; +Cc: linux-wireless, Bing Zhao, Amitkumar Karwar
From: Amitkumar Karwar <akarwar@marvell.com>
Return status of lbs_prepare_and_send_command and lbs_cmd_with_response
functions is not checked at some places. Those checks are added.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/libertas/debugfs.c | 27 ++++++++++++++++++---------
drivers/net/wireless/libertas/main.c | 2 ++
drivers/net/wireless/libertas/scan.c | 11 +++++++----
drivers/net/wireless/libertas/wext.c | 10 +++++++---
4 files changed, 34 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 893a55c..587b0cb 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -451,10 +451,12 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
CMD_MAC_REG_ACCESS, 0,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
- pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
+ if (!ret) {
+ pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
priv->mac_offset, priv->offsetvalue.value);
- ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ }
free_page(addr);
return ret;
}
@@ -514,7 +516,8 @@ static ssize_t lbs_wrmac_write(struct file *file,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
- res = count;
+ if (!res)
+ res = count;
out_unlock:
free_page(addr);
return res;
@@ -539,10 +542,12 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
CMD_BBP_REG_ACCESS, 0,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
- pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
+ if (!ret) {
+ pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
priv->bbp_offset, priv->offsetvalue.value);
- ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ }
free_page(addr);
return ret;
@@ -603,7 +608,8 @@ static ssize_t lbs_wrbbp_write(struct file *file,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
- res = count;
+ if (!res)
+ res = count;
out_unlock:
free_page(addr);
return res;
@@ -628,10 +634,12 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
CMD_RF_REG_ACCESS, 0,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
- pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
+ if (!ret) {
+ pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
priv->rf_offset, priv->offsetvalue.value);
- ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ }
free_page(addr);
return ret;
@@ -692,7 +700,8 @@ static ssize_t lbs_wrrf_write(struct file *file,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
- res = count;
+ if (!res)
+ res = count;
out_unlock:
free_page(addr);
return res;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 3b14fcc..bce752c 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1087,6 +1087,8 @@ static void auto_deepsleep_timer_fn(unsigned long data)
ret = lbs_prepare_and_send_command(priv,
CMD_802_11_DEEP_SLEEP, 0,
0, 0, NULL);
+ if (ret)
+ lbs_pr_err("Enter Deep Sleep command failed\n");
}
}
mod_timer(&priv->auto_deepsleep_timer , jiffies +
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 6c95af3..d8fc2b8 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -1022,9 +1022,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
return -EAGAIN;
/* Update RSSI if current BSS is a locally created ad-hoc BSS */
- if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate)
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
- CMD_OPTION_WAITFORRSP, 0, NULL);
+ if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
+ err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+ CMD_OPTION_WAITFORRSP, 0, NULL);
+ if (err)
+ goto out;
+ }
mutex_lock(&priv->lock);
list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
@@ -1058,7 +1061,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
dwrq->length = (ev - extra);
dwrq->flags = 0;
-
+out:
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
return err;
}
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 69dd19b..4594841 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -832,7 +832,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
u32 rssi_qual;
u32 tx_qual;
u32 quality = 0;
- int stats_valid = 0;
+ int ret, stats_valid = 0;
u8 rssi;
u32 tx_retries;
struct cmd_ds_802_11_get_log log;
@@ -881,7 +881,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
memset(&log, 0, sizeof(log));
log.hdr.size = cpu_to_le16(sizeof(log));
- lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
+ ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
+ if (ret)
+ goto out;
tx_retries = le32_to_cpu(log.retry);
@@ -909,8 +911,10 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
stats_valid = 1;
/* update stats asynchronously for future calls */
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
0, 0, NULL);
+ if (ret)
+ lbs_pr_err("RSSI command failed\n");
out:
if (!stats_valid) {
priv->wstats.miss.beacon = 0;
--
1.5.4.3
^ permalink raw reply related
* Re: [.32-rc3] scheduler: iwlagn consistently high in "waiting for CPU"
From: Mike Galbraith @ 2009-10-09 3:04 UTC (permalink / raw)
To: Frans Pop
Cc: Arjan van de Ven, Linux Kernel Mailing List, Ingo Molnar,
Peter Zijlstra, linux-wireless
In-Reply-To: <200910082259.35204.elendil@planet.nl>
On Thu, 2009-10-08 at 22:59 +0200, Frans Pop wrote:
> On Thursday 08 October 2009, Mike Galbraith wrote:
> > I still see very high latencies coming out of idle (last noted was >
> > 300ms, NO_HZ) with this patch,
> >
> > Like this:
> >
> > Cause Maximum Percentage
> > Scheduler: waiting for cpu 604.2 msec 49.0 %
>
> I'm not seeing anything even remotely like that.
>
> I've tried quieting the system down as much as possible, but that made
> no difference. I do have NO_HZ set; will send my full config privately.
>
> If you'd still like me to try your patch I will, but I'm not sure if
> that has much value.
No, if you watch for a bit with box mostly idle, and don't see > 100ms
hits occasionally, testing patchlet is likely a waste of time. To get
one like the above, I have to hold my tongue just right ;-) they're not
common.
-Mike
^ permalink raw reply
* Re: [.32-rc3] scheduler: iwlagn consistently high in "waiting for CPU"
From: Mike Galbraith @ 2009-10-09 3:35 UTC (permalink / raw)
To: Markus Trippelsdorf
Cc: Frans Pop, Arjan van de Ven, Linux Kernel Mailing List,
Ingo Molnar, Peter Zijlstra, linux-wireless
In-Reply-To: <20091008203426.GA1946@phenom2.trippelsdorf.de>
On Thu, 2009-10-08 at 22:34 +0200, Markus Trippelsdorf wrote:
> On Thu, Oct 08, 2009 at 08:23:37PM +0200, Mike Galbraith wrote:
> > On Thu, 2009-10-08 at 16:55 +0200, Frans Pop wrote:
> > > On Thursday 08 October 2009, Arjan van de Ven wrote:
> > > > From: Arjan van de Ven <arjan@linux.intel.com>
> > > > Date: Thu, 24 Sep 2009 13:24:16 +0200
> > > > Subject: [PATCH] x86, timers: check for pending timers after (device)
> > > > interrupts
> > > >
> > > > Now that range timers and deferred timers are common, I found a
> > > > problem with these using the "perf timechart" tool.
> > > >
> > > > It turns out that on x86, these two 'opportunistic' timers only
> > > > get checked when another "real" timer happens.
> > > > These opportunistic timers have the objective to save power by
> > > > hitchhiking on other wakeups, as to avoid CPU wakeups by themselves
> > > > as much as possible.
> > >
> > > This patch makes quite a difference for me. iwlagn and phy0 now
> > > consistently show at ~10 ms or lower.
> > >
> > > I do still get occasional high latencies, but those are for things like
> > > "[rpc_wait_bit_killable]" or "Writing a page to disk", where I guess you'd
> > > expect them. Those high latencies are mostly only listed for "Global" and
> > > don't translate to individual processes.
> >
> > I still see very high latencies coming out of idle (last noted was >
> > 300ms, NO_HZ) with this patch, and wonder if the hunk below makes any
> > difference whatsoever for you. Here, it definitely does. (shouldn't)
>
> I'm also seeing these strange, very high latencies here. Your patch
> didn't help unfortunately.
>
> This is from an otherwise idle NO_NZ system:
>
> # ./perf sched latency
>
> -----------------------------------------------------------------------------------------
> Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |
> -----------------------------------------------------------------------------------------
> ksoftirqd/0:4 | 2.216 ms | 170 | avg: 24.235 ms | max: 808.356 ms |
> ksoftirqd/1:6 | 2.611 ms | 205 | avg: 4.334 ms | max: 165.553 ms |
> migration/2:7 | 0.000 ms | 1 | avg: 3.060 ms | max: 3.060 ms |
>
> With latencytop the ksoftirqd latency is over 1 sec frequently. (Could be
> ondemand CPUfreq governor related?)
That's a separate issue, which Arjan was nice enough to fix for me. He
even wrote the changelog, and used my mouse to do so ;-)
Watch.
Virgin tip pulled this morning, perf sched record sleep 1 on idle box.
-----------------------------------------------------------------------------------------
Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |
-----------------------------------------------------------------------------------------
kicker:5845 | 0.000 ms | 1 | avg: 999.406 ms | max: 999.406 ms |
rt2870TimerQHan:4952 | 0.008 ms | 3 | avg: 0.087 ms | max: 0.131 ms |
Xorg:4913 | 0.099 ms | 2 | avg: 0.027 ms | max: 0.044 ms |
kondemand/3:3106 | 0.014 ms | 2 | avg: 0.013 ms | max: 0.018 ms |
perf:7229 | 3.986 ms | 1 | avg: 0.017 ms | max: 0.017 ms |
events/3:14 | 0.038 ms | 1 | avg: 0.017 ms | max: 0.017 ms |
kondemand/2:3105 | 0.017 ms | 1 | avg: 0.008 ms | max: 0.008 ms |
kondemand/1:3104 | 0.041 ms | 1 | avg: 0.007 ms | max: 0.007 ms |
konsole:5855 | 0.362 ms | 3 | avg: 0.004 ms | max: 0.006 ms |
kondemand/0:3103 | 0.000 ms | 1 | avg: 0.000 ms | max: 0.000 ms |
-----------------------------------------------------------------------------------------
TOTAL: | 4.565 ms | 16 |
---------------------------------------------------
INFO: 40.741% state machine bugs (11 out of 27)
INFO: 51.852% context switch bugs (14 out of 27)
Repeatable. Apply patchlet, and the numbers below become repeatable.
perf_counter tools: make perf sched pass -F 0 to record
Commit 42e59d7d19dc4b4 introduced a sample frequency framework..
.. however it unfortunately changed how perf events get recorded,
and caused sched to miss events.
This patch causes the sched code to use -F 0 to not use the
new framework when recording sched data.
Signed-off-by: Mike Galbraith <efault@gmx.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arjan The Wise <arjan@linux.intel.com>
LKML-Reference: <new-submission>
---
tools/perf/builtin-sched.c | 1 +
1 file changed, 1 insertion(+)
Index: linux-2.6/tools/perf/builtin-sched.c
===================================================================
--- linux-2.6.orig/tools/perf/builtin-sched.c
+++ linux-2.6/tools/perf/builtin-sched.c
@@ -1902,6 +1902,7 @@ static const char *record_args[] = {
"-f",
"-m", "1024",
"-c", "1",
+ "-F", "0",
"-e", "sched:sched_switch:r",
"-e", "sched:sched_stat_wait:r",
"-e", "sched:sched_stat_sleep:r",
-----------------------------------------------------------------------------------------
Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |
-----------------------------------------------------------------------------------------
Xorg:4913 | 2.296 ms | 43 | avg: 0.075 ms | max: 0.686 ms |
kicker:5845 | 3.106 ms | 28 | avg: 0.017 ms | max: 0.307 ms |
perf:7419 | 147.147 ms | 16 | avg: 0.028 ms | max: 0.261 ms |
klipper:6404 | 0.035 ms | 1 | avg: 0.256 ms | max: 0.256 ms |
kondemand/3:3106 | 0.139 ms | 18 | avg: 0.039 ms | max: 0.192 ms |
rt2870TimerQHan:4952 | 0.726 ms | 107 | avg: 0.010 ms | max: 0.165 ms |
konsole:5856 | 0.180 ms | 2 | avg: 0.050 ms | max: 0.094 ms |
kded:5831 | 0.044 ms | 1 | avg: 0.055 ms | max: 0.055 ms |
events/3:14 | 0.066 ms | 3 | avg: 0.018 ms | max: 0.031 ms |
kondemand/2:3105 | 0.015 ms | 2 | avg: 0.020 ms | max: 0.029 ms |
ksoftirqd/3:10 | 0.326 ms | 3 | avg: 0.018 ms | max: 0.027 ms |
kondemand/1:3104 | 0.142 ms | 24 | avg: 0.008 ms | max: 0.023 ms |
rt2870MlmeThrea:4950 | 0.095 ms | 13 | avg: 0.012 ms | max: 0.022 ms |
kondemand/0:3103 | 0.259 ms | 36 | avg: 0.013 ms | max: 0.020 ms |
kwin:5841 | 0.038 ms | 1 | avg: 0.018 ms | max: 0.018 ms |
sync_supers:92 | 0.008 ms | 1 | avg: 0.018 ms | max: 0.018 ms |
events/0:11 | 0.005 ms | 1 | avg: 0.015 ms | max: 0.015 ms |
konsole:5855 | 0.709 ms | 10 | avg: 0.007 ms | max: 0.013 ms |
events/2:13 | 0.009 ms | 1 | avg: 0.011 ms | max: 0.011 ms |
events/1:12 | 0.006 ms | 1 | avg: 0.010 ms | max: 0.010 ms |
mysqld:5030 | 0.185 ms | 1 | avg: 0.009 ms | max: 0.009 ms |
hald-addon-inpu:3191 | 0.006 ms | 1 | avg: 0.006 ms | max: 0.006 ms |
mono:6472 | 0.144 ms | 11 | avg: 0.005 ms | max: 0.006 ms |
ntpd:6020 | 0.030 ms | 1 | avg: 0.005 ms | max: 0.005 ms |
gpg-agent:5783 | 0.047 ms | 1 | avg: 0.005 ms | max: 0.005 ms |
sleep:7420 | 0.973 ms | 2 | avg: 0.003 ms | max: 0.005 ms |
httpd2-prefork:6416 | 0.013 ms | 1 | avg: 0.005 ms | max: 0.005 ms |
mysqld:5031 | 0.172 ms | 1 | avg: 0.005 ms | max: 0.005 ms |
kwrapper:5838 | 0.010 ms | 1 | avg: 0.005 ms | max: 0.005 ms |
-----------------------------------------------------------------------------------------
TOTAL: | 156.930 ms | 332 |
---------------------------------------------------
^ permalink raw reply
* Re: [.32-rc3] scheduler: iwlagn consistently high in "waiting for CPU"
From: Markus Trippelsdorf @ 2009-10-09 3:51 UTC (permalink / raw)
To: Mike Galbraith
Cc: Frans Pop, Arjan van de Ven, Linux Kernel Mailing List,
Ingo Molnar, Peter Zijlstra, linux-wireless
In-Reply-To: <1255059318.7236.13.camel@marge.simson.net>
On Fri, Oct 09, 2009 at 05:35:18AM +0200, Mike Galbraith wrote:
> On Thu, 2009-10-08 at 22:34 +0200, Markus Trippelsdorf wrote:
> > On Thu, Oct 08, 2009 at 08:23:37PM +0200, Mike Galbraith wrote:
> > > On Thu, 2009-10-08 at 16:55 +0200, Frans Pop wrote:
> > > > On Thursday 08 October 2009, Arjan van de Ven wrote:
> > > > > From: Arjan van de Ven <arjan@linux.intel.com>
> > > > > Date: Thu, 24 Sep 2009 13:24:16 +0200
> > > > > Subject: [PATCH] x86, timers: check for pending timers after (device)
> > > > > interrupts
> > > > >
> > > > > Now that range timers and deferred timers are common, I found a
> > > > > problem with these using the "perf timechart" tool.
> > > > >
> > > > > It turns out that on x86, these two 'opportunistic' timers only
> > > > > get checked when another "real" timer happens.
> > > > > These opportunistic timers have the objective to save power by
> > > > > hitchhiking on other wakeups, as to avoid CPU wakeups by themselves
> > > > > as much as possible.
> > > >
> > > > This patch makes quite a difference for me. iwlagn and phy0 now
> > > > consistently show at ~10 ms or lower.
> > > >
> > > > I do still get occasional high latencies, but those are for things like
> > > > "[rpc_wait_bit_killable]" or "Writing a page to disk", where I guess you'd
> > > > expect them. Those high latencies are mostly only listed for "Global" and
> > > > don't translate to individual processes.
> > >
> > > I still see very high latencies coming out of idle (last noted was >
> > > 300ms, NO_HZ) with this patch, and wonder if the hunk below makes any
> > > difference whatsoever for you. Here, it definitely does. (shouldn't)
> >
> > I'm also seeing these strange, very high latencies here. Your patch
> > didn't help unfortunately.
> >
> > This is from an otherwise idle NO_NZ system:
> >
> > # ./perf sched latency
> >
> > -----------------------------------------------------------------------------------------
> > Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |
> > -----------------------------------------------------------------------------------------
> > ksoftirqd/0:4 | 2.216 ms | 170 | avg: 24.235 ms | max: 808.356 ms |
> > ksoftirqd/1:6 | 2.611 ms | 205 | avg: 4.334 ms | max: 165.553 ms |
> > migration/2:7 | 0.000 ms | 1 | avg: 3.060 ms | max: 3.060 ms |
> >
> > With latencytop the ksoftirqd latency is over 1 sec frequently. (Could be
> > ondemand CPUfreq governor related?)
>
> That's a separate issue, which Arjan was nice enough to fix for me. He
> even wrote the changelog, and used my mouse to do so ;-)
>
>
> Repeatable. Apply patchlet, and the numbers below become repeatable.
>
> perf_counter tools: make perf sched pass -F 0 to record
>
> Commit 42e59d7d19dc4b4 introduced a sample frequency framework..
> .. however it unfortunately changed how perf events get recorded,
> and caused sched to miss events.
>
> This patch causes the sched code to use -F 0 to not use the
> new framework when recording sched data.
Yes, your're right. With this patch applied perf sched latency is back
to normal.
--
Markus
^ permalink raw reply
* [PATCH] ath9k: Fix TX hang poll routine
From: Sujith @ 2009-10-09 4:21 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
When TX is hung, the chip is reset. Ensure that
the chip is awake by using the PS wrappers.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/xmit.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index a8620b1..2a4efcb 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2079,7 +2079,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
if (needreset) {
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
"tx hung, resetting the chip\n");
+ ath9k_ps_wakeup(sc);
ath_reset(sc, false);
+ ath9k_ps_restore(sc);
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
--
1.6.4.4
^ permalink raw reply related
* Re: [.32-rc3] scheduler: iwlagn consistently high in "waiting for CPU"
From: Mike Galbraith @ 2009-10-09 6:35 UTC (permalink / raw)
To: Frans Pop
Cc: Arjan van de Ven, Linux Kernel Mailing List, Ingo Molnar,
Peter Zijlstra, linux-wireless
In-Reply-To: <200910082259.35204.elendil@planet.nl>
On Thu, 2009-10-08 at 22:59 +0200, Frans Pop wrote:
> On Thursday 08 October 2009, Mike Galbraith wrote:
> > I still see very high latencies coming out of idle (last noted was >
> > 300ms, NO_HZ) with this patch,
> >
> > Like this:
> >
> > Cause Maximum Percentage
> > Scheduler: waiting for cpu 604.2 msec 49.0 %
>
> I'm not seeing anything even remotely like that.
Instrumenting, I saw (stale) clock deltas of >900ms coming out of idle,
delta being the difference between rq->clock when we hit update_curr()
and discover that this queue was idle, and what the clock will be an
instant or two later when somebody winds the clock.
I've been watching latencytop for a while now to make sure latency is
really dead. I see no twitching, so...
sched: update the clock of runqueue select_task_rq() selected.
In try_to_wake_up(), we update the runqueue clock, but select_task_rq()
may select a different runqueue than the one we updated, leaving the new
runqueue's clock stale for a bit.
This patch cures occasional huge latencies reported by latencytop when
coming out of idle on a mostly idle NO_HZ box.
Signed-off-by: Mike Galbraith <efault@gmx.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <new-submission>
---
kernel/sched.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -2311,7 +2311,7 @@ static int try_to_wake_up(struct task_st
{
int cpu, orig_cpu, this_cpu, success = 0;
unsigned long flags;
- struct rq *rq;
+ struct rq *rq, *orig_rq;
if (!sched_feat(SYNC_WAKEUPS))
wake_flags &= ~WF_SYNC;
@@ -2319,7 +2319,7 @@ static int try_to_wake_up(struct task_st
this_cpu = get_cpu();
smp_wmb();
- rq = task_rq_lock(p, &flags);
+ rq = orig_rq = task_rq_lock(p, &flags);
update_rq_clock(rq);
if (!(p->state & state))
goto out;
@@ -2350,6 +2350,10 @@ static int try_to_wake_up(struct task_st
set_task_cpu(p, cpu);
rq = task_rq_lock(p, &flags);
+
+ if (rq != orig_rq)
+ update_rq_clock(rq);
+
WARN_ON(p->state != TASK_WAKING);
cpu = task_cpu(p);
^ permalink raw reply
* Re: [.32-rc3] scheduler: iwlagn consistently high in "waiting for CPU"
From: Peter Zijlstra @ 2009-10-09 7:13 UTC (permalink / raw)
To: Mike Galbraith
Cc: Frans Pop, Arjan van de Ven, Linux Kernel Mailing List,
Ingo Molnar, linux-wireless
In-Reply-To: <1255070103.7639.30.camel@marge.simson.net>
On Fri, 2009-10-09 at 08:35 +0200, Mike Galbraith wrote:
>
> sched: update the clock of runqueue select_task_rq() selected.
>
> In try_to_wake_up(), we update the runqueue clock, but select_task_rq()
> may select a different runqueue than the one we updated, leaving the new
> runqueue's clock stale for a bit.
>
> This patch cures occasional huge latencies reported by latencytop when
> coming out of idle on a mostly idle NO_HZ box.
>
> Signed-off-by: Mike Galbraith <efault@gmx.de>
> Cc: Ingo Molnar <mingo@elte.hu>
> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Awesome catch Mike, seems I goofed up in my recent ttwu changes.
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
>
> ---
> kernel/sched.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> Index: linux-2.6/kernel/sched.c
> ===================================================================
> --- linux-2.6.orig/kernel/sched.c
> +++ linux-2.6/kernel/sched.c
> @@ -2311,7 +2311,7 @@ static int try_to_wake_up(struct task_st
> {
> int cpu, orig_cpu, this_cpu, success = 0;
> unsigned long flags;
> - struct rq *rq;
> + struct rq *rq, *orig_rq;
>
> if (!sched_feat(SYNC_WAKEUPS))
> wake_flags &= ~WF_SYNC;
> @@ -2319,7 +2319,7 @@ static int try_to_wake_up(struct task_st
> this_cpu = get_cpu();
>
> smp_wmb();
> - rq = task_rq_lock(p, &flags);
> + rq = orig_rq = task_rq_lock(p, &flags);
> update_rq_clock(rq);
> if (!(p->state & state))
> goto out;
> @@ -2350,6 +2350,10 @@ static int try_to_wake_up(struct task_st
> set_task_cpu(p, cpu);
>
> rq = task_rq_lock(p, &flags);
> +
> + if (rq != orig_rq)
> + update_rq_clock(rq);
> +
> WARN_ON(p->state != TASK_WAKING);
> cpu = task_cpu(p);
>
>
>
>
^ permalink raw reply
* [PATCH] libertas: depend on CONFIG_CFG80211
From: Holger Schurig @ 2009-10-09 7:10 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: John W Linville, Dan Williams, linux-wireless
Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>
---
Fixes bug noted by Stephen Rothwell:
> On Wed, 7 Oct 2009 17:35:17 +1100 Stephen Rothwell wrote:
>
> > Hi all,
> >
> > Changes since 20091006:
>
>
> drivers/built-in.o: In function `lbs_cfg_free':
> (.text+0x3479e0): undefined reference to `wiphy_unregister'
> drivers/built-in.o: In function `lbs_cfg_free':
> (.text+0x3479e7): undefined reference to `wiphy_free'
> drivers/built-in.o: In function `lbs_cfg_register':
> (.text+0x347a52): undefined reference to `wiphy_register'
> drivers/built-in.o: In function `lbs_cfg_alloc':
> (.text+0x347acf): undefined reference to `wiphy_new'
Index: linux-wl/drivers/net/wireless/libertas/Kconfig
===================================================================
--- linux-wl.orig/drivers/net/wireless/libertas/Kconfig 2009-10-09 08:00:03.000000000 +0200
+++ linux-wl/drivers/net/wireless/libertas/Kconfig 2009-10-09 08:00:27.000000000 +0200
@@ -1,6 +1,6 @@
config LIBERTAS
tristate "Marvell 8xxx Libertas WLAN driver support"
- depends on WLAN_80211
+ depends on WLAN_80211 && CFG80211
select WIRELESS_EXT
select WEXT_SPY
select LIB80211
--
http://www.holgerschurig.de
^ permalink raw reply
* Re: [PATCH] libertas: remove double assignment of dev->netdev_ops
From: Holger Schurig @ 2009-10-09 7:22 UTC (permalink / raw)
To: Luis R. Rodriguez; +Cc: linville, linux-wireless
In-Reply-To: <1255034769-18882-1-git-send-email-lrodriguez@atheros.com>
On Thursday 08 October 2009 22:46:09 Luis R. Rodriguez wrote:
> - dev->netdev_ops = &lbs_netdev_ops;
Acked-by: Holger Schurig <hs4233@mail.mn-solutions.de>
--
http://www.holgerschurig.de
^ permalink raw reply
* Re: [.32-rc3] scheduler: iwlagn consistently high in "waiting for CPU"
From: Sedat Dilek @ 2009-10-09 7:55 UTC (permalink / raw)
To: Mike Galbraith
Cc: Frans Pop, Arjan van de Ven, Linux Kernel Mailing List,
Ingo Molnar, Peter Zijlstra, linux-wireless
In-Reply-To: <1255070103.7639.30.camel@marge.simson.net>
Hi Mike,
will you (re)send this patch as a new one with correct subject line to LKML?
Otherwise, it might disapper in this long thread.
Kind Regards,
- Sedat -
On Fri, Oct 9, 2009 at 8:35 AM, Mike Galbraith <efault@gmx.de> wrote:
> On Thu, 2009-10-08 at 22:59 +0200, Frans Pop wrote:
>> On Thursday 08 October 2009, Mike Galbraith wrote:
>> > I still see very high latencies coming out of idle (last noted was >
>> > 300ms, NO_HZ) with this patch,
>> >
>> > Like this:
>> >
>> > Cause Maximum Percentage
>> > Scheduler: waiting for cpu 604.2 msec 49.0 %
>>
>> I'm not seeing anything even remotely like that.
>
> Instrumenting, I saw (stale) clock deltas of >900ms coming out of idle,
> delta being the difference between rq->clock when we hit update_curr()
> and discover that this queue was idle, and what the clock will be an
> instant or two later when somebody winds the clock.
>
> I've been watching latencytop for a while now to make sure latency is
> really dead. I see no twitching, so...
>
> sched: update the clock of runqueue select_task_rq() selected.
>
> In try_to_wake_up(), we update the runqueue clock, but select_task_rq()
> may select a different runqueue than the one we updated, leaving the new
> runqueue's clock stale for a bit.
>
> This patch cures occasional huge latencies reported by latencytop when
> coming out of idle on a mostly idle NO_HZ box.
>
> Signed-off-by: Mike Galbraith <efault@gmx.de>
> Cc: Ingo Molnar <mingo@elte.hu>
> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
> LKML-Reference: <new-submission>
>
> ---
> kernel/sched.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> Index: linux-2.6/kernel/sched.c
> ===================================================================
> --- linux-2.6.orig/kernel/sched.c
> +++ linux-2.6/kernel/sched.c
> @@ -2311,7 +2311,7 @@ static int try_to_wake_up(struct task_st
> {
> int cpu, orig_cpu, this_cpu, success = 0;
> unsigned long flags;
> - struct rq *rq;
> + struct rq *rq, *orig_rq;
>
> if (!sched_feat(SYNC_WAKEUPS))
> wake_flags &= ~WF_SYNC;
> @@ -2319,7 +2319,7 @@ static int try_to_wake_up(struct task_st
> this_cpu = get_cpu();
>
> smp_wmb();
> - rq = task_rq_lock(p, &flags);
> + rq = orig_rq = task_rq_lock(p, &flags);
> update_rq_clock(rq);
> if (!(p->state & state))
> goto out;
> @@ -2350,6 +2350,10 @@ static int try_to_wake_up(struct task_st
> set_task_cpu(p, cpu);
>
> rq = task_rq_lock(p, &flags);
> +
> + if (rq != orig_rq)
> + update_rq_clock(rq);
> +
> WARN_ON(p->state != TASK_WAKING);
> cpu = task_cpu(p);
>
>
>
> --
> 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: [.32-rc3] scheduler: iwlagn consistently high in "waiting for CPU"
From: Peter Zijlstra @ 2009-10-09 8:06 UTC (permalink / raw)
To: Sedat Dilek
Cc: Mike Galbraith, Frans Pop, Arjan van de Ven,
Linux Kernel Mailing List, Ingo Molnar, linux-wireless
In-Reply-To: <2d0a357f0910090055v7a454ca5rb895fecbb9747ecd@mail.gmail.com>
On Fri, 2009-10-09 at 09:55 +0200, Sedat Dilek wrote:
>
> will you (re)send this patch as a new one with correct subject line to LKML?
> Otherwise, it might disapper in this long thread.
No need, I've got it.
^ permalink raw reply
* Re: NULL pointer deref at wext ioctl (Re: [PATCH] compat-2.6: adding ethtool.h to compat-2.6.31.h)
From: Johannes Berg @ 2009-10-09 8:05 UTC (permalink / raw)
To: Luis R. Rodriguez; +Cc: Hin-Tak Leung, John W. Linville, linux-wireless
In-Reply-To: <43e72e890910081714u7e1d2168u98c0ccb74915c94c@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 866 bytes --]
On Thu, 2009-10-08 at 20:14 -0400, Luis R. Rodriguez wrote:
> > There are some harmless warnings from using the old header, but
> > otherwise it is working as it should:
> > CC [M] /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.o
> > /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c: In
> > function ‘__cfg80211_connect_result’:
> > /home/Hin-Tak/tmp-git/compat-wireless-2.6/net/wireless/sme.c:370:
> > warning: passing argument 4 of ‘wireless_send_event’ discards
> > qualifiers from pointer target type
> > include/net/iw_handler.h:443: note: expected ‘char *’ but argument is
> > of type ‘const u8 *’
> The last argument to wireless_send_event() was changed to be const on
> 2.6.32, cant think of a way to avoid this warning.
Yeah, it was never modified though so the warning is harmless.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: pull request: wireless-2.6 2009-10-08
From: Michael Buesch @ 2009-10-09 8:57 UTC (permalink / raw)
To: David Miller; +Cc: linville, linux-wireless, netdev, linux-kernel
In-Reply-To: <20091008.180119.242402327.davem@davemloft.net>
On Friday 09 October 2009 03:01:19 David Miller wrote:
> From: Michael Buesch <mb@bu3sch.de>
> Date: Fri, 9 Oct 2009 01:08:06 +0200
>
> > I was planning to do a better solution, but I didn't have the time, yet.
>
> The change is harmless while we're twiddling our thumbs waiting
> for you to implement the fix "properly."
>
> Not having the fix in is a developer burdon because people turn
> on the DMA API debugger and are going to keep reporting it's
> complaints here and elsewhere.
>
> Get over your Napoleon complex, and let reasonable working fixes
> get into the tree even if you don't find them optimal. You can
> always improve them later, "when you get around to it."
>
> People put fixes in without my ACK in my areas of expertiece all
> the time. I got over it a long time ago, it's OK, and not worth
> stressing out over.
Ok, that's enough. If you do not need a maintainer, then work without one.
What's a maintainer good for, if it's not for maintaining the code quality?
The patch needlessly moves huge chunks of crap, adds stupid comments, wastes memory.
If that's what you want just to remove a debugging message on devices that virtually
nobody owns, so be it.
---
MAINTAINERS | 1 -
1 file changed, 1 deletion(-)
--- wireless-testing.orig/MAINTAINERS
+++ wireless-testing/MAINTAINERS
@@ -1066,7 +1066,6 @@ F: include/net/ax25.h
F: net/ax25/
B43 WIRELESS DRIVER
-M: Michael Buesch <mb@bu3sch.de>
M: Stefano Brivio <stefano.brivio@polimi.it>
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/en/users/Drivers/b43
--
Greetings, Michael.
^ permalink raw reply
* [PATCH V3] iwlwifi: use paged Rx
From: Zhu Yi @ 2009-10-09 9:19 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Zhu Yi
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
^ permalink raw reply related
* Re: pull request: wireless-2.6 2009-10-08
From: David Miller @ 2009-10-09 9:18 UTC (permalink / raw)
To: mb; +Cc: linville, linux-wireless, netdev, linux-kernel
In-Reply-To: <200910091057.21269.mb@bu3sch.de>
From: Michael Buesch <mb@bu3sch.de>
Date: Fri, 9 Oct 2009 10:57:19 +0200
> What's a maintainer good for, if it's not for maintaining the code
> quality?
It does not mean you get total control over anything, ever.
That's my main point.
Every maintainer who loses his mind when some change goes in he
doesn't like has a serious control problem. And yes, sometimes that
includes me.
^ permalink raw reply
* Re: [2.6.32-rc3] iwlagn lost connection after s2ram (with warnings)
From: Carlos R. Mafra @ 2009-10-09 9:36 UTC (permalink / raw)
To: reinette chatre
Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
johannes
In-Reply-To: <20091008181534.GA19621@Pilar.aei.mpg.de>
On Thu 8.Oct'09 at 20:15:34 +0200, Carlos R. Mafra wrote:
> I will keep you informed if it happens again.
Yes, it just happened again. I saved the dmesg, but it looks identical
to the one I already posted.
So the problem is still there (with 2.6.32-rc3+ now), but I am very afraid
of trying a bisection marathon here, because it does not happen everytime.
Anything else I could try to help debbuging this?
^ permalink raw reply
* Broadcom cards for free
From: Michael Buesch @ 2009-10-09 9:39 UTC (permalink / raw)
To: bcm43xx-dev; +Cc: linux-wireless
Hi,
I've currently got two Broadcom cards to offer for free.
http://bu3sch.de/misc/bcmcards.JPG
The cardbus one is a WPC300N V1 802.11n card.
It can be used for development of the b43 N-PHY code.
The USB one is BCM4320 which works over RNDIS-WLAN.
This device is disassembled and the EEPROM, which contains
the on-board operating system, is unsoldered and connected through a pinheader.
That means it can be read and/or reprogrammed outside of the device.
The RF-shield on the RF-side of the board was removed.
The device should work properly. It properly registers to the kernel, but I did
not try if it works with the rndis-wlan driver.
--
Greetings, Michael.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox