* Re: iwlwifi: Intel 3945ABG speed issues finally identified.
From: Guy, Wey-Yi @ 2010-12-24 16:19 UTC (permalink / raw)
To: Eric Appleman; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <loom.20101224T055254-814@post.gmane.org>
On Thu, 2010-12-23 at 22:16 -0800, Eric Appleman wrote:
> Btw, I've never seen a firmware reload message in association with this bug,
> regardless of commit, whether it be from May or December.
> then most likely "stuck queue detection" is not the problem.
Wey
>
> --
> 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: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Dave Kilroy @ 2010-12-24 16:46 UTC (permalink / raw)
To: Bruno Randolf; +Cc: johannes, linville, linux-wireless
In-Reply-To: <20101224074410.16337.90008.stgit@localhost6.localdomain6>
On Fri, Dec 24, 2010 at 7:44 AM, Bruno Randolf <br1@einfach.org> wrote:
> Extend channel to frequency mapping for 802.11j Japan 4.9GHz band, according to
> IEEE802.11 section 17.3.8.3.2 and Annex J. Because there are now overlapping
> channel numbers in the 2GHz and 5GHz band we can't map from channel to
> frequency without knowing the band. This is no problem as in most contexts we
> know the band. In places where we don't know the band (and WEXT compatibility)
> we assume the 2GHz band for channels below 14.
>
> Signed-off-by: Bruno Randolf <br1@einfach.org>
> ---
> -int ieee80211_channel_to_frequency(int chan)
> +int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band)
> {
> - if (chan < 14)
> - return 2407 + chan * 5;
> -
> - if (chan == 14)
> - return 2484;
> -
> - /* FIXME: 802.11j 17.3.8.3.2 */
> - return (chan + 1000) * 5;
> + /* see 802.11 17.3.8.3.2 and Annex J
> + * there are overlapping channel numbers in 5GHz and 2GHz bands */
> + if (band == IEEE80211_BAND_5GHZ) {
> + if (chan >= 182 && chan <= 196)
> + return 4000 + chan * 5;
> + else
> + return 5000 + chan * 5;
> + } else { /* IEEE80211_BAND_2GHZ */
> + if (chan == 14)
> + return 2484;
> + else if (chan < 14)
> + return 2407 + chan * 5;
> + else
> + return 0; /* not supported */
> + }
> }
> EXPORT_SYMBOL(ieee80211_channel_to_frequency);
>
> int ieee80211_frequency_to_channel(int freq)
> {
> + /* see 802.11 17.3.8.3.2 and Annex J */
> if (freq == 2484)
> return 14;
> -
> - if (freq < 2484)
> + else if (freq < 2484)
> return (freq - 2407) / 5;
> -
> - /* FIXME: 802.11j 17.3.8.3.2 */
> - return freq/5 - 1000;
> + else if (freq >= 4910 && freq <= 4980)
> + return (freq - 4000) / 5;
> + else
> + return (freq - 5000) / 5;
> }
> EXPORT_SYMBOL(ieee80211_frequency_to_channel);
You don't have to use them, but there are a few channel/frequency
conversion routines in include/ieee80211.h which could be reused in
these functions.
Regards,
Dave.
^ permalink raw reply
* Re: iwlwifi: Intel 3945ABG speed issues finally identified.
From: Guy, Wey-Yi @ 2010-12-24 16:37 UTC (permalink / raw)
To: Eric Appleman; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <loom.20101224T030743-87@post.gmane.org>
On Thu, 2010-12-23 at 18:08 -0800, Eric Appleman wrote:
> Hmmm.
>
> Both "fix internal scan" and "stuck queue detection" made the cut for the rc2
> kernel. Said kernel is unaffected by the bug.
>
> For rc3, "rcu lock" and "move sysfs" both make the cut. "serialize station
> management" barely misses the cut.
>
> Does the sysfs commit apply to the 3945 or is it only for newer cards?
>
> -
"move sysfs_create_group to post request firmware" patch only apply to
_agn, not for 3945. so it is not the problem :-(
Wey
^ permalink raw reply
* Compat-wireless release for 2010-12-24 is baked
From: Compat-wireless cronjob account @ 2010-12-24 20:03 UTC (permalink / raw)
To: linux-wireless
compat-wireless code metrics
777174 - Total upstream lines of code being pulled
2223 - backport code changes
1946 - backport code additions
277 - backport code deletions
6648 - backport from compat module
8871 - total backport code
1.1414 - % of code consists of backport work
1532 - Crap changes not yet posted
1489 - Crap additions not yet posted
43 - Crap deletions not yet posted
0.1971 - % of crap code
Base tree: linux-next.git
Base tree version: next-20101221
compat-wireless release: compat-wireless-2010-12-20-1-g53f8e22-pc
^ permalink raw reply
* Re: iwlwifi: Intel 3945ABG speed issues finally identified.
From: Eric Appleman @ 2010-12-24 22:13 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <1293208648.3997.54.camel@wwguy-huron>
So, unless I find something between 2.6.34 release and 2.6.35-rc2 (no changes
between rc1 and rc2), that leaves "fix internal scan", doesn't it?
Btw, this bug is ridiculously hard to test. The early rc kernels for 2.6.35 are
a pain in the ass to test because the iwl3945 driver was in flux at the time. If
I push too hard with speedtests, the driver will cause a kernel panic.
^ permalink raw reply
* [PATCH] airo: use simple_write_to_buffer
From: Akinobu Mita @ 2010-12-25 6:03 UTC (permalink / raw)
To: linux-kernel; +Cc: Akinobu Mita, John W. Linville, linux-wireless, netdev
Simplify write file operation for /proc files by using
simple_write_to_buffer().
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
---
drivers/net/wireless/airo.c | 20 +++++++-------------
1 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index a36e787..57a79b0 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4652,24 +4652,18 @@ static ssize_t proc_write( struct file *file,
size_t len,
loff_t *offset )
{
- loff_t pos = *offset;
+ ssize_t ret;
struct proc_data *priv = file->private_data;
if (!priv->wbuffer)
return -EINVAL;
- if (pos < 0)
- return -EINVAL;
- if (pos >= priv->maxwritelen)
- return 0;
- if (len > priv->maxwritelen - pos)
- len = priv->maxwritelen - pos;
- if (copy_from_user(priv->wbuffer + pos, buffer, len))
- return -EFAULT;
- if ( pos + len > priv->writelen )
- priv->writelen = len + file->f_pos;
- *offset = pos + len;
- return len;
+ ret = simple_write_to_buffer(priv->wbuffer, priv->maxwritelen, offset,
+ buffer, len);
+ if (ret > 0)
+ priv->writelen = max_t(int, priv->writelen, *offset);
+
+ return ret;
}
static int proc_status_open(struct inode *inode, struct file *file)
--
1.7.3.4
^ permalink raw reply related
* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Ohad Ben-Cohen @ 2010-12-25 7:34 UTC (permalink / raw)
To: Alan Stern
Cc: Rafael J. Wysocki, linux-pm, Johannes Berg, linux-wireless,
linux-mmc, Ido Yariv, Kevin Hilman
In-Reply-To: <Pine.LNX.4.44L0.1012231055440.5617-100000@netrider.rowland.org>
On Thu, Dec 23, 2010 at 6:03 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> I'm still not aware of the details of your situation. Nevertheless, it
> shouldn't be hard to set up a suspend() routine that would do whatever
> was needed to power down the device, whether this means calling the
> runtime_suspend() routine directly or something else. That's basically
> what every other driver does.
And that's what we already do as well, but as I wrote earlier, in our
specific scenario this _breaks_ if system suspend is cancelled (for
whatever reason) _before_ our suspend handler kicks in (and after
mac80211 has suspended our driver).
Moreover, even if it did work, it wouldn't have been enough.
I'll try to explain, and if something is still not clear, please let me know.
Our wlan device is an ARM microcontroller running some flavor of RTOS
(i.e. the firmware); as I mentioned before, its power and reset
functionalities are tied together (as far as software is concerned. a
small detail I won't get into now). The ability to unconditionally
power it down is needed for error recovery, for booting a new firmware
(and for unconditionally stopping all radios...).
The driver assumes it can unconditionally power down the device, and
is built around this assumption, so a user interface such as
/sys/devices/.../power/control has no sense, and if set to 'on', will
be fatal for this driver (e.g. it will not be possible to bring the
wlan interface down and up).
There is no way around this. The driver must be able to
unconditionally power the hardware down.
About the suspend/resume issue:
This is a mac80211 driver. It is basically a set of "dumb" handlers,
which mac80211 uses to abstract the hardware differences between its
various drivers. For example, there are handlers to take down/up an
interface, to start/stop the hardware, etc..
When one of the driver's handlers is being called, the driver doesn't
really know (or care) if this is during runtime or not. If it is asked
to stop its hardware, it should just do so. And when (in our case)
this handler is invoked during system suspend, any disability to power
off the device immediately opens a window for races due to the
driver's assumption, on resume, that the device was powered off
successfully. So, yeah, we do have a suspend() handler, which powers
the device off directly, but we need the "runtime" handler of the
driver to immediately succeed too in order to prevent the race (and
then it's fully powered off and we wouldn't need to wait for the
suspend() handler to do so too). For that to happen, we need runtime
PM not to be disabled during system suspend (or by
/sys/devices/.../power/control).
Tweaking the driver around this limitation (to realize somehow if the
hardware was really powered down or not) doesn't make sense and
frankly isn't worth the effort, since the driver anyway has to be able
to unconditionally power down the device for the aforementioned
reasons (error recovery, reboot a new fw, disable radios, ..).
A small comment: SDIO drivers' suspend handler is actually triggered
by the mmc host controller's suspend routine (through the SDIO
subsystem); it's not the classic dpm-triggered suspend handler, so
Rafael's notion of "runtime only" flag will work here.
Why runtime PM:
The device has an SDIO interface, so one of its incarnations is an SDIO driver.
Short background: MMC/SDIO cards are dynamically probed, identified
and configured by the MMC/SDIO subsystem, so toggling their power must
take place from within the MMC/SDIO subsystem itself.
Until recently, MMC/SDIO cards were kept powered on from the moment
they were inserted, up until they were removed (exception: power was
removed on system suspend and brought up back on resume. there is an
exception to this exception, too, but I won't get into that now).
Recently, we have added runtime PM support to the MMC/SDIO subsystem,
so cards can be powered down when they're not in use. E.g., an SDIO
card is powered down if no driver is available or requires power to
it, and an MMC card might be powered off after some period of
inactivity (the latter is just being discussed and has not yet hit
mainline).
As far as the MMC/SDIO subsystem is concerned, this is merely a power
optimization, and it's perfectly fine if the user will disable runtime
PM for the card and by that disallow powering it down.
But for our particular device this is fatal; as explained, the driver
must have unconditional control of the device's power.
So we need runtime PM at the subsystem level (to allow the MMC/SDIO
subsystem power it off in case the driver is not loaded), but we will
have no choice but bypass runtime PM at the driver level, in order to
avoid the aforementioned suspend race, and a potential
/sys/devices/.../power/control block.
To maintain coherency with the runtime-PM's usage_count (and by that
prevent dpm_complete() from powering off our device after a system
resume) we will also keep calling the pm_runtime_{get, put} API
appropriately.
It's not pretty, but this is the only way we can make this work
(unless, of course, our use case will be supported within the
runtime-PM framework itself).
Thanks,
Ohad.
^ permalink raw reply
* Re: Backporting wl1271 driver to kernel-2.6.32 using compat-wireless
From: Ohad Ben-Cohen @ 2010-12-25 8:02 UTC (permalink / raw)
To: Elvis Dowson; +Cc: Hauke Mehrtens, Linux Wireless Mailing List
In-Reply-To: <15BE8E73-27A7-4415-9196-B4BD56D72338@mac.com>
On Fri, Dec 24, 2010 at 7:17 AM, Elvis Dowson <elvis.dowson@mac.com> wrote:
> When working with the wl1271 backport to 2.6.32 kernel, is CONFIG_MMC_EMBEDDED_SDIO=y required?
Nope. wl1271 doesn't need it - the device is dynamically probed,
identified and configured.
^ permalink raw reply
* Re: Backporting wl1271 driver to kernel-2.6.32 using compat-wireless
From: Ohad Ben-Cohen @ 2010-12-25 8:05 UTC (permalink / raw)
To: Elvis Dowson; +Cc: Linux Wireless Mailing List
In-Reply-To: <FF69470D-9C14-4324-BA8E-F134B2AD9DEE@mac.com>
On Thu, Dec 23, 2010 at 11:12 PM, Elvis Dowson <elvis.dowson@mac.com> wrote:
> Is the SDIO subsystem sufficiently modular so as to allow me to take a few file and use it as a drop in
> replacement for the 2.6.32 kernel?
I'm not sure I'm following the question...
btw, IMHO you don't need to replace any file at all. 2.6.32 has a
functional SDIO subsystem.
>
> Elvis Dowson
>
>
^ permalink raw reply
* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Alan Stern @ 2010-12-25 16:21 UTC (permalink / raw)
To: Ohad Ben-Cohen
Cc: Rafael J. Wysocki, linux-pm, Johannes Berg, linux-wireless,
linux-mmc, Ido Yariv, Kevin Hilman
In-Reply-To: <AANLkTi=aHU57xDq+-DWrN2sJsAwx_9bZ_ofy1rOmp0VH@mail.gmail.com>
On Sat, 25 Dec 2010, Ohad Ben-Cohen wrote:
> I'll try to explain, and if something is still not clear, please let me know.
>
> Our wlan device is an ARM microcontroller running some flavor of RTOS
> (i.e. the firmware); as I mentioned before, its power and reset
> functionalities are tied together (as far as software is concerned. a
> small detail I won't get into now). The ability to unconditionally
> power it down is needed for error recovery, for booting a new firmware
> (and for unconditionally stopping all radios...).
Okay.
> The driver assumes it can unconditionally power down the device, and
> is built around this assumption, so a user interface such as
> /sys/devices/.../power/control has no sense, and if set to 'on', will
> be fatal for this driver (e.g. it will not be possible to bring the
> wlan interface down and up).
>
> There is no way around this. The driver must be able to
> unconditionally power the hardware down.
Right. You may or may not realize it, but this requirement means that
the driver _must_ bypass runtime PM sometimes.
> About the suspend/resume issue:
>
> This is a mac80211 driver. It is basically a set of "dumb" handlers,
> which mac80211 uses to abstract the hardware differences between its
> various drivers. For example, there are handlers to take down/up an
> interface, to start/stop the hardware, etc..
>
> When one of the driver's handlers is being called, the driver doesn't
> really know (or care) if this is during runtime or not. If it is asked
> to stop its hardware, it should just do so.
With you so far.
> And when (in our case)
> this handler is invoked during system suspend, any disability to power
> off the device immediately opens a window for races due to the
> driver's assumption, on resume, that the device was powered off
> successfully.
Now you've lost me. Which of the driver's handlers are you talking
about? The one responsible for powering down the device? What races?
Why does the driver have to _assume_ the device was powered off -- why
doesn't it simply _do_ the power down? (As you said above, if it is
asked to stop its hardware, it should just do so.)
> So, yeah, we do have a suspend() handler, which powers
> the device off directly, but we need the "runtime" handler of the
Which "runtime" handler? Are you talking about the runtime_suspend
method, the runtime_resume method, the runtime_idle method, or
something else?
> driver to immediately succeed too in order to prevent the race (and
> then it's fully powered off and we wouldn't need to wait for the
> suspend() handler to do so too). For that to happen, we need runtime
> PM not to be disabled during system suspend (or by
> /sys/devices/.../power/control).
At this point I'm so confused, it's hard to ask a rational question.
What goes wrong if runtime PM is disabled during system suspend?
Since the driver must bypass runtime PM anyway, what difference does it
make if runtime PM is disabled?
> Tweaking the driver around this limitation (to realize somehow if the
> hardware was really powered down or not) doesn't make sense and
> frankly isn't worth the effort, since the driver anyway has to be able
> to unconditionally power down the device for the aforementioned
> reasons (error recovery, reboot a new fw, disable radios, ..).
>
> A small comment: SDIO drivers' suspend handler is actually triggered
> by the mmc host controller's suspend routine (through the SDIO
> subsystem); it's not the classic dpm-triggered suspend handler, so
> Rafael's notion of "runtime only" flag will work here.
Maybe it would help if you provided a list of the relevant subroutines
together with descriptions of the circumstances under which they are
called and what they are expected to do. For example, a brief
pseudo-code listing.
> Why runtime PM:
>
> The device has an SDIO interface, so one of its incarnations is an SDIO driver.
>
> Short background: MMC/SDIO cards are dynamically probed, identified
> and configured by the MMC/SDIO subsystem, so toggling their power must
> take place from within the MMC/SDIO subsystem itself.
>
> Until recently, MMC/SDIO cards were kept powered on from the moment
> they were inserted, up until they were removed (exception: power was
> removed on system suspend and brought up back on resume. there is an
> exception to this exception, too, but I won't get into that now).
>
> Recently, we have added runtime PM support to the MMC/SDIO subsystem,
> so cards can be powered down when they're not in use. E.g., an SDIO
> card is powered down if no driver is available or requires power to
> it, and an MMC card might be powered off after some period of
> inactivity (the latter is just being discussed and has not yet hit
> mainline).
>
> As far as the MMC/SDIO subsystem is concerned, this is merely a power
> optimization, and it's perfectly fine if the user will disable runtime
> PM for the card and by that disallow powering it down.
>
> But for our particular device this is fatal; as explained, the driver
> must have unconditional control of the device's power.
>
> So we need runtime PM at the subsystem level (to allow the MMC/SDIO
> subsystem power it off in case the driver is not loaded), but we will
> have no choice but bypass runtime PM at the driver level, in order to
> avoid the aforementioned suspend race, and a potential
> /sys/devices/.../power/control block.
That all makes sense, and there's nothing wrong with it. (Except that
I still don't know what suspend race you mean.)
> To maintain coherency with the runtime-PM's usage_count
It's not necessary to maintain usage_count while you're bypassing
runtime PM. Just make sure when you're done that everything is back in
sync.
For example, the USB subsystem bypasses runtime PM for interface
drivers; the interface driver is told to suspend at the time the
interface's parent device driver suspends. This means it's possible to
see that an interface's runtime PM status is RPM_SUSPENDED even though
the interface driver's suspend method hasn't been called. In the end
it all works out okay.
> (and by that
> prevent dpm_complete() from powering off our device after a system
> resume)
Why shouldn't dpm_complete cause the device to be powered down
(assuming the device isn't in use, of course)?
> we will also keep calling the pm_runtime_{get, put} API
> appropriately.
>
> It's not pretty, but this is the only way we can make this work
> (unless, of course, our use case will be supported within the
> runtime-PM framework itself).
It doesn't sound any less pretty than the situation in USB, so you
shouldn't be too concerned about the aesthetics. :-)
Alan Stern
^ permalink raw reply
* [PATCH] ath9k: fix spur mitigation no-spur case for AR9002
From: Brian Prodoehl @ 2010-12-25 19:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, mcgrof
For the AR9002, the spur frequency read from the EEPROM is mangled
before being compared against AR_NO_SPUR. This results in the driver
trying to set up the spur mitigation for bogus spurs, rather than
cleanly breaking out.
Signed-off-by: Brian Prodoehl <bprodoehl@nomadio.net>
---
drivers/net/wireless/ath/ath9k/ar9002_phy.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index 7ae66a8..7d68d61 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -203,13 +203,14 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+ if (AR_NO_SPUR == cur_bb_spur)
+ break;
+
if (is2GHz)
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
else
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
- if (AR_NO_SPUR == cur_bb_spur)
- break;
cur_bb_spur = cur_bb_spur - freq;
if (IS_CHAN_HT40(chan)) {
^ permalink raw reply related
* Compat-wireless release for 2010-12-25 is baked
From: Compat-wireless cronjob account @ 2010-12-25 20:02 UTC (permalink / raw)
To: linux-wireless
compat-wireless code metrics
777174 - Total upstream lines of code being pulled
2223 - backport code changes
1946 - backport code additions
277 - backport code deletions
6648 - backport from compat module
8871 - total backport code
1.1414 - % of code consists of backport work
1532 - Crap changes not yet posted
1489 - Crap additions not yet posted
43 - Crap deletions not yet posted
0.1971 - % of crap code
Base tree: linux-next.git
Base tree version: next-20101221
compat-wireless release: compat-wireless-2010-12-20-1-g53f8e22-pc
^ permalink raw reply
* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Ohad Ben-Cohen @ 2010-12-25 20:58 UTC (permalink / raw)
To: Alan Stern
Cc: Rafael J. Wysocki, linux-pm, Johannes Berg, linux-wireless,
linux-mmc, Ido Yariv, Kevin Hilman
In-Reply-To: <Pine.LNX.4.44L0.1012251046060.5079-100000@netrider.rowland.org>
On Sat, Dec 25, 2010 at 6:21 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> Right. You may or may not realize it, but this requirement means that
> the driver _must_ bypass runtime PM sometimes.
http://www.spinics.net/lists/linux-pm/msg22864.html
> Now you've lost me. Which of the driver's handlers are you talking
> about?
The driver's handler, which is called by mac80211, and is responsible
to power off the device.
The _same_ handler is being called either during runtime or during a
system transition to suspend
> What races?
Driver thinks power is off and device is now fully reset, but it's isn't really
> Why does the driver have to _assume_ the device was powered off -- why
> doesn't it simply _do_ the power down?
runtime PM is disabled during suspend. and the driver doesn't know
that the system is suspending, and it is using pm_runtime_put_sync().
It's the same code that executes during runtime and while system is
suspending
Even if we changed mac80211 to tell us the system is suspending, so we
would power off the device directly in this case, it won't solve all
of our problems, because even during runtime we need to bypass runtime
PM due to /sys/devices/.../power/control.
> Maybe it would help if you provided a list of the relevant subroutines
> together with descriptions of the circumstances under which they are
> called and what they are expected to do. For example, a brief
> pseudo-code listing.
Frankly, I don't think it's worth it.
We're just a single use case and Rafael already said he won't support it.
> It's not necessary to maintain usage_count while you're bypassing
> runtime PM. Just make sure when you're done that everything is back in
> sync.
I think you are missing the fact that we will have to bypass runtime
PM also during runtime, and not only in suspend/resume, and that's due
to /sys/devices/.../power/control.
That's why we will also have to maintain usage_count - to prevent
dpm_complete() from powering the device down, when it is really up.
> Why shouldn't dpm_complete cause the device to be powered down
> (assuming the device isn't in use, of course)?
Because it _is_ in use
^ permalink raw reply
* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Vitaly Wool @ 2010-12-25 21:50 UTC (permalink / raw)
To: Ohad Ben-Cohen
Cc: Alan Stern, linux-wireless, linux-mmc, Ido Yariv, linux-pm,
Johannes Berg
In-Reply-To: <AANLkTimj0E3Rz_8WQrU4wGg3ONyXzkUT9+U3Xqz7Cq0X@mail.gmail.com>
Hi Ohad,
On Sat, Dec 25, 2010 at 9:58 PM, Ohad Ben-Cohen <ohad@wizery.com> wrote:
> On Sat, Dec 25, 2010 at 6:21 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
>> Right. You may or may not realize it, but this requirement means that
>> the driver _must_ bypass runtime PM sometimes.
>
> http://www.spinics.net/lists/linux-pm/msg22864.html
>
>> Now you've lost me. Which of the driver's handlers are you talking
>> about?
>
> The driver's handler, which is called by mac80211, and is responsible
> to power off the device.
> The _same_ handler is being called either during runtime or during a
> system transition to suspend
>
>> What races?
>
> Driver thinks power is off and device is now fully reset, but it's isn't really
maybe it's worth starting off with the description of chip power
states and how they are mapped to runtime PM and static PM?
Most of the WLAN chips have some very low power modes, but you're
talking about _complete_ shutdown as a suspended state for both
runtime PM and static PM, is that correct?
Thanks,
Vitaly
^ permalink raw reply
* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Vitaly Wool @ 2010-12-25 21:54 UTC (permalink / raw)
To: Ohad Ben-Cohen
Cc: Alan Stern, linux-wireless, linux-mmc, Ido Yariv, linux-pm,
Johannes Berg
In-Reply-To: <AANLkTimj0E3Rz_8WQrU4wGg3ONyXzkUT9+U3Xqz7Cq0X@mail.gmail.com>
Hi Ohad,
On Sat, Dec 25, 2010 at 9:58 PM, Ohad Ben-Cohen <ohad@wizery.com> wrote:
> On Sat, Dec 25, 2010 at 6:21 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
>> Right. You may or may not realize it, but this requirement means that
>> the driver _must_ bypass runtime PM sometimes.
>
> http://www.spinics.net/lists/linux-pm/msg22864.html
>
>> Now you've lost me. Which of the driver's handlers are you talking
>> about?
>
> The driver's handler, which is called by mac80211, and is responsible
> to power off the device.
> The _same_ handler is being called either during runtime or during a
> system transition to suspend
>
>> What races?
>
> Driver thinks power is off and device is now fully reset, but it's isn't really
maybe it's worth starting off with the description of chip power
states and how they are mapped to runtime PM and static PM?
Most of the WLAN chips have some very low power modes, but you're
talking about _complete_ shutdown as a suspended state for both
runtime PM and static PM, is that correct?
Thanks,
Vitaly
^ permalink raw reply
* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Alan Stern @ 2010-12-26 2:48 UTC (permalink / raw)
To: Ohad Ben-Cohen
Cc: Rafael J. Wysocki, linux-pm, Johannes Berg, linux-wireless,
linux-mmc, Ido Yariv, Kevin Hilman
In-Reply-To: <AANLkTimj0E3Rz_8WQrU4wGg3ONyXzkUT9+U3Xqz7Cq0X@mail.gmail.com>
On Sat, 25 Dec 2010, Ohad Ben-Cohen wrote:
> On Sat, Dec 25, 2010 at 6:21 PM, Alan Stern <stern@rowland.harvard.edu> wrote:
> > Right. You may or may not realize it, but this requirement means that
> > the driver _must_ bypass runtime PM sometimes.
>
> http://www.spinics.net/lists/linux-pm/msg22864.html
>
> > Now you've lost me. Which of the driver's handlers are you talking
> > about?
>
> The driver's handler, which is called by mac80211, and is responsible
> to power off the device.
> The _same_ handler is being called either during runtime or during a
> system transition to suspend
Is there a separate handler responsible for powering the device back
on? What are the names of these handlers?
> > What races?
>
> Driver thinks power is off and device is now fully reset, but it's isn't really
That's not a race; it's just a misunderstanding. A race is when you
have two threads of control executing concurrently and either one can
end up carrying out some action first.
> > Why does the driver have to _assume_ the device was powered off -- why
> > doesn't it simply _do_ the power down?
>
> runtime PM is disabled during suspend. and the driver doesn't know
> that the system is suspending, and it is using pm_runtime_put_sync().
What is the name of the routine that calls pm_runtime_put_sync()?
What is the name of the driver's runtime_suspend routine? Is either of
them the same as the handler you mentioned above? And while we're at
it, what is the name of the routine that _actually_ changes the
device's power level?
It's very difficult to talk about different pieces of code without
knowing their names.
> It's the same code that executes during runtime and while system is
> suspending
Okay, there's nothing wrong with that. But the code that runs during
system suspend should not call pm_runtime_put_sync().
> Even if we changed mac80211 to tell us the system is suspending, so we
> would power off the device directly in this case, it won't solve all
> of our problems, because even during runtime we need to bypass runtime
> PM due to /sys/devices/.../power/control.
Evidently you are facing two distinct problems, and they need to be
solved together. In fact, solving one problem (bypassing runtime PM)
will probably help to solve the other (doing system resume correctly).
> > Maybe it would help if you provided a list of the relevant subroutines
> > together with descriptions of the circumstances under which they are
> > called and what they are expected to do. For example, a brief
> > pseudo-code listing.
>
> Frankly, I don't think it's worth it.
>
> We're just a single use case and Rafael already said he won't support it.
Well, I'd like to help you find the best solution, but I can't because
I don't understand how the subsystem and driver are structured, and you
aren't providing enough details. We won't make any further progress on
this unless you abandon the incomplete high-level overviews and instead
give a more or less complete lower-level description -- including the
subroutine names!
> > It's not necessary to maintain usage_count while you're bypassing
> > runtime PM. Just make sure when you're done that everything is back in
> > sync.
>
> I think you are missing the fact that we will have to bypass runtime
> PM also during runtime, and not only in suspend/resume, and that's due
> to /sys/devices/.../power/control.
No, I realize that.
> That's why we will also have to maintain usage_count - to prevent
> dpm_complete() from powering the device down, when it is really up.
When else should dpm_complete() power the device down? You certainly
don't want to power the device down when it is already down! :-)
Maybe you mean that you want to prevent dpm_complete() from powering
the device down while it is in use. That should never be a problem --
the device should never be used without the PM core being aware. The
unusual cases you have described all involve powering the device down
at times when it is supposed to be in use (e.g., in order to do a
reset). If you do these power-downs directly instead of trying to use
runtime PM, then the PM core will never think the device is idle when
it really is being used.
Ultimately it boils down to this. You have several possible reasons
for powering-down the device: runtime PM, system sleep, and reset (or
other similar driver-specific things). Presumably the reset case
occurs only while the device is in use, and with sufficient locking to
prevent the driver from trying to access the device while the reset is
in progress.
Therefore you need to have a single routine that actually powers-down
the device, and you need to call this routine in different settings:
during system sleep or runtime suspend (the same code in the driver
handles these two cases, right?) and when a reset is needed.
Alan Stern
^ permalink raw reply
* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Ohad Ben-Cohen @ 2010-12-26 5:27 UTC (permalink / raw)
To: Vitaly Wool
Cc: Alan Stern, linux-wireless, linux-mmc, Ido Yariv, linux-pm,
Johannes Berg
In-Reply-To: <AANLkTikcTSgjdxR106H2XZdmepN40bTKfEgmP04OQAz3@mail.gmail.com>
On Sat, Dec 25, 2010 at 11:50 PM, Vitaly Wool <vitalywool@gmail.com> wrote:
> you're talking about _complete_ shutdown as a suspended state for both
> runtime PM and static PM, is that correct?
Exactly.
This is the power of the card as seen by the MMC/SDIO subsystem.
^ permalink raw reply
* Re: [linux-pm] subtle pm_runtime_put_sync race and sdio functions
From: Ohad Ben-Cohen @ 2010-12-26 5:55 UTC (permalink / raw)
To: Alan Stern
Cc: Rafael J. Wysocki, linux-pm, Johannes Berg, linux-wireless,
linux-mmc, Ido Yariv, Kevin Hilman
In-Reply-To: <Pine.LNX.4.44L0.1012252041260.10725-100000@netrider.rowland.org>
On Sun, Dec 26, 2010 at 4:48 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> Is there a separate handler responsible for powering the device back
> on? What are the names of these handlers?
wl1271_sdio_power_on() and wl1271_sdio_power_off().
If you're taking a look, please do so using the latest code as seen on mmc-next:
git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git mmc-next
> That's not a race
It is.
If system suspend will continue uninterruptedly, and the driver will
be suspended (by the SDIO subsystem), then the device will be powered
down, and everything will work.
But if something will interrupt the suspend transition _before_ our
driver is suspended (e.g. some other suspend() handler will fail),
then we have a problem, because the device will not be reset as the
driver needs it to be.
> What is the name of the driver's runtime_suspend routine?
The driver itself doesn't have one; power is being controlled by the
MMC/SDIO subsystem, so the actual runtime_suspend handler is
mmc_runtime_suspend().
> And while we're at it, what is the name of the routine that _actually_ changes the
> device's power level?
mmc_power_save_host(), which is called by mmc_runtime_suspend().
(well, more accurately it is actually fixed_voltage_disable(), but
that's a few levels deeper than I think you'll be interested in)
> Evidently you are facing two distinct problems, and they need to be
> solved together. In fact, solving one problem (bypassing runtime PM)
> will probably help to solve the other (doing system resume correctly).
I agree.
> Well, I'd like to help you find the best solution, but I can't because
> I don't understand how the subsystem and driver are structured, and you
> aren't providing enough details. We won't make any further progress on
> this unless you abandon the incomplete high-level overviews and instead
> give a more or less complete lower-level description -- including the
> subroutine names!
In fact, I'd appreciate if we can abandon the high-level discussions too :)
I have provided pointers to the actual code, please tell me if you're
interested in any other parts or have questions about it.
> Maybe you mean that you want to prevent dpm_complete() from powering
> the device down while it is in use.
Yes.
> That should never be a problem --
> the device should never be used without the PM core being aware.
That's why I said we will have to both directly manipulate the power
of the device, and also maintain usage_count.
> Therefore you need to have a single routine that actually powers-down
> the device, and you need to call this routine in different settings:
> during system sleep or runtime suspend (the same code in the driver
> handles these two cases, right?) and when a reset is needed.
Yes. and sometimes also just because the user turned wlan off.
Thanks,
Ohad.
^ permalink raw reply
* [PATCH] wl12xx: don't join upon disassociation
From: Eliad Peller @ 2010-12-26 8:27 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
wl12xx "rejoins" upon every BSS_CHANGED_BSSID notification.
However, there is no need to rejoin after disassociation, so just
filter out the case when the new bssid is 00:00:00:00:00:00.
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
drivers/net/wireless/wl12xx/main.c | 24 ++++++++++++++----------
1 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 062247e..7aa783c 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1944,19 +1944,23 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
- ret = wl1271_cmd_build_null_data(wl);
- if (ret < 0)
- goto out_sleep;
+ if (!is_zero_ether_addr(wl->bssid)) {
+ ret = wl1271_cmd_build_null_data(wl);
+ if (ret < 0)
+ goto out_sleep;
- ret = wl1271_build_qos_null_data(wl);
- if (ret < 0)
- goto out_sleep;
+ ret = wl1271_build_qos_null_data(wl);
+ if (ret < 0)
+ goto out_sleep;
- /* filter out all packets not from this BSSID */
- wl1271_configure_filters(wl, 0);
+ /* filter out all packets not from this BSSID */
+ wl1271_configure_filters(wl, 0);
- /* Need to update the BSSID (for filtering etc) */
- do_join = true;
+ /*
+ * Need to update the BSSID (for filtering etc)
+ */
+ do_join = true;
+ }
}
if (changed & BSS_CHANGED_ASSOC) {
--
1.7.0.4
^ permalink raw reply related
* [RFC PATCH 0/6] zd1211rw: add support for AP mode
From: Jussi Kivilinna @ 2010-12-26 11:24 UTC (permalink / raw)
To: linux-wireless; +Cc: Daniel Drake, zd1211-devs, Ulrich Kunitz
Hello!
This patchset adds AP mode to zd1211rw. I have done this with vendor driver
as reference and in most parts everything appears ok. Unencrypted AP and
WEP appears to work without issues, driver can switch back to station mode
without problems.
Now current problems are:
1. I have not been able to trigger bc/mc buffering. I have tested with
b43 and rndis_wlan stations.
2. When connecting with b43 to WPA enabled AP (hostapd 0.7.3), I get lots of:
wlan2: STA 00:xx:xx:xx:xx:xx IEEE 802.1X: unauthorizing port
wlan2: STA 00:xx:xx:xx:xx:xx IEEE 802.11: deauthenticated
and then after ~1-2 minutes of retrying finally it makes connection.
With rndis_wlan, no problems.
Either I have hostapd config error (first time using hostapd), or
something is wrong with driver.
^ permalink raw reply
* [RFC PATCH 1/6] zd1211rw: fix beacon interval setup
From: Jussi Kivilinna @ 2010-12-26 11:24 UTC (permalink / raw)
To: linux-wireless; +Cc: Daniel Drake, zd1211-devs, Ulrich Kunitz
In-Reply-To: <20101226112404.31775.77854.stgit@fate.lan>
Vendor driver uses CR_BNC_INTERVAL at various places, one is HW_EnableBeacon()
that combinies beacon interval with BSS-type flag and DTIM value in upper
16bit of u32. The other one is HW_UpdateBcnInterval() that set_aw_pt_bi()
appears to be based on. HW_UpdateBcnInterval() takes interval argument as u16
and uses that for calculations, set_aw_pt_bi() uses u32 value that has flags
and dtim in upper part. This clearly seems wrong. Also HW_UpdateBcnInterval()
updates only lower 16bit part of CR_BNC_INTERVAL.
So make set_aw_pt_bi() do calculations on only lower u16 part of
s->beacon_interval.
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
drivers/net/wireless/zd1211rw/zd_chip.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 30f8d40..f21cd7e 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -849,10 +849,12 @@ static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
{
struct zd_ioreq32 reqs[3];
- if (s->beacon_interval <= 5)
- s->beacon_interval = 5;
+ if ((s->beacon_interval & 0xffff) <= 5) {
+ s->beacon_interval &= ~0xffff;
+ s->beacon_interval |= 5;
+ }
if (s->pre_tbtt < 4 || s->pre_tbtt >= s->beacon_interval)
- s->pre_tbtt = s->beacon_interval - 1;
+ s->pre_tbtt = (s->beacon_interval & 0xffff) - 1;
if (s->atim_wnd_period >= s->pre_tbtt)
s->atim_wnd_period = s->pre_tbtt - 1;
^ permalink raw reply related
* [RFC PATCH 2/6] zd1211rw: support setting BSSID for AP mode
From: Jussi Kivilinna @ 2010-12-26 11:24 UTC (permalink / raw)
To: linux-wireless; +Cc: Daniel Drake, zd1211-devs, Ulrich Kunitz
In-Reply-To: <20101226112404.31775.77854.stgit@fate.lan>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
drivers/net/wireless/zd1211rw/zd_chip.c | 39 +++++++++++++++++++++++--------
drivers/net/wireless/zd1211rw/zd_chip.h | 1 +
drivers/net/wireless/zd1211rw/zd_mac.c | 25 +++++++++++++++++++-
drivers/net/wireless/zd1211rw/zd_mac.h | 1 +
4 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index f21cd7e..91bf8bc 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -369,16 +369,12 @@ error:
return r;
}
-/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
- * CR_MAC_ADDR_P2 must be overwritten
- */
-int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+static int zd_write_mac_addr_common(struct zd_chip *chip, const u8 *mac_addr,
+ const struct zd_ioreq32 *in_reqs,
+ const char *type)
{
int r;
- struct zd_ioreq32 reqs[2] = {
- [0] = { .addr = CR_MAC_ADDR_P1 },
- [1] = { .addr = CR_MAC_ADDR_P2 },
- };
+ struct zd_ioreq32 reqs[2] = {in_reqs[0], in_reqs[1]};
if (mac_addr) {
reqs[0].value = (mac_addr[3] << 24)
@@ -387,9 +383,9 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
| mac_addr[0];
reqs[1].value = (mac_addr[5] << 8)
| mac_addr[4];
- dev_dbg_f(zd_chip_dev(chip), "mac addr %pM\n", mac_addr);
+ dev_dbg_f(zd_chip_dev(chip), "%s addr %pM\n", type, mac_addr);
} else {
- dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n");
+ dev_dbg_f(zd_chip_dev(chip), "set NULL %s\n", type);
}
mutex_lock(&chip->mutex);
@@ -398,6 +394,29 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
return r;
}
+/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
+ * CR_MAC_ADDR_P2 must be overwritten
+ */
+int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+{
+ static const struct zd_ioreq32 reqs[2] = {
+ [0] = { .addr = CR_MAC_ADDR_P1 },
+ [1] = { .addr = CR_MAC_ADDR_P2 },
+ };
+
+ return zd_write_mac_addr_common(chip, mac_addr, reqs, "mac");
+}
+
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
+{
+ static const struct zd_ioreq32 reqs[2] = {
+ [0] = { .addr = CR_BSSID_P1 },
+ [1] = { .addr = CR_BSSID_P2 },
+ };
+
+ return zd_write_mac_addr_common(chip, bssid, reqs, "bssid");
+}
+
int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
{
int r;
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index f8bbf7d..7b0c58c 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -881,6 +881,7 @@ static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
u8 zd_chip_get_channel(struct zd_chip *chip);
int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid);
int zd_chip_switch_radio_on(struct zd_chip *chip);
int zd_chip_switch_radio_off(struct zd_chip *chip);
int zd_chip_enable_int(struct zd_chip *chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 43307bd..d3f454b 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -231,6 +231,26 @@ static int set_rx_filter(struct zd_mac *mac)
return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
}
+static int set_mac_and_bssid(struct zd_mac *mac)
+{
+ int r;
+
+ if (!mac->vif)
+ return -1;
+
+ r = zd_write_mac_addr(&mac->chip, mac->vif->addr);
+ if (r)
+ return r;
+
+ /* Vendor driver after setting MAC either sets BSSID for AP or
+ * filter for other modes.
+ */
+ if (mac->type != NL80211_IFTYPE_AP)
+ return set_rx_filter(mac);
+ else
+ return zd_write_bssid(&mac->chip, mac->vif->addr);
+}
+
static int set_mc_hash(struct zd_mac *mac)
{
struct zd_mc_hash hash;
@@ -888,7 +908,9 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
return -EOPNOTSUPP;
}
- return zd_write_mac_addr(&mac->chip, vif->addr);
+ mac->vif = vif;
+
+ return set_mac_and_bssid(mac);
}
static void zd_op_remove_interface(struct ieee80211_hw *hw,
@@ -896,6 +918,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
{
struct zd_mac *mac = zd_hw_mac(hw);
mac->type = NL80211_IFTYPE_UNSPECIFIED;
+ mac->vif = NULL;
zd_set_beacon_interval(&mac->chip, 0);
zd_write_mac_addr(&mac->chip, NULL);
}
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index a6d86b9..92dd071 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -172,6 +172,7 @@ struct zd_mac {
spinlock_t lock;
spinlock_t intr_lock;
struct ieee80211_hw *hw;
+ struct ieee80211_vif *vif;
struct housekeeping housekeeping;
struct work_struct set_multicast_hash_work;
struct work_struct set_rts_cts_work;
^ permalink raw reply related
* [RFC PATCH 3/6] zd1211rw: let zd_set_beacon_interval() set dtim_period and add AP-beacon flag
From: Jussi Kivilinna @ 2010-12-26 11:24 UTC (permalink / raw)
To: linux-wireless; +Cc: Daniel Drake, zd1211-devs, Ulrich Kunitz
In-Reply-To: <20101226112404.31775.77854.stgit@fate.lan>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
drivers/net/wireless/zd1211rw/zd_chip.c | 11 ++++++-----
drivers/net/wireless/zd1211rw/zd_chip.h | 3 ++-
drivers/net/wireless/zd1211rw/zd_mac.c | 22 +++++++++++++---------
3 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 91bf8bc..fdbf6ea 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -888,7 +888,8 @@ static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
}
-static int set_beacon_interval(struct zd_chip *chip, u32 interval)
+static int set_beacon_interval(struct zd_chip *chip, u32 interval,
+ u16 dtim_period)
{
int r;
struct aw_pt_bi s;
@@ -897,16 +898,16 @@ static int set_beacon_interval(struct zd_chip *chip, u32 interval)
r = get_aw_pt_bi(chip, &s);
if (r)
return r;
- s.beacon_interval = interval;
+ s.beacon_interval = interval | (dtim_period << 16);
return set_aw_pt_bi(chip, &s);
}
-int zd_set_beacon_interval(struct zd_chip *chip, u32 interval)
+int zd_set_beacon_interval(struct zd_chip *chip, u32 interval, u16 dtim_period)
{
int r;
mutex_lock(&chip->mutex);
- r = set_beacon_interval(chip, interval);
+ r = set_beacon_interval(chip, interval, dtim_period);
mutex_unlock(&chip->mutex);
return r;
}
@@ -925,7 +926,7 @@ static int hw_init(struct zd_chip *chip)
if (r)
return r;
- return set_beacon_interval(chip, 100);
+ return set_beacon_interval(chip, 100, 0);
}
static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 7b0c58c..1e791ba 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -546,6 +546,7 @@ enum {
#define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
RX_FILTER_CFEND | RX_FILTER_CFACK)
+#define BCN_MODE_AP 0x1000000
#define BCN_MODE_IBSS 0x2000000
/* Monitor mode sets filter to 0xfffff */
@@ -921,7 +922,7 @@ enum led_status {
int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
-int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
+int zd_set_beacon_interval(struct zd_chip *chip, u32 interval, u16 dtim_period);
static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
{
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index d3f454b..71a7576 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -919,7 +919,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
struct zd_mac *mac = zd_hw_mac(hw);
mac->type = NL80211_IFTYPE_UNSPECIFIED;
mac->vif = NULL;
- zd_set_beacon_interval(&mac->chip, 0);
+ zd_set_beacon_interval(&mac->chip, 0, 0);
zd_write_mac_addr(&mac->chip, NULL);
}
@@ -1081,15 +1081,19 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
}
if (changes & BSS_CHANGED_BEACON_ENABLED) {
- u32 interval;
-
- if (bss_conf->enable_beacon)
- interval = BCN_MODE_IBSS |
- bss_conf->beacon_int;
- else
- interval = 0;
+ u32 interval = 0;
+ u16 period = 0;
+
+ if (bss_conf->enable_beacon) {
+ period = bss_conf->dtim_period;
+ interval = bss_conf->beacon_int;
+ if (mac->type == NL80211_IFTYPE_AP)
+ interval |= BCN_MODE_AP;
+ else
+ interval |= BCN_MODE_IBSS;
+ }
- zd_set_beacon_interval(&mac->chip, interval);
+ zd_set_beacon_interval(&mac->chip, interval, period);
}
} else
associated = is_valid_ether_addr(bss_conf->bssid);
^ permalink raw reply related
* [RFC PATCH 4/6] zd1211rw: implement seq_num for IEEE80211_TX_CTL_ASSIGN_SEQ
From: Jussi Kivilinna @ 2010-12-26 11:24 UTC (permalink / raw)
To: linux-wireless; +Cc: Daniel Drake, zd1211-devs, Ulrich Kunitz
In-Reply-To: <20101226112404.31775.77854.stgit@fate.lan>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
drivers/net/wireless/zd1211rw/zd_mac.c | 21 +++++++++++++++++++++
drivers/net/wireless/zd1211rw/zd_mac.h | 3 +++
2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 71a7576..9f755fc 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -654,6 +654,24 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
(full_len << 19));
}
+static void create_tx_desc_seq(struct zd_mac *mac, struct ieee80211_hdr *hdr,
+ struct ieee80211_tx_info *info)
+{
+ unsigned long irqflags;
+
+ if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
+ return;
+
+ spin_lock_irqsave(&mac->seqlock, irqflags);
+
+ if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+ mac->seqno += 0x10;
+ hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+ hdr->seq_ctrl |= cpu_to_le16(mac->seqno);
+
+ spin_unlock_irqrestore(&mac->seqlock, irqflags);
+}
+
static int fill_ctrlset(struct zd_mac *mac,
struct sk_buff *skb)
{
@@ -678,6 +696,8 @@ static int fill_ctrlset(struct zd_mac *mac,
cs_set_control(mac, cs, hdr, info);
+ create_tx_desc_seq(mac, hdr, info);
+
packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
ZD_ASSERT(packet_length <= 0xffff);
/* ZD1211B: Computing the length difference this way, gives us
@@ -1151,6 +1171,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
memset(mac, 0, sizeof(*mac));
spin_lock_init(&mac->lock);
+ spin_lock_init(&mac->seqlock);
mac->hw = hw;
mac->type = NL80211_IFTYPE_UNSPECIFIED;
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index 92dd071..929bef9 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -189,6 +189,9 @@ struct zd_mac {
struct ieee80211_rate rates[12];
struct ieee80211_supported_band band;
+ spinlock_t seqlock;
+ u16 seqno;
+
/* Short preamble (used for RTS/CTS) */
unsigned int short_preamble:1;
^ permalink raw reply related
* [RFC PATCH 5/6] zd1211rw: implement beacon fetching and handling ieee80211_get_buffered_bc()
From: Jussi Kivilinna @ 2010-12-26 11:24 UTC (permalink / raw)
To: linux-wireless; +Cc: Daniel Drake, zd1211-devs, Ulrich Kunitz
In-Reply-To: <20101226112404.31775.77854.stgit@fate.lan>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
drivers/net/wireless/zd1211rw/zd_mac.c | 38 +++++++++++++++++++++++++++++---
1 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 9f755fc..2489c97 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -951,15 +951,46 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
}
+static void zd_beacon_done(struct zd_mac *mac)
+{
+ struct sk_buff *skb, *beacon;
+
+ if (mac->vif || mac->vif->type == NL80211_IFTYPE_UNSPECIFIED)
+ return;
+
+ /*
+ * Send out buffered broad- and multicast frames.
+ */
+ if (mac->vif->type == NL80211_IFTYPE_AP) {
+ dev_dbg_f_limit(zd_mac_dev(mac), "buffered_bc tx\n");
+ skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
+ while (skb) {
+ zd_op_tx(mac->hw, skb);
+ skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
+ }
+ }
+
+ /*
+ * Fetch next beacon so that tim_count is updated.
+ */
+ beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+ if (!beacon)
+ return;
+
+ zd_mac_config_beacon(mac->hw, beacon);
+ kfree_skb(beacon);
+}
+
static void zd_process_intr(struct work_struct *work)
{
u16 int_status;
struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer+4));
- if (int_status & INT_CFG_NEXT_BCN)
+ if (int_status & INT_CFG_NEXT_BCN) {
dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
- else
+ zd_beacon_done(mac);
+ } else
dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
zd_chip_enable_hwint(&mac->chip);
@@ -1186,7 +1217,8 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_SIGNAL_UNSPEC;
+ IEEE80211_HW_SIGNAL_UNSPEC |
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_MESH_POINT) |
^ permalink raw reply related
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