linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support
       [not found] <804B13F8F3D94A4AB18B9B01ACB68FA1037B5158@EXCHSRV.fokus.fraunhofer.de>
@ 2010-07-27 17:20 ` Luis R. Rodriguez
       [not found]   ` <804B13F8F3D94A4AB18B9B01ACB68FA1037B526B@EXCHSRV.fokus.fraunhofer.de>
  2010-09-13 17:11   ` AW: " Simsek, Burak
  0 siblings, 2 replies; 7+ messages in thread
From: Luis R. Rodriguez @ 2010-07-27 17:20 UTC (permalink / raw)
  To: Simsek, Burak; +Cc: Luis Rodriguez, linux-wireless

On Tue, Jul 27, 2010 at 08:12:10AM -0700, Simsek, Burak wrote:
> Dear Luis,
>
> I have found out that you have worked on WoW for ath9k for a while. However,
> in the wiki page of wireless.kernel.org the current state is written as
> ongoing work. Can you please tell me whether you were successful while
> implementing WoW. Is there anything that we could use?

WoW worked for me but inconsistantly and at the time of writing
the patches I had to do quite a lot of coordination with Johannes
since he had a lot of API changes and his changes needed to get
merged first.

I also found quite a few issues in mac80211 back then but I believe
we have resolved all of them by now so I would expect that if the
same WoW-only patches to be rebased and tested we may get better
results.

I stopped working on the WoW stuff due to lack of time to keep
testing them but the last series can be edited to remove all
of the already merged stuff and test out the new stuff. The more
challenging thing for me was to actually get a WoW enabled
802.11 card, these are not as popular as you would hope. The
EEPROM would be modified when WoW is enabled but WoW requires
some actual hardware mucking to allow for the PCI Wake signal
which is typically blocked off. If the EEPROM has WoW enabled
then the hardware mucking would have been done.

To test WoW you also need to drop Network Manager and use
the supplicant directly so that during suspend you remain
associated. I should note that WoW will only work on
non-WPA networks with ath9k due to the lack of
hardware CPU, during suspend there is only power for the
802.11 hardware, the CPU on your box would be asleep but
would be required for group key changes. The way I was thinking
of doing this was to only enable WoW through cfg80211 for ath9k if
and only if you are associated and you are connected to a non
WPA network.

WoW would work with encryption on our USB devices where
there is a CPU though.

You can find my last series here:

http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/wow-07-21.patch
http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/iw-add-wow.patch

If you manage to do what I noted above, get an actual WoW enabled card,
and it works reliably I'd gladly welcome and ACK the patches :)

  Luis

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support
       [not found]   ` <804B13F8F3D94A4AB18B9B01ACB68FA1037B526B@EXCHSRV.fokus.fraunhofer.de>
@ 2010-07-29 15:31     ` Luis R. Rodriguez
  2010-07-29 20:56       ` Luis R. Rodriguez
  0 siblings, 1 reply; 7+ messages in thread
From: Luis R. Rodriguez @ 2010-07-29 15:31 UTC (permalink / raw)
  To: Simsek, Burak, David Quan, Amod Bodas, Stephen Chen, Christian Lamparter
  Cc: Luis Rodriguez, linux-wireless

On Thu, Jul 29, 2010 at 06:31:02AM -0700, Simsek, Burak wrote:
> Hi Luis,
> 
> we tried your patches on the old version as described in your patch file. 
> 
> As you wrote the first issue was about the getting the right hardware. We
> first wanted to use RS71-USB from ubiquity and it has AR9280. However, we
> then realized that the implementation was for pci. We had assumed that RS71
> would use ath9k but it used AR9170 driver. First question: do you think that
> we can do similar patch for usb without much effort?

Well, ar9170 uses Atheros radios but uses an old Zydas MAC so the programming
would be different and I am not sure if ar9170 ever supported WoW. Stephen
and Christian would know best at this point, whom I have CC'd.

> Then we tried it with DWA-547 from DLink (phy0: Atheros AR9280 MAC/BB Rev:2
> AR5133 RF Rev:d0: mem=0xf8720000, irq=16), which also has AR9280. This is
> the output we got:
> [    9.411217] ath9k: WoW capabler device: yes

Neat.

> [    9.411226] ath9k: EEPROM indicates WoW hw changes in place: no

Without this you won't get anywhere IIRC. This indicates that the card
was actually modified to enable the PCIE WAKE signal, by default all
Atheros devices have this wedged off.

> [    9.411234] ath9k: WoW exact match pattern support: no
> [    9.411241] ath9k: WoW match pattern first dword requirement: no
> 
> Now, regarding those EEPROM problems we will have difficulties. Were you
> able to get it running with a specific device? Can you recommend us
> something? 

Well I can see if we can get docs out to let developers enable WoW on
their own. This may take me some time to get and release.

I should note enabling WoW requires some hw mods and then an EEPROM change.
We cannot support allowing users to mod their EEPROMs at this point
but if you do mod the hardware it would be simple enough to just modify
the patch to not check for the EEPROM to enable WoW, as a starter.

Your other best bet is to purchase a laptop that has WoW enabled but
I unfortunately do not have a list of laptops/devices that have this
enabled.

> Our next step will be carrying the patch to the last version. Is there any
> kind of documentation which could help us dealing with EEPROM issues? 

The EEPROM will be informative for the patch, that's all, now you can
at least tell which cards have been moded or not, so now you just have
to either get a WoW card or mode your card for it. If you mod it yourself
you can then just disable the EEPROM check for testsing purposes (ie, patch
won't be accepted upstream without the EEPROM check, but you can keep
whatever you want on your end).

  Luis
> 
> Best regards
> 
> Burak Simsek
> 
> 
> 
> 
> 
> -----Original Message-----
> From: Luis R. Rodriguez [mailto:lrodriguez@atheros.com] 
> Sent: Dienstag, 27. Juli 2010 19:20
> To: Simsek, Burak
> Cc: Luis Rodriguez; linux-wireless@vger.kernel.org
> Subject: Re: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support
> 
> On Tue, Jul 27, 2010 at 08:12:10AM -0700, Simsek, Burak wrote:
> > Dear Luis,
> >
> > I have found out that you have worked on WoW for ath9k for a while.
> However,
> > in the wiki page of wireless.kernel.org the current state is written as
> > ongoing work. Can you please tell me whether you were successful while
> > implementing WoW. Is there anything that we could use?
> 
> WoW worked for me but inconsistantly and at the time of writing
> the patches I had to do quite a lot of coordination with Johannes
> since he had a lot of API changes and his changes needed to get
> merged first.
> 
> I also found quite a few issues in mac80211 back then but I believe
> we have resolved all of them by now so I would expect that if the
> same WoW-only patches to be rebased and tested we may get better
> results.
> 
> I stopped working on the WoW stuff due to lack of time to keep
> testing them but the last series can be edited to remove all
> of the already merged stuff and test out the new stuff. The more
> challenging thing for me was to actually get a WoW enabled
> 802.11 card, these are not as popular as you would hope. The
> EEPROM would be modified when WoW is enabled but WoW requires
> some actual hardware mucking to allow for the PCI Wake signal
> which is typically blocked off. If the EEPROM has WoW enabled
> then the hardware mucking would have been done.
> 
> To test WoW you also need to drop Network Manager and use
> the supplicant directly so that during suspend you remain
> associated. I should note that WoW will only work on
> non-WPA networks with ath9k due to the lack of
> hardware CPU, during suspend there is only power for the
> 802.11 hardware, the CPU on your box would be asleep but
> would be required for group key changes. The way I was thinking
> of doing this was to only enable WoW through cfg80211 for ath9k if
> and only if you are associated and you are connected to a non
> WPA network.
> 
> WoW would work with encryption on our USB devices where
> there is a CPU though.
> 
> You can find my last series here:
> 
> http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/wow-07-21.pa
> tch
> http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/iw-add-wow.p
> atch
> 
> If you manage to do what I noted above, get an actual WoW enabled card,
> and it works reliably I'd gladly welcome and ACK the patches :)
> 
>   Luis



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support
  2010-07-29 15:31     ` Luis R. Rodriguez
@ 2010-07-29 20:56       ` Luis R. Rodriguez
  0 siblings, 0 replies; 7+ messages in thread
From: Luis R. Rodriguez @ 2010-07-29 20:56 UTC (permalink / raw)
  To: Luis Rodriguez
  Cc: Simsek, Burak, David Quan, Amod Bodas, Stephen Chen,
	Christian Lamparter, linux-wireless

On Thu, Jul 29, 2010 at 08:31:17AM -0700, Luis Rodriguez wrote:
> On Thu, Jul 29, 2010 at 06:31:02AM -0700, Simsek, Burak wrote:
> > Hi Luis,
> > 
> > we tried your patches on the old version as described in your patch file. 
> > 
> > As you wrote the first issue was about the getting the right hardware. We
> > first wanted to use RS71-USB from ubiquity and it has AR9280. However, we
> > then realized that the implementation was for pci. We had assumed that RS71
> > would use ath9k but it used AR9170 driver. First question: do you think that
> > we can do similar patch for usb without much effort?
> 
> Well, ar9170 uses Atheros radios but uses an old Zydas MAC so the programming
> would be different and I am not sure if ar9170 ever supported WoW. Stephen
> and Christian would know best at this point, whom I have CC'd.

I checked and ar9170 does not support WoW in hardware but since the firmware is
open (GPLv2) a WoW solution might be possible through software. You'd just have
to implement it. May want to look at carl9170.

  Luis

^ permalink raw reply	[flat|nested] 7+ messages in thread

* AW: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support
  2010-07-27 17:20 ` [ath9k-devel] [PATCH 4/5] mac80211: add WoW support Luis R. Rodriguez
       [not found]   ` <804B13F8F3D94A4AB18B9B01ACB68FA1037B526B@EXCHSRV.fokus.fraunhofer.de>
@ 2010-09-13 17:11   ` Simsek, Burak
  2010-09-13 17:29     ` Luis R. Rodriguez
  1 sibling, 1 reply; 7+ messages in thread
From: Simsek, Burak @ 2010-09-13 17:11 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: Luis Rodriguez, linux-wireless

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

Dear Luis,

we are moving your patch to the latest version whenever we have the time to
do so... You had sent us two patch files:

http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/wow-07-21.pa
tch
http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/iw-add-wow.p
atch


The first one is successfully accomplished, but we have problems with the
second one. I am giving a summary of the errors that we get below. There are
files and variables defined in that patch that we cannot find anywhere and
do not know what they should do. Can you please provide us with some hints
regarding those errors?

best regards

Burak 

‘NL_CB_CUSTOM’ undeclared (first use in this function)	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 159
C/C++ Problem
‘NL_CB_VALID’ undeclared (first use in this function)	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 159
C/C++ Problem
‘NL_OK’ undeclared (first use in this function)	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 137
C/C++ Problem
‘NL_SKIP’ undeclared (first use in this function)	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 129
C/C++ Problem
‘stderr’ undeclared (first use in this function)	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 79	C/C++
Problem
errno.h: No such file or directory	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 21	C/C++
Problem
expected ‘)’ before ‘(’ token	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 162
C/C++ Problem
expected ‘)’ before string constant	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 95	C/C++
Problem
implicit declaration of function ‘fprintf’	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 79	C/C++
Problem
implicit declaration of function ‘genlmsg_attrdata’	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 123
C/C++ Problem
implicit declaration of function ‘genlmsg_attrlen’	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 124
C/C++ Problem
implicit declaration of function ‘nl_cb_set’	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 159
C/C++ Problem
implicit declaration of function ‘nla_get_u32’	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 132
C/C++ Problem
implicit declaration of function ‘nla_parse’	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 123
C/C++ Problem
implicit declaration of function ‘NLA_PUT_U32’	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 89	C/C++
Problem
implicit declaration of function ‘nlmsg_data’	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 119
C/C++ Problem
implicit declaration of function ‘printf’	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 128
C/C++ Problem
iw.h: No such file or directory	wow.c
/wireless-testing/drivers/net/wireless/ath/ath9k	line 32	C/C++
Problem



-----Ursprüngliche Nachricht-----
Von: Luis R. Rodriguez [mailto:lrodriguez@atheros.com] 
Gesendet: Dienstag, 27. Juli 2010 19:20
An: Simsek, Burak
Cc: Luis Rodriguez; linux-wireless@vger.kernel.org
Betreff: Re: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support

On Tue, Jul 27, 2010 at 08:12:10AM -0700, Simsek, Burak wrote:
> Dear Luis,
>
> I have found out that you have worked on WoW for ath9k for a while. 
> However, in the wiki page of wireless.kernel.org the current state is 
> written as ongoing work. Can you please tell me whether you were 
> successful while implementing WoW. Is there anything that we could use?

WoW worked for me but inconsistantly and at the time of writing the patches
I had to do quite a lot of coordination with Johannes since he had a lot of
API changes and his changes needed to get merged first.

I also found quite a few issues in mac80211 back then but I believe we have
resolved all of them by now so I would expect that if the same WoW-only
patches to be rebased and tested we may get better results.

I stopped working on the WoW stuff due to lack of time to keep testing them
but the last series can be edited to remove all of the already merged stuff
and test out the new stuff. The more challenging thing for me was to
actually get a WoW enabled
802.11 card, these are not as popular as you would hope. The EEPROM would be
modified when WoW is enabled but WoW requires some actual hardware mucking
to allow for the PCI Wake signal which is typically blocked off. If the
EEPROM has WoW enabled then the hardware mucking would have been done.

To test WoW you also need to drop Network Manager and use the supplicant
directly so that during suspend you remain associated. I should note that
WoW will only work on non-WPA networks with ath9k due to the lack of
hardware CPU, during suspend there is only power for the
802.11 hardware, the CPU on your box would be asleep but would be required
for group key changes. The way I was thinking of doing this was to only
enable WoW through cfg80211 for ath9k if and only if you are associated and
you are connected to a non WPA network.

WoW would work with encryption on our USB devices where there is a CPU
though.

You can find my last series here:

http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/wow-07-21.pa
tch
http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/iw-add-wow.p
atch

If you manage to do what I noted above, get an actual WoW enabled card, and
it works reliably I'd gladly welcome and ACK the patches :)

  Luis

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 7083 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support
  2010-09-13 17:11   ` AW: " Simsek, Burak
@ 2010-09-13 17:29     ` Luis R. Rodriguez
  2010-09-14  9:53       ` AW: " Simsek, Burak
  0 siblings, 1 reply; 7+ messages in thread
From: Luis R. Rodriguez @ 2010-09-13 17:29 UTC (permalink / raw)
  To: Simsek, Burak; +Cc: Luis Rodriguez, linux-wireless

On Mon, Sep 13, 2010 at 10:11 AM, Simsek, Burak
<burak.simsek@fokus.fraunhofer.de> wrote:
> Dear Luis,
>
> we are moving your patch to the latest version whenever we have the time to
> do so... You had sent us two patch files:
>
> http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/wow-07-21.pa
> tch
> http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/iw-add-wow.p
> atch
>
>
> The first one is successfully accomplished, but we have problems with the
> second one. I am giving a summary of the errors that we get below. There are
> files and variables defined in that patch that we cannot find anywhere and
> do not know what they should do. Can you please provide us with some hints
> regarding those errors?

The first one is the biggest chunk of work, I can take care of the
second one. Can you post the first patch so I can test?

BTW, I learned that we can test WoW in the community by using Apple
boxen, Apple devices seems to always have WoW capable 802.11 Atheros
chipsets. What are you using for your testing?

  Luis

^ permalink raw reply	[flat|nested] 7+ messages in thread

* AW: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support
  2010-09-13 17:29     ` Luis R. Rodriguez
@ 2010-09-14  9:53       ` Simsek, Burak
  2010-09-14 14:33         ` Luis R. Rodriguez
  0 siblings, 1 reply; 7+ messages in thread
From: Simsek, Burak @ 2010-09-14  9:53 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: Luis Rodriguez, linux-wireless


[-- Attachment #1.1: Type: text/plain, Size: 2199 bytes --]

Hi Luis,

so far we could not find any device that worked. We ordered new ones... Will let you know in case we get something working. 
Attached you can find two patch files. Since we could not get any device working yet, I am not sure whether the patch is prepared correctly. But all your previous changes (from the first patch file) should be in. And we did not get compilation errors. 

Apple is interesting. We might give it a try as well. I ordered 2 mini-pci cards from sparklan (http://www.sparklan.com/product.php?func=view&prod_id=63) and (http://www.oxfordtec.com/us/p127/SparkLAN-WMIA-199N-WLAN-802.11n-draft-wifi-%202.4/5Ghz-dual-band-3T/3R-Module-%28Atheros-AR9001-AR9160-XSPAN%29-Wireless-miniP%20CI-card/product_info.html ) that I hope support wow. 

Best regards

Burak Simsek

-----Ursprüngliche Nachricht-----
Von: mcgrof@gmail.com [mailto:mcgrof@gmail.com] Im Auftrag von Luis R. Rodriguez
Gesendet: Montag, 13. September 2010 19:29
An: Simsek, Burak
Cc: Luis Rodriguez; linux-wireless@vger.kernel.org
Betreff: Re: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support

On Mon, Sep 13, 2010 at 10:11 AM, Simsek, Burak <burak.simsek@fokus.fraunhofer.de> wrote:
> Dear Luis,
>
> we are moving your patch to the latest version whenever we have the 
> time to do so... You had sent us two patch files:
>
> http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/wow-07
> -21.pa
> tch
> http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/iw-add
> -wow.p
> atch
>
>
> The first one is successfully accomplished, but we have problems with 
> the second one. I am giving a summary of the errors that we get below. 
> There are files and variables defined in that patch that we cannot 
> find anywhere and do not know what they should do. Can you please 
> provide us with some hints regarding those errors?

The first one is the biggest chunk of work, I can take care of the second one. Can you post the first patch so I can test?

BTW, I learned that we can test WoW in the community by using Apple boxen, Apple devices seems to always have WoW capable 802.11 Atheros chipsets. What are you using for your testing?

  Luis


[-- Attachment #1.2: 0001-mac80211-add-WoW-support.patch --]
[-- Type: application/octet-stream, Size: 9965 bytes --]

>From 91e3f7f301103d7f65d1d997fe10849d4093cdcb Mon Sep 17 00:00:00 2001
From: Luis R. Rodriguez <lrodriguez@atheros.com>
Date: Tue, 12 May 2009 17:31:32 -0700
Subject: [PATCH 1/2] mac80211: add WoW support

If we're associated and have not already gone into PS mode
we ensure send a nullfunc frame before going to suspend. Upon
resume we ensure we restore PS mode if it was enabled and inform
the driver accordingly, also notify the AP we're awake.

WoW requires the radio to be left on during suspend, to do this
we inform drivers of the requested wow triggers on the mac80211
stop callback.

When using WoW we do not remove the interface for the device
we are using as a STA in mac80211.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: burak <burak@burak-desktop.(none)>
---
 drivers/net/wireless/adm8211.c              |    2 +-
 drivers/net/wireless/at76c50x-usb.c         |    3 ++-
 drivers/net/wireless/ath/ar9170/main.c      |    2 +-
 drivers/net/wireless/ath/ath9k/main.c       |    2 +-
 drivers/net/wireless/b43/main.c             |    2 +-
 drivers/net/wireless/b43legacy/main.c       |    2 +-
 drivers/net/wireless/iwlwifi/iwl-agn.c      |    2 +-
 drivers/net/wireless/iwlwifi/iwl3945-base.c |    2 +-
 drivers/net/wireless/libertas_tf/main.c     |    2 +-
 drivers/net/wireless/mac80211_hwsim.c       |    2 +-
 drivers/net/wireless/p54/main.c             |    2 +-
 drivers/net/wireless/rtl818x/rtl8180_dev.c  |    2 +-
 drivers/net/wireless/wl12xx/wl1251_main.c   |    2 +-
 drivers/net/wireless/zd1211rw/zd_mac.c      |    2 +-
 net/mac80211/debugfs.c                      |    4 ++--
 net/mac80211/driver-trace.h                 |    6 ++++--
 net/mac80211/main.c                         |    2 +-
 17 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index f9aa1bc..fcaa286 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1543,7 +1543,7 @@ fail:
 	return retval;
 }
 
-static void adm8211_stop(struct ieee80211_hw *dev)
+static void adm8211_stop(struct ieee80211_hw *dev, struct cfg80211_wow *wow)
 {
 	struct adm8211_priv *priv = dev->priv;
 
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 91c5f73..cbd93b1 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1826,7 +1826,8 @@ error:
 	return 0;
 }
 
-static void at76_mac80211_stop(struct ieee80211_hw *hw)
+static void at76_mac80211_stop(struct ieee80211_hw *hw,
+			       struct cfg80211_wow *wow)
 {
 	struct at76_priv *priv = hw->priv;
 
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 32bf79e..ce7cdb5 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -1136,7 +1136,7 @@ out:
 	return err;
 }
 
-static void ar9170_op_stop(struct ieee80211_hw *hw)
+static void ar9170_op_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct ar9170 *ar = hw->priv;
 	unsigned int i;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 1165f90..a57ead1 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1291,7 +1291,7 @@ exit:
 	return 0;
 }
 
-static void ath9k_stop(struct ieee80211_hw *hw)
+static void ath9k_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index a118652..7557533 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4512,7 +4512,7 @@ static int b43_op_start(struct ieee80211_hw *hw)
 	return err;
 }
 
-static void b43_op_stop(struct ieee80211_hw *hw)
+static void b43_op_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
 	struct b43_wldev *dev = wl->current_dev;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 67f18ec..e1422ae 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3459,7 +3459,7 @@ out_mutex_unlock:
 	return err;
 }
 
-static void b43legacy_op_stop(struct ieee80211_hw *hw)
+static void b43legacy_op_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
 	struct b43legacy_wldev *dev = wl->current_dev;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index ad0e67f..f962528 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3475,7 +3475,7 @@ out:
 	return 0;
 }
 
-static void iwl_mac_stop(struct ieee80211_hw *hw)
+static void iwl_mac_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct iwl_priv *priv = hw->priv;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 68e624a..f9549ef 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3220,7 +3220,7 @@ out_release_irq:
 	return ret;
 }
 
-static void iwl3945_mac_stop(struct ieee80211_hw *hw)
+static void iwl3945_mac_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct iwl_priv *priv = hw->priv;
 
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 5550755..3c4bf68 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -332,7 +332,7 @@ err_prog_firmware:
 	return ret;
 }
 
-static void lbtf_op_stop(struct ieee80211_hw *hw)
+static void lbtf_op_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct lbtf_private *priv = hw->priv;
 	unsigned long flags;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 92b486d..071229d 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -582,7 +582,7 @@ static int mac80211_hwsim_start(struct ieee80211_hw *hw)
 }
 
 
-static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
+static void mac80211_hwsim_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct mac80211_hwsim_data *data = hw->priv;
 	data->started = 0;
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 622d27b..360685f 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -199,7 +199,7 @@ out:
 	return err;
 }
 
-static void p54_stop(struct ieee80211_hw *dev)
+static void p54_stop(struct ieee80211_hw *dev, struct cfg80211_wow *wow)
 {
 	struct p54_common *priv = dev->priv;
 	int i;
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 05c6bad..540abda 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -650,7 +650,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
 	return ret;
 }
 
-static void rtl8180_stop(struct ieee80211_hw *dev)
+static void rtl8180_stop(struct ieee80211_hw *dev, struct cfg80211_wow *wow)
 {
 	struct rtl8180_priv *priv = dev->priv;
 	u8 reg;
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index faf221c..1bde702 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -452,7 +452,7 @@ out:
 	return ret;
 }
 
-static void wl1251_op_stop(struct ieee80211_hw *hw)
+static void wl1251_op_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct wl1251 *wl = hw->priv;
 
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 43307bd..237c9ee 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -286,7 +286,7 @@ out:
 	return r;
 }
 
-static void zd_op_stop(struct ieee80211_hw *hw)
+static void zd_op_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	struct zd_chip *chip = &mac->chip;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index e81ef4e..ec9c403 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -112,8 +112,8 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf,
 	struct ieee80211_local *local = file->private_data;
 
 	rtnl_lock();
-	__ieee80211_suspend(&local->hw);
-	__ieee80211_resume(&local->hw);
+	__ieee80211_suspend(&local->hw, NULL);
+	__ieee80211_resume(&local->hw, NULL);
 	rtnl_unlock();
 
 	return count;
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index f6f3d89..34c935a 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -95,16 +95,18 @@ TRACE_EVENT(drv_start,
 );
 
 TRACE_EVENT(drv_stop,
-	TP_PROTO(struct ieee80211_local *local),
+	TP_PROTO(struct ieee80211_local *local, struct cfg80211_wow *wow),
 
-	TP_ARGS(local),
+	TP_ARGS(local, wow),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
+		__field(u32, triggers_enabled)
 	),
 
 	TP_fast_assign(
 		LOCAL_ASSIGN;
+		__entry->triggers_enabled = wow->triggers_enabled;
 	),
 
 	TP_printk(
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 4935b84..3333491 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -295,7 +295,7 @@ static void ieee80211_restart_work(struct work_struct *work)
 		container_of(work, struct ieee80211_local, restart_work);
 
 	rtnl_lock();
-	ieee80211_reconfig(local);
+	ieee80211_reconfig(local, NULL);
 	rtnl_unlock();
 }
 
-- 
1.7.0.4


[-- Attachment #1.3: 0002-Add-the-WoW-patch-of-Luis.patch --]
[-- Type: application/octet-stream, Size: 56612 bytes --]

>From 0d2ecb4947f18143e152874853c0dcf36f79d597 Mon Sep 17 00:00:00 2001
From: Burak Simsek <burak.simsekfokus.fraunhofer.de>
Date: Tue, 14 Sep 2010 10:35:22 +0200
Subject: [PATCH 2/2] Add the WoW patch of Luis
 http://www.mk.kernel.org/pub/linux/kernel/people/mcgrof/patches/wow-07-21.patch

---
 drivers/net/wireless/ath/ath5k/base.c            |    4 +-
 drivers/net/wireless/ath/ath9k/Makefile          |    1 +
 drivers/net/wireless/ath/ath9k/ar9002_hw.c       |   13 ++
 drivers/net/wireless/ath/ath9k/ar9002_initvals.h |   32 ++++
 drivers/net/wireless/ath/ath9k/ath9k.h           |   20 +++
 drivers/net/wireless/ath/ath9k/eeprom.h          |    1 +
 drivers/net/wireless/ath/ath9k/eeprom_def.c      |    2 +
 drivers/net/wireless/ath/ath9k/hw.c              |   48 +++++++
 drivers/net/wireless/ath/ath9k/hw.h              |   62 ++++++++
 drivers/net/wireless/ath/ath9k/main.c            |   26 ++++-
 drivers/net/wireless/ath/ath9k/pci.c             |  148 +++++++++++++++++++
 drivers/net/wireless/ath/ath9k/reg.h             |  153 ++++++++++++++++++++-
 drivers/net/wireless/mwl8k.c                     |    2 +-
 drivers/net/wireless/rt2x00/rt2x00.h             |    2 +-
 drivers/net/wireless/rt2x00/rt2x00mac.c          |    2 +-
 drivers/net/wireless/rtl818x/rtl8187_dev.c       |    2 +-
 include/linux/nl80211.h                          |   37 +++++
 include/net/cfg80211.h                           |   43 +++++-
 include/net/mac80211.h                           |   16 ++-
 net/mac80211/cfg.c                               |    8 +-
 net/mac80211/driver-ops.h                        |    7 +-
 net/mac80211/ieee80211_i.h                       |   23 ++-
 net/mac80211/iface.c                             |    6 +-
 net/mac80211/mlme.c                              |    3 +-
 net/mac80211/pm.c                                |   67 ++++++++-
 net/mac80211/util.c                              |   31 ++++-
 net/wireless/core.h                              |    3 +
 net/wireless/nl80211.c                           |  165 ++++++++++++++++++++++
 net/wireless/sme.c                               |   14 ++
 net/wireless/sysfs.c                             |    4 +-
 30 files changed, 896 insertions(+), 49 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 116ac66..5b3e5d3 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -224,7 +224,7 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 		struct ath5k_txq *txq);
 static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
 static int ath5k_start(struct ieee80211_hw *hw);
-static void ath5k_stop(struct ieee80211_hw *hw);
+static void ath5k_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow);
 static int ath5k_add_interface(struct ieee80211_hw *hw,
 		struct ieee80211_vif *vif);
 static void ath5k_remove_interface(struct ieee80211_hw *hw,
@@ -3024,7 +3024,7 @@ static int ath5k_start(struct ieee80211_hw *hw)
 	return ath5k_init(hw->priv);
 }
 
-static void ath5k_stop(struct ieee80211_hw *hw)
+static void ath5k_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	ath5k_stop_hw(hw->priv);
 }
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 4555e99..0103ef5 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -10,6 +10,7 @@ ath9k-y +=	beacon.o \
 ath9k-$(CONFIG_PCI) += pci.o
 ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
 ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
+ath9k-$(CONFIG_PM) += wow.o
 
 obj-$(CONFIG_ATH9K) += ath9k.o
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index 303c63d..3e808d7 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -103,6 +103,12 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
 			ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
 				  2);
 		}
+#ifdef CONFIG_PM
+		/* SerDes values during WOW sleep */
+		INIT_INI_ARRAY(&ah->iniPcieSerdesWow,
+			       ar9285PciePhy_AWOW_9285_1_2,
+			       ARRAY_SIZE(ar9285PciePhy_AWOW_9285_1_2), 2);
+#endif
 	} else if (AR_SREV_9280_20_OR_LATER(ah)) {
 		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
 			       ARRAY_SIZE(ar9280Modes_9280_2), 6);
@@ -118,6 +124,13 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
 			       ar9280PciePhy_clkreq_always_on_L1_9280,
 			       ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
 		}
+
+	#ifdef CONFIG_PM
+		/* SerDes values during WOW sleep */
+		INIT_INI_ARRAY(&ah->iniPcieSerdesWow, ar9280PciePhy_AWOW_9280,
+			       ARRAY_SIZE(ar9280PciePhy_AWOW_9280), 2);
+	#endif
+
 		INIT_INI_ARRAY(&ah->iniModesAdditional,
 			       ar9280Modes_fast_clock_9280_2,
 			       ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
index 6203eed..930de6d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
@@ -919,6 +919,22 @@ static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
 	{0x00004044, 0x00000000},
 };
 
+#ifdef CONFIG_PM
+/* Auto generated PCI-E PHY config for AR9280 with WOW */
+static const u_int32_t ar9280PciePhy_AWOW_9280[][2] = {
+    {0x00004040,  0x9248fd00 },
+    {0x00004040,  0x24924924 },
+    {0x00004040,  0xa8000019 },
+    {0x00004040,  0x13160820 },
+    {0x00004040,  0xe5980560 },
+    {0x00004040,  0xc01ddffd },
+    {0x00004040,  0x1aaabe41 },
+    {0x00004040,  0xbe105554 },
+    {0x00004040,  0x00043007 },
+    {0x00004044,  0x00000000 },
+};
+#endif
+
 static const u32 ar9285PciePhy_clkreq_always_on_L1_9285[][2] = {
 	/* Addr      allmodes  */
 	{0x00004040, 0x9248fd00},
@@ -1760,6 +1776,22 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
 	{0x00004044, 0x00000000},
 };
 
+
+#ifdef CONFIG_PM
+static const u_int32_t ar9285PciePhy_AWOW_9285_1_2[][2] = {
+    {0x00004040,  0x9248fd00 },
+    {0x00004040,  0x24924924 },
+    {0x00004040,  0xa8000019 },
+    {0x00004040,  0x13160820 },
+    {0x00004040,  0xe5980560 },
+    {0x00004040,  0xc01ddffd },
+    {0x00004040,  0x1aaabe41 },
+    {0x00004040,  0xbe105554 },
+    {0x00004040,  0x00043007 },
+    {0x00004044,  0x00000000 },
+};
+#endif /* CONFIG_PM */
+
 static const u32 ar9287Modes_9287_1_1[][6] = {
 	{0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0},
 	{0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0},
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index f0197a6..d61ea8f 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -589,6 +589,13 @@ struct ath_softc {
 
 	int beacon_interval;
 
+#ifdef CONFIG_PM
+	bool wow_got_bmiss_intr;
+	bool wow_sleep_proc_intr;
+	u32 wow_intr_before_sleep;
+	u32 wow_triggers_enabled;
+#endif
+
 #ifdef CONFIG_ATH9K_DEBUGFS
 	struct ath9k_debug debug;
 #endif
@@ -599,6 +606,19 @@ struct ath_softc {
 	struct ath_descdma txsdma;
 };
 
+#ifdef CONFIG_PM
+/*
+ * WoW trigger types
+ */
+#define AH_WOW_USER_PATTERN_EN		0x1
+#define AH_WOW_MAGIC_PATTERN_EN		0x2
+#define AH_WOW_LINK_CHANGE		0x4
+#define AH_WOW_BEACON_MISS		0x8
+#define AH_WOW_MAX_EVENTS		4
+
+#endif
+
+
 struct ath_wiphy {
 	struct ath_softc *sc; /* shared for all virtual wiphys */
 	struct ieee80211_hw *hw;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 0b09db0..6a7317f 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -239,6 +239,7 @@ enum eeprom_param {
 	EEP_MAC_MSW,
 	EEP_MAC_MID,
 	EEP_MAC_LSW,
+	EEP_WOW,
 	EEP_REG_0,
 	EEP_REG_1,
 	EEP_OP_CAP,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index afa2b73..921eee1 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -249,6 +249,8 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
 		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
 	case EEP_MAC_MSW:
 		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+	case EEP_WOW:
+		return pBase->eepMisc & BIT(1);
 	case EEP_REG_0:
 		return pBase->regDmn[0];
 	case EEP_REG_1:
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 3384ca1..10bcdb2 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -22,6 +22,8 @@
 #include "hw-ops.h"
 #include "rc.h"
 #include "ar9003_mac.h"
+#include "ar9002_initvals.h"
+
 
 static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
 
@@ -545,6 +547,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 	ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n",
 		ah->config.serialize_regmode);
 
+
 	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
 		ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
 	else
@@ -605,6 +608,16 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 		return r;
 	}
 
+	#ifdef CONFIG_PM
+	/* WOW */
+	ath9k_wow_set_gpio_reset_low(ah);
+	/* Clear the Wow Status */
+	REG_WRITE(ah, AR_PCIE_PM_CTRL, REG_READ(ah, AR_PCIE_PM_CTRL) |
+		  AR_PMCTRL_WOW_PME_CLR);
+	REG_WRITE(ah, AR_WOW_PATTERN_REG,
+		  AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN_REG)));
+	#endif
+
 	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
 		ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
 	else
@@ -617,6 +630,18 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 	return 0;
 }
 
+void ath9k_wow_set_gpio_reset_low(struct ath_hw *ah)
+{
+    u32 val;
+
+    val = REG_READ(ah, AR_GPIO_OE_OUT);
+    val |= (1 << (2 * 2));
+    REG_WRITE(ah, AR_GPIO_OE_OUT, val);
+    val = REG_READ(ah, AR_GPIO_OE_OUT);
+    val = REG_READ(ah,AR_GPIO_IN_OUT );
+}
+
+
 int ath9k_hw_init(struct ath_hw *ah)
 {
 	int ret;
@@ -2078,6 +2103,29 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 			  "regdomain mapped to 0x%x\n", regulatory->current_rd);
 	}
 
+	eeval = ah->eep_ops->get_eeprom(ah, EEP_WOW);
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		/*
+		 * Devices >= AR9280 rev 10 are capable of WoW but require
+		 * a few hardware changes. The EEPROM tells us whether these
+		 * hardware changes are in place on the device. Just enabling
+		 * WoW on the EEPROM is not enough to enable WoW.
+		 */
+		pCap->wow |= ATH9K_WOW_DEVICE_CAPABLE;
+		if (eeval) {
+			pCap->wow |= ATH9K_WOW_HW_ENABLED;
+			pCap->wow |= ATH9K_WOW_PATTERN_MATCH_EXACT;
+			/*
+			 * First 4 bytes of all patterns must match,
+			 * requires some wide masks to ensure proper
+			 * functionality for the disassociation and
+			 * deauthentication frames.
+			 */
+			if (AR_SREV_9280(ah))
+				pCap->wow |= ATH9K_WOW_PATTERN_MATCH_DWORD;
+		}
+	}
+
 	eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
 	if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
 		ath_print(common, ATH_DBG_FATAL,
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 1601dd4..a89351c 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -206,6 +206,42 @@ enum ath9k_hw_caps {
 	ATH9K_HW_CAP_PAPRD			= BIT(22),
 };
 
+/**
+ * enum ath9k_hw_wow_caps - WoW device capabilities
+ *
+ * @ATH9K_WOW_DEVICE_CAPABLE: device revision is capable of WoW
+ * @ATH9K_WOW_HW_ENABLED: EEPROM indicates hardware changes for WoW
+ *	*should be* are present. Devices need some the PCI Wake signal to go
+ *	through, this signal is typically capped with a resistor.
+ *	Devices with WoW physically enabled have this resistor
+ *	shorted to 0 ohm and also have the register that PCI core
+ *	picks up as PCI PME capable enabled.
+ * ATH9K_WOW_PATTERN_MATCH_EXACT: device is capable of matching
+ *	an exact pattern for de-authentication and disassocation.
+ * ATH9K_WOW_PATTERN_MATCH_DWORD: device requires the first four
+ *	bytes of the pattern for deauthentication and disassocation
+ * 	to match for all types of possible frames received of those
+ *	types.
+ */
+enum ath9k_hw_wow_caps {
+	ATH9K_WOW_DEVICE_CAPABLE		= BIT(0),
+	ATH9K_WOW_HW_ENABLED			= BIT(1),
+	ATH9K_WOW_PATTERN_MATCH_EXACT		= BIT(2),
+	ATH9K_WOW_PATTERN_MATCH_DWORD		= BIT(3),
+};
+
+
+/**
+ * struct ath9k_hw_capabilities - device capabilities
+ *
+ * This structure contains the device capabilities. The EEPROM will
+ * be read and specific device capabilities are mapped accordingly
+ * for easy access.
+ *
+ * wow: Wake-on-Wireless LAN capabilities, can be any of the
+ * 	%ATH9K_WOW_*.
+ */
+
 struct ath9k_hw_capabilities {
 	u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
 	DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */
@@ -221,6 +257,7 @@ struct ath9k_hw_capabilities {
 	u8 num_gpio_pins;
 	u8 num_antcfg_2ghz;
 	u8 num_antcfg_5ghz;
+	u32 wow;
 	u8 rx_hp_qdepth;
 	u8 rx_lp_qdepth;
 	u8 rx_status_len;
@@ -785,6 +822,13 @@ struct ath_hw {
 	int PDADCdelta;
 	u8 led_pin;
 
+
+#ifdef CONFIG_PM
+	/* WoW mask -- used to indicate which WoW we have enabled */
+	u32 ah_wowEventMask;
+#endif
+
+
 	struct ar5416IniArray iniModes;
 	struct ar5416IniArray iniCommon;
 	struct ar5416IniArray iniBank0;
@@ -815,6 +859,11 @@ struct ath_hw {
 	struct ar5416IniArray iniRadio[ATH_INI_NUM_SPLIT];
 	struct ar5416IniArray iniSOC[ATH_INI_NUM_SPLIT];
 
+#ifdef CONFIG_PM
+	/* SerDes values during WOW sleep */
+	struct ar5416IniArray iniPcieSerdesWow;
+#endif
+
 	u32 intr_gen_timer_trigger;
 	u32 intr_gen_timer_thresh;
 	struct ath_gen_timer_table hw_gen_timers;
@@ -1005,4 +1054,17 @@ void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah);
 #define ATH9K_CLOCK_RATE_2GHZ_OFDM	44
 #define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44
 
+#ifdef CONFIG_PM
+
+/* WOW - Wake on Wireless */
+void ath9k_wow_set_gpio_reset_low(struct ath_hw *ah);
+/* Called when going to suspend/hibernate */
+void ath9k_hw_wow_enable(struct ath_hw *ah, u32 patternEnable);
+/* Called when coming back up from suspend/hibernation */
+u32 ath9k_hw_wow_wake_up(struct ath_hw *ah);
+const char *ath9k_hw_wow_event_to_string(u32 wow_event);
+
+#endif /* CONFIG_PM */
+
+
 #endif
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a57ead1..4344a87 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -645,7 +645,7 @@ irqreturn_t ath_isr(int irq, void *dev)
 	struct ath_hw *ah = sc->sc_ah;
 	enum ath9k_int status;
 	bool sched = false;
-
+	struct ath_common *common = ath9k_hw_common(ah);
 	/*
 	 * The hardware is not ready/present, don't
 	 * touch anything. Note this can happen early
@@ -725,6 +725,21 @@ irqreturn_t ath_isr(int irq, void *dev)
 		ath9k_hw_set_interrupts(ah, ah->imask);
 	}
 
+	if (status & ATH9K_INT_BMISS) {
+	#ifdef CONFIG_PM
+		if (sc->wow_sleep_proc_intr) {
+			ath_print(common, (ATH_DBG_ANY | ATH_DBG_INTERRUPT),
+				"during WoW we got a BMISS\n");
+			sc->wow_got_bmiss_intr = true;
+			sc->wow_sleep_proc_intr = false;
+		}
+	#else
+		/* BMISS not enabled on ath9k unless WoW is enabled */
+		ath_print(sc, ATH_DBG_INTERRUPT,
+			"spurious unattended beacon miss interrupt\n");
+	#endif
+	}
+
 	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
 		if (status & ATH9K_INT_TIM_TIMER) {
 			/* Clear RxAbort bit so that we can
@@ -1320,6 +1335,15 @@ static void ath9k_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 		cancel_work_sync(&sc->chan_work);
 	}
 
+#ifdef CONFIG_PM
+	if (wow && wow->triggers_enabled) {
+		sc->wow_triggers_enabled = wow->triggers_enabled;
+		ath_print(common, ATH_DBG_ANY, "Leaving radio on during "
+			"suspend for WoW\n");
+		return;
+	}
+#endif
+
 	if (sc->sc_flags & SC_OP_INVALID) {
 		ath_print(common, ATH_DBG_ANY, "Device not present\n");
 		mutex_unlock(&sc->mutex);
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index b5b6514..8311a0a 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -156,6 +156,9 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if ((val & 0x0000ff00) != 0)
 		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
+	device_init_wakeup(&pdev->dev, 1);
+	device_set_wakeup_enable(&pdev->dev, 0);
+
 	ret = pci_request_region(pdev, 0, "ath9k");
 	if (ret) {
 		dev_err(&pdev->dev, "PCI memory region reserve error\n");
@@ -212,6 +215,34 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
 		   hw_name, (unsigned long)mem, pdev->irq);
 
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	/* WoW is for PCI for ath9k */
+
+	/*
+	 * Bmiss and link change triggers not yet fully tested, add them
+	 * after properly testing and confirming behaviour. I believe
+	 * we need pattern matching support to enable them as well
+	 * (detect deauth and disassoc).
+	 */
+	if (ah->caps.wow & ATH9K_WOW_DEVICE_CAPABLE &&
+	    ah->caps.wow & ATH9K_WOW_HW_ENABLED)
+		hw->wiphy->wow_triggers_supported =
+				NL80211_WOW_TRIGGER_MAGIC_PACKET;
+
+	ath_print(common, ATH_DBG_CONFIG,
+		"WoW capabler device: %s\n",
+		(ah->caps.wow & ATH9K_WOW_DEVICE_CAPABLE) ? "yes" : "no");
+	ath_print(common, ATH_DBG_CONFIG,
+		"EEPROM indicates WoW hw changes in place: %s\n",
+		(ah->caps.wow & ATH9K_WOW_HW_ENABLED) ? "yes" : "no");
+	ath_print(common, ATH_DBG_CONFIG,
+		"WoW exact match pattern support: %s\n",
+		(ah->caps.wow & ATH9K_WOW_PATTERN_MATCH_EXACT) ? "yes" : "no");
+	ath_print(common, ATH_DBG_CONFIG,
+		"WoW match pattern first dword requirement: %s\n",
+		(ah->caps.wow & ATH9K_WOW_PATTERN_MATCH_DWORD) ? "yes" : "no");
+
 	return 0;
 
 err_init:
@@ -247,21 +278,134 @@ static void ath_pci_remove(struct pci_dev *pdev)
 
 #ifdef CONFIG_PM
 
+static u32 ath9k_wow_event_map(u32 cfg_wow_events)
+{
+	u32 wow_events = 0;
+
+	if (cfg_wow_events & NL80211_WOW_TRIGGER_MAGIC_PACKET)
+		wow_events |= AH_WOW_MAGIC_PATTERN_EN;
+#if 0
+	if (cfg_wow_events & NL80211_WOW_TRIGGER_BMISS)
+		wow_events |= AH_WOW_BEACON_MISS;
+	if (cfg_wow_events & NL80211_WOW_TRIGGER_LINK_CHANGE)
+		wow_events |= AH_WOW_LINK_CHANGE;
+#endif
+
+	return wow_events;
+}
+
+static void ath9k_pci_wow_enable(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	u32 wake_up_events;
+	struct ath_common *common = ath9k_hw_common(ah);
+	wake_up_events = ath9k_wow_event_map(sc->wow_triggers_enabled);
+
+	/* eventually we'll add this...
+	 * if (wake_up_events & AH_WOW_USER_PATTERN_EN)
+	 *	ath9k_wow_create_pattern(sc);
+	 */
+
+	/*
+	 * To avoid false wake, we enable beacon miss interrupt only when
+	 * we go to sleep. We save the current interrupt mask so that
+	 * we can restore it after the system wakes up.
+	 */
+	//burak> resmen uctum burada
+	sc->wow_intr_before_sleep = ah->imask;
+	ath9k_hw_set_interrupts(ah, ATH9K_INT_BMISS | ATH9K_INT_GLOBAL);
+	ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL;
+
+	ath9k_hw_wow_enable(ah, wake_up_events);
+	device_set_wakeup_enable(sc->dev, 1);
+
+	ath_print(common, ATH_DBG_ANY,
+		"WoW enabled\n");
+
+	sc->wow_sleep_proc_intr = true;
+
+	/*
+	sc->wow_intr_before_sleep = ah->mask_reg;
+		ath9k_hw_set_interrupts(ah, ATH9K_INT_BMISS | ATH9K_INT_GLOBAL);
+		sc->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL;
+
+		ath9k_hw_wow_enable(ah, wake_up_events);
+		device_set_wakeup_enable(sc->dev, 1);
+
+		DPRINTF(sc, ATH_DBG_ANY,
+			"WoW enabled\n");
+
+		sc->wow_sleep_proc_intr = true;
+	*/
+
+
+}
+
+
 static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 
+	if (!!sc->wow_triggers_enabled && device_can_wakeup(&pdev->dev))
+		ath9k_pci_wow_enable(sc);
+
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
+
+
+	if (!!sc->wow_triggers_enabled && device_can_wakeup(&pdev->dev)) {
+		pci_prepare_to_sleep(pdev);
+		return 0;
+	}
+
+	pci_wake_from_d3(pdev, !!sc->wow_triggers_enabled);
+
 	pci_set_power_state(pdev, PCI_D3hot);
 
 	return 0;
 }
 
+
+static void ath9k_pci_wow_wake(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	u32 wow_status;
+
+	ath9k_hw_set_interrupts(ah, sc->wow_intr_before_sleep);
+	ah->imask = sc->wow_intr_before_sleep;
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	wow_status = ath9k_hw_wow_wake_up(sc->sc_ah);
+
+	if (sc->wow_got_bmiss_intr) {
+		/*
+		 * Some devices may not pick beacon miss
+		 * as the reason they woke up so we add that
+		 * here for that shortcoming
+		 */
+		wow_status |= AH_WOW_BEACON_MISS;
+		sc->wow_got_bmiss_intr = false;
+		ath_print(common, ATH_DBG_ANY,
+			"Beacon miss interrupt picked up during sleep, "
+			"adding as possible wake up reason\n");
+	}
+
+	if (wow_status) {
+		ath_print(common, ATH_DBG_ANY,
+			"Waking up due to WoW trigger%s\n",
+			ath9k_hw_wow_event_to_string(wow_status));
+		ath_print(common, ATH_DBG_ANY,
+			"WoW status: %d\n WoW reason: %s\n",
+			wow_status,
+			ath9k_hw_wow_event_to_string((wow_status & 0x0FFF)));
+	}
+}
+
+
 static int ath_pci_resume(struct pci_dev *pdev)
 {
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
@@ -285,6 +429,10 @@ static int ath_pci_resume(struct pci_dev *pdev)
 	if ((val & 0x0000ff00) != 0)
 		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
+	if (sc->wow_triggers_enabled)
+		ath9k_pci_wow_wake(sc);
+
+
 	/* Enable LED */
 	ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
 			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index d01c4ad..2891d65 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -707,8 +707,9 @@
 #define AR_WA_D3_TO_L1_DISABLE_REAL     (1 << 16)
 #define AR_WA_ASPM_TIMER_BASED_DISABLE  (1 << 17)
 #define AR_WA_RESET_EN                  (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
-#define AR_WA_ANALOG_SHIFT              (1 << 20)
-#define AR_WA_POR_SHORT                 (1 << 21) /* PCI-E Phy reset control */
+#define AR_WA_UNTIE_RESET_EN	(1 << 15)   /* Enable PCI Reset to POR (power-on-reset) */
+#define AR_WA_ANALOG_SHIFT	(1 << 20)
+#define AR_WA_POR_SHORT		(1 << 21)   /* PCI-E Phy reset control */
 #define AR9285_WA_DEFAULT		0x004a050b
 #define AR9280_WA_DEFAULT           	0x0040073b
 #define AR_WA_DEFAULT               	0x0000073f
@@ -1824,6 +1825,154 @@ enum {
 #define AR_KEYTABLE_TYPE(_n)    (AR_KEYTABLE(_n) + 20)
 #define AR_KEYTABLE_MAC0(_n)    (AR_KEYTABLE(_n) + 24)
 #define AR_KEYTABLE_MAC1(_n)    (AR_KEYTABLE(_n) + 28)
+/* WoW - Wake On Wireless */
+
+#define AR_PMCTRL_AUX_PWR_DET		0x10000000  /* Puts Chip in L2 state */
+#define AR_PMCTRL_D3COLD_VAUX		0x00800000
+#define AR_PMCTRL_HOST_PME_EN		0x00400000    /* Send OOB WAKE_L on WoW event */
+#define AR_PMCTRL_WOW_PME_CLR		0x00200000    /* Clear WoW event */
+#define AR_PMCTRL_PWR_STATE_MASK	0x0F000000    /* Power State Mask */
+#define AR_PMCTRL_PWR_STATE_D1D3	0x0F000000    /* Activate D1 and D3 */
+#define AR_PMCTRL_PWR_STATE_D0		0x08000000    /* Activate D0 */
+#define AR_PMCTRL_PWR_PM_CTRL_ENA	0x00008000    /* Enable power management */
+
+#define AR_WOW_BEACON_TIMO_MAX		0xFFFFFFFF  /* Max. value for Beacon Timeout */
+
+/*
+ * MAC WoW Registers.
+ */
+#define AR_WOW_PATTERN_REG		0x825C
+#define AR_WOW_COUNT_REG		0x8260
+#define AR_WOW_BCN_EN_REG		0x8270
+#define AR_WOW_BCN_TIMO_REG		0x8274
+#define AR_WOW_KEEP_ALIVE_TIMO_REG	0x8278
+#define AR_WOW_KEEP_ALIVE_REG		0x827C
+#define AR_WOW_US_SCALAR_REG		0x8284
+#define AR_WOW_KEEP_ALIVE_DELAY_REG	0x8288
+#define AR_WOW_PATTERN_MATCH_REG	0x828C
+#define AR_WOW_PATTERN_OFF1_REG		0x8290 /* Pattern bytes 0 -> 3 */
+#define AR_WOW_PATTERN_OFF2_REG		0x8294 /* Pattern bytes 4 -> 7 */
+/* For AR9285 or Later version of chips */
+#define AR_WOW_EXACT_REG		0x829C
+#define AR_WOW_LENGTH1_REG		0x8360
+#define AR_WOW_LENGTH2_REG		0x8364
+/* Register to enable pattern match for less than 256 bytes packets */
+#define AR_WOW_PATTERN_MATCH_LT_256B_REG	0x8368
+
+/* AR_WOW_PATTERN_REG Values */
+#define AR_WOW_BACK_OFF_SHIFT(x)	((x & 0xf) << 27)    /* in usecs */
+#define AR_WOW_MAC_INTR_EN		0x00040000
+#define AR_WOW_MAGIC_EN			0x00010000
+#define AR_WOW_PATTERN_EN(x)		((x & 0xff) << 0)
+#define AR_WOW_PATTERN_FOUND_SHIFT	8
+#define AR_WOW_PATTERN_FOUND(x)		(x & (0xff << AR_WOW_PATTERN_FOUND_SHIFT))
+#define AR_WOW_PATTERN_FOUND_MASK	((0xff) << AR_WOW_PATTERN_FOUND_SHIFT)
+#define AR_WOW_MAGIC_PAT_FOUND		0x00020000
+#define AR_WOW_MAC_INTR			0x00080000
+#define AR_WOW_KEEP_ALIVE_FAIL		0x00100000
+#define AR_WOW_BEACON_FAIL		0x00200000
+
+#define AR_WOW_STATUS(x)	(x & (AR_WOW_PATTERN_FOUND_MASK | \
+				      AR_WOW_MAGIC_PAT_FOUND | \
+				      AR_WOW_KEEP_ALIVE_FAIL | \
+				      AR_WOW_BEACON_FAIL))
+#define AR_WOW_CLEAR_EVENTS(x)	(x & ~(AR_WOW_PATTERN_EN(0xff) | \
+				       AR_WOW_MAGIC_EN | \
+				       AR_WOW_MAC_INTR_EN | \
+				       AR_WOW_BEACON_FAIL | \
+				       AR_WOW_KEEP_ALIVE_FAIL))
+
+/* AR_WOW_COUNT_REG Values */
+#define AR_WOW_AIFS_CNT(x)		((x & 0xff) << 0)
+#define AR_WOW_SLOT_CNT(x)		((x & 0xff) << 8)
+#define AR_WOW_KEEP_ALIVE_CNT(x)	((x & 0xff) << 16)
+
+/* AR_WOW_BCN_EN_REG */
+#define AR_WOW_BEACON_FAIL_EN		0x00000001
+
+/* AR_WOW_BCN_TIMO_REG */
+#define AR_WOW_BEACON_TIMO		0x40000000  /* Valid if BCN_EN is set */
+
+/* AR_WOW_KEEP_ALIVE_TIMO_REG */
+#define AR_WOW_KEEP_ALIVE_TIMO		0x00007A12
+#define AR_WOW_KEEP_ALIVE_NEVER		0xFFFFFFFF
+
+/* AR_WOW_KEEP_ALIVE_REG */
+#define AR_WOW_KEEP_ALIVE_AUTO_DIS	0x00000001
+#define AR_WOW_KEEP_ALIVE_FAIL_DIS	0x00000002
+
+/* AR_WOW_KEEP_ALIVE_DELAY_REG */
+#define AR_WOW_KEEP_ALIVE_DELAY		0x000003E8 /* 1 msec */
+
+/*
+ * Keep it long for Beacon workaround - ensures no false alarm
+ */
+#define AR_WOW_BMISSTHRESHOLD 0x20
+
+/* AR_WOW_PATTERN_MATCH_REG */
+#define AR_WOW_PAT_END_OF_PKT(x)	((x & 0xf) << 0)
+#define AR_WOW_PAT_OFF_MATCH(x)		((x & 0xf) << 8)
+
+/*
+ * Default values for Wow Configuration for backoff, aifs, slot, keep-alive, etc
+ * to be programmed into various registers.
+ */
+#define AR_WOW_PAT_BACKOFF	0x00000004 /* AR_WOW_PATTERN_REG */
+#define AR_WOW_CNT_AIFS_CNT	0x00000022 /* AR_WOW_COUNT_REG */
+#define AR_WOW_CNT_SLOT_CNT	0x00000009 /* AR_WOW_COUNT_REG */
+/*
+ * Keepalive count applicable for AR9280 2.0 and above.
+ */
+#define AR_WOW_CNT_KA_CNT 0x00000008    /* AR_WOW_COUNT_REG */
+
+/* WoW - Transmit buffer for keep alive frames */
+#define AR_WOW_TRANSMIT_BUFFER	0xE000 /* E000 - EFFC */
+
+#define AR_WOW_KA_DESC_WORD2	0xE000
+#define AR_WOW_KA_DESC_WORD3	0xE004
+#define AR_WOW_KA_DESC_WORD4	0xE008
+#define AR_WOW_KA_DESC_WORD5	0xE00C
+#define AR_WOW_KA_DESC_WORD6	0xE010
+#define AR_WOW_KA_DESC_WORD7	0xE014
+#define AR_WOW_KA_DESC_WORD8	0xE018
+#define AR_WOW_KA_DESC_WORD9	0xE01C
+#define AR_WOW_KA_DESC_WORD10	0xE020
+#define AR_WOW_KA_DESC_WORD11	0xE024
+#define AR_WOW_KA_DESC_WORD12	0xE028
+#define AR_WOW_KA_DESC_WORD13	0xE02C
+
+#define AR_WOW_KA_DATA_WORD0	0xE030
+#define AR_WOW_KA_DATA_WORD1	0xE034
+#define AR_WOW_KA_DATA_WORD2	0xE038
+#define AR_WOW_KA_DATA_WORD3	0xE03C
+#define AR_WOW_KA_DATA_WORD4	0xE040
+#define AR_WOW_KA_DATA_WORD5	0xE044
+
+/* WoW Transmit Buffer for patterns */
+#define AR_WOW_TB_PATTERN0	0xE100
+#define AR_WOW_TB_PATTERN1	0xE200
+#define AR_WOW_TB_PATTERN2	0xE300
+#define AR_WOW_TB_PATTERN3	0xE400
+#define AR_WOW_TB_PATTERN4	0xE500
+#define AR_WOW_TB_PATTERN5	0xE600
+#define AR_WOW_TB_PATTERN6	0xE700
+#define AR_WOW_TB_PATTERN7	0xE800
+#define AR_WOW_TB_MASK0		0xEC00
+#define AR_WOW_TB_MASK1		0xEC20
+#define AR_WOW_TB_MASK2		0xEC40
+#define AR_WOW_TB_MASK3		0xEC60
+#define AR_WOW_TB_MASK4		0xEC80
+#define AR_WOW_TB_MASK5		0xECa0
+#define AR_WOW_TB_MASK6		0xECC0
+#define AR_WOW_TB_MASK7		0xECE0
+
+/* Currently Pattern 0-7 are supported - so bit 0-7 are set */
+#define AR_WOW_PATTERN_SUPPORTED	0xFF
+#define AR_WOW_LENGTH_MAX		0xFF
+#define AR_WOW_LENGTH1_SHIFT(_i)	((0x3 - ((_i) & 0x3)) << 0x3)
+#define AR_WOW_LENGTH1_MASK(_i)		(AR_WOW_LENGTH_MAX << AR_WOW_LENGTH1_SHIFT(_i))
+#define AR_WOW_LENGTH2_SHIFT(_i)	((0x7 - ((_i) & 0x7)) << 0x3)
+#define AR_WOW_LENGTH2_MASK(_i)		(AR_WOW_LENGTH_MAX << AR_WOW_LENGTH2_SHIFT(_i))
 
 #define AR9271_CORE_CLOCK	117   /* clock to 117Mhz */
 #define AR9271_TARGET_BAUD_RATE	19200 /* 115200 */
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f152a25..5a711c3 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -3256,7 +3256,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
 	return rc;
 }
 
-static void mwl8k_stop(struct ieee80211_hw *hw)
+static void mwl8k_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct mwl8k_priv *priv = hw->priv;
 	int i;
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 0ae942c..0e59b84 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1082,7 +1082,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
  */
 int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 int rt2x00mac_start(struct ieee80211_hw *hw);
-void rt2x00mac_stop(struct ieee80211_hw *hw);
+void rt2x00mac_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow);
 int rt2x00mac_add_interface(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif);
 void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 235e037..92a95cd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -175,7 +175,7 @@ int rt2x00mac_start(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_start);
 
-void rt2x00mac_stop(struct ieee80211_hw *hw)
+void rt2x00mac_stop(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 38fa824..f62f464 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -987,7 +987,7 @@ rtl8187_start_exit:
 	return ret;
 }
 
-static void rtl8187_stop(struct ieee80211_hw *dev)
+static void rtl8187_stop(struct ieee80211_hw *dev, struct cfg80211_wow *wow)
 {
 	struct rtl8187_priv *priv = dev->priv;
 	struct sk_buff *skb;
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 31603e8..805048c 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -311,6 +311,19 @@
  * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
  *	associated with this wiphy must be down and will follow.
  *
+ * @NL80211_CMD_GET_WOW: get Wake-on-Wireless-LAN (WoW) settings.
+ * @NL80211_CMD_SET_WOW: set Wake-on-Wireless-LAN (Wow) settings. Wake on
+ *	wireless makes use of standard Wake-on-LAN (WoL) frames, you receive
+ *	a WoW frame when your AP sends you a regular WOL frame. The difference
+ *	difference WoL is you need to be associated to an AP in order to
+ *	receive WoW frames, so additional triggers are available for a wakeup.
+ *	A driver capable of WoW should initialize the wiphy with its supported
+ *	WoW triggers. Upon suspend cfg80211 will inform the driver of the user
+ *	enabled triggers. By default no WoW triggers are enabled.
+ *	For more information see:
+ *	http://wireless.kernel.org/en/users/Documentation/WoW
+ *
+ *
  * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified
  *	channel for the specified amount of time. This can be used to do
  *	off-channel operations like transmit a Public Action frame and wait for
@@ -462,6 +475,8 @@ enum nl80211_commands {
 	NL80211_CMD_DISCONNECT,
 
 	NL80211_CMD_SET_WIPHY_NETNS,
+	NL80211_CMD_GET_WOW,
+	NL80211_CMD_SET_WOW,
 
 	NL80211_CMD_GET_SURVEY,
 	NL80211_CMD_NEW_SURVEY_RESULTS,
@@ -509,6 +524,8 @@ enum nl80211_commands {
 #define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE
 #define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE
 #define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT
+#define NL80211_CMD_GET_WOW NL80211_CMD_GET_WOW
+#define NL80211_CMD_SET_WOW NL80211_CMD_SET_WOW
 
 /**
  * enum nl80211_attrs - nl80211 netlink attributes
@@ -736,6 +753,12 @@ enum nl80211_commands {
  *
  * @NL80211_ATTR_PID: Process ID of a network namespace.
  *
+ * @NL80211_ATTR_WOW_TRIGGERS_SUPPORTED: the supported WoW triggers
+ * @NL80211_ATTR_WOW_TRIGGERS_ENABLED: used by %NL80211_CMD_SET_WOW to
+ *	indicate which WoW triggers should be enabled. This is also
+ *	used by %NL80211_CMD_GET_WOW to get the currently enabled WoW
+ *	triggers.
+ *
  * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
  *	dumps. This number increases whenever the object list being
  *	dumped changes, and as such userspace can verify that it has
@@ -927,6 +950,9 @@ enum nl80211_attrs {
 	NL80211_ATTR_KEYS,
 
 	NL80211_ATTR_PID,
+	
+	NL80211_ATTR_WOW_TRIGGERS_SUPPORTED,
+	NL80211_ATTR_WOW_TRIGGERS_ENABLED,
 
 	NL80211_ATTR_4ADDR,
 
@@ -1703,6 +1729,17 @@ enum nl80211_key_attributes {
 };
 
 /**
+ * enum nl80211_wow_triggers - Wake-on-Wireless-LAN triggers
+ *
+ * NL80211_WOW_TRIGGER_MAGIC_PACKET: a wake signal will be sent to the
+ *     devices if a magic packet is received.
+ */
+enum nl80211_wow_triggers {
+	NL80211_WOW_TRIGGER_MAGIC_PACKET	= 1 << 1,
+};
+
+
+/**
  * enum nl80211_tx_rate_attributes - TX rate set attributes
  * @__NL80211_TXRATE_INVALID: invalid
  * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4c8c727..2d1ba87 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -780,6 +780,9 @@ struct cfg80211_crypto_settings {
 	bool control_port_no_encrypt;
 };
 
+
+
+
 /**
  * struct cfg80211_auth_request - Authentication request data
  *
@@ -977,6 +980,27 @@ struct cfg80211_pmksa {
 	u8 *pmkid;
 };
 
+
+/*
+ * struct cfg80211_wow - Wake on Wireless-LAN support info
+ *
+ * This structure defines the WoW triggers enabled and set for the device.
+ * For now we only carry the supported tiggers but this is expected to grow
+ * once we add support for user patterns.
+ *
+ * @triggers_enabled: enabled triggers by the user. Default
+ *	is to disable all triggers. The flags for this bitmask
+ *	are %NL80211_WOW_TRIGGER_*.
+ * @netdev: net_device where we enabled WoW. This is only used to clear
+ *	the @triggers_enabled upon disassociation and to prevent settings
+ *	onto other netdevices from the same rdev.
+ */
+struct cfg80211_wow {
+	u32 triggers_enabled;
+	struct net_device *netdev;
+};
+
+
 /**
  * struct cfg80211_ops - backend description for wireless configuration
  *
@@ -990,8 +1014,11 @@ struct cfg80211_pmksa {
  * wireless extensions but this is subject to reevaluation as soon as this
  * code is used more widely and we have a first user without wext.
  *
- * @suspend: wiphy device needs to be suspended
- * @resume: wiphy device needs to be resumed
+ * @suspend: wiphy device needs to be suspended. We pass the struct cfg80211_wow
+ *	so the device enables the appropriate triggers during suspend.
+ * @resume: wiphy device needs to be resumed. We pass the struct cfg80211_wow
+ * 	so the device can opt out from adding new information for the AP we
+ *	we were last associated to when WoW was enabled
  *
  * @add_virtual_intf: create a new virtual interface with the given name,
  *	must set the struct wireless_dev's iftype. Beware: You must create
@@ -1115,8 +1142,11 @@ struct cfg80211_pmksa {
  *
  */
 struct cfg80211_ops {
-	int	(*suspend)(struct wiphy *wiphy);
-	int	(*resume)(struct wiphy *wiphy);
+//	int	(*suspend)(struct wiphy *wiphy);
+//	int	(*resume)(struct wiphy *wiphy);
+
+	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wow *wow);
+	int	(*resume)(struct wiphy *wiphy, struct cfg80211_wow *wow);
 
 	int	(*add_virtual_intf)(struct wiphy *wiphy, char *name,
 				    enum nl80211_iftype type, u32 *flags,
@@ -1337,6 +1367,10 @@ struct ieee80211_txrx_stypes {
  * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
  *	-1 = fragmentation disabled, only odd values >= 256 used
  * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
+ * @wow_triggers_supported: supported bitmask of Wake-on-Wireless triggers.
+ *	The flags for this bitmask are %NL80211_WOW_TRIGGER_*. The driver
+ *	should set the capabilities before registering the wiphy. WoW triggers
+ *	which should be used are passed to the driver upon suspend.
  * @_net: the network namespace this wiphy currently lives in
  * @perm_addr: permanent MAC address of this device
  * @addr_mask: If the device supports multiple MAC addresses by masking,
@@ -1414,6 +1448,7 @@ struct wiphy {
 	u32 hw_version;
 
 	u8 max_num_pmkids;
+	u32 wow_triggers_supported;
 
 	/* If multiple wiphys are registered and you're handed e.g.
 	 * a regular netdev with assigned ieee80211_ptr, you won't
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f91fc33..c04b222 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1520,12 +1520,14 @@ enum ieee80211_ampdu_mlme_action {
  *	Must be implemented and can sleep.
  *
  * @stop: Called after last netdevice attached to the hardware
- *	is disabled. This should turn off the hardware (at least
- *	it must turn off frame reception.)
- *	May be called right after add_interface if that rejects
- *	an interface. If you added any work onto the mac80211 workqueue
- *	you should ensure to cancel it on this callback.
- *	Must be implemented and can sleep.
+ *	is disabled or during suspend. This should turn off the
+ *	hardware (at least it must turn off frame reception) unless
+ *	the device wants to enable Wake-on-Wireless-LAN. In order to
+ *	process WoW triggers the radio must be left on and the driver
+ *	must enable the triggers in hardware. This callback may be
+ *	called right after add_interface if that rejects an interface.
+ *	Must be implemented. WoW triggers which should be enabled prior
+ *	suspend are passed in the callback.
  *
  * @add_interface: Called when a netdevice attached to the hardware is
  *	enabled. Because it is not called for monitor mode devices, @start
@@ -1696,7 +1698,7 @@ enum ieee80211_ampdu_mlme_action {
 struct ieee80211_ops {
 	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
 	int (*start)(struct ieee80211_hw *hw);
-	void (*stop)(struct ieee80211_hw *hw);
+	void (*stop)(struct ieee80211_hw *hw, struct cfg80211_wow *wow);
 	int (*add_interface)(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif);
 	int (*change_interface)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5de1ca3..ba85860 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1132,14 +1132,14 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
 }
 
 #ifdef CONFIG_PM
-static int ieee80211_suspend(struct wiphy *wiphy)
+static int ieee80211_suspend(struct wiphy *wiphy, struct cfg80211_wow *wow)
 {
-	return __ieee80211_suspend(wiphy_priv(wiphy));
+	return __ieee80211_suspend(wiphy_priv(wiphy) , wow);
 }
 
-static int ieee80211_resume(struct wiphy *wiphy)
+static int ieee80211_resume(struct wiphy *wiphy, struct cfg80211_wow *wow)
 {
-	return __ieee80211_resume(wiphy_priv(wiphy));
+	return __ieee80211_resume(wiphy_priv(wiphy) ,wow);
 }
 #else
 #define ieee80211_suspend NULL
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 6064b7b..82a695d 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -24,12 +24,13 @@ static inline int drv_start(struct ieee80211_local *local)
 	return ret;
 }
 
-static inline void drv_stop(struct ieee80211_local *local)
+static inline void drv_stop(struct ieee80211_local *local, struct cfg80211_wow *wow)
 {
 	might_sleep();
 
-	trace_drv_stop(local);
-	local->ops->stop(&local->hw);
+	trace_drv_stop(local, wow);
+	local->ops->stop(&local->hw, wow);
+
 	trace_drv_return_void(local);
 
 	/* sync away all work on the tasklet before clearing started */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 16f7fb1..5313ecd 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -723,6 +723,13 @@ struct ieee80211_local {
 	 * ease timer cancelling etc.
 	 */
 	bool quiescing;
+	/*
+	 * This will be true if we had enabled PS before going to suspend.
+	 * We use this to help resume restore the PS state to what it was.
+	 * Note that this only makes sense if we're associated and are a
+	 * station.
+	 */
+	bool ps_before_suspend;
 
 	/* device is started */
 	bool started;
@@ -1178,23 +1185,25 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
 				       size_t len);
 
 /* Suspend/resume and hw reconfiguration */
-int ieee80211_reconfig(struct ieee80211_local *local);
-void ieee80211_stop_device(struct ieee80211_local *local);
+int ieee80211_reconfig(struct ieee80211_local *local, struct cfg80211_wow *wow);
+void ieee80211_stop_device(struct ieee80211_local *local,  struct cfg80211_wow *wow);
 
 #ifdef CONFIG_PM
-int __ieee80211_suspend(struct ieee80211_hw *hw);
+int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wow *wow);
 
-static inline int __ieee80211_resume(struct ieee80211_hw *hw)
+static inline int __ieee80211_resume(struct ieee80211_hw *hw,
+				     struct cfg80211_wow *wow)
 {
-	return ieee80211_reconfig(hw_to_local(hw));
+	return ieee80211_reconfig(hw_to_local(hw), wow);
 }
 #else
-static inline int __ieee80211_suspend(struct ieee80211_hw *hw)
+static inline int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	return 0;
 }
 
-static inline int __ieee80211_resume(struct ieee80211_hw *hw)
+static inline int __ieee80211_resume(struct ieee80211_hw *hw,
+				     struct cfg80211_wow *wow)
 {
 	return 0;
 }
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index c1cc200..78506a6 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -216,7 +216,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
 
 		if (!is_valid_ether_addr(dev->dev_addr)) {
 			if (!local->open_count)
-				drv_stop(local);
+				drv_stop(local,NULL);
 			return -EADDRNOTAVAIL;
 		}
 	}
@@ -338,7 +338,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
 	drv_remove_interface(local, &sdata->vif);
  err_stop:
 	if (!local->open_count)
-		drv_stop(local);
+		drv_stop(local,NULL);
  err_del_bss:
 	sdata->bss = NULL;
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -543,7 +543,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 		if (local->ops->napi_poll)
 			napi_disable(&local->napi);
 		ieee80211_clear_tx_pending(local);
-		ieee80211_stop_device(local);
+		ieee80211_stop_device(local,NULL);
 
 		/* no reconfiguring after stop! */
 		hw_reconf_flags = 0;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0cb822c..9072293 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1912,7 +1912,8 @@ static void ieee80211_sta_monitor_work(struct work_struct *work)
 	struct ieee80211_sub_if_data *sdata =
 		container_of(work, struct ieee80211_sub_if_data,
 			     u.mgd.monitor_work);
-
+	if (sdata->local->scanning)
+		return;
 	ieee80211_mgd_probe_ap(sdata, false);
 }
 
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index d287fde..37bd195 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -6,14 +6,68 @@
 #include "driver-ops.h"
 #include "led.h"
 
-int __ieee80211_suspend(struct ieee80211_hw *hw)
+int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wow *wow)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct ieee80211_sub_if_data *sdata;
 	struct sta_info *sta;
+	
+	bool wow_netdev_found = false;
 
 	ieee80211_scan_cancel(local);
 
+
+	local->ps_before_suspend = !!(local->hw.conf.flags & IEEE80211_CONF_PS);
+
+	if (wow->triggers_enabled) {
+		if (!local->ps_before_suspend) {
+			local->hw.conf.flags |= IEEE80211_CONF_PS;
+			ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+		}
+
+		del_timer_sync(&local->dynamic_ps_timer);
+		cancel_work_sync(&local->dynamic_ps_enable_work);
+
+		/*
+		 * Send nullfunc PS frame to AP so it can buffer frames for us,
+		 * unless we already are in that PS state. We'll discard all
+		 * frames except the ones our harware will process and use for
+		 * triggering a wake up.
+		 */
+		list_for_each_entry(sdata, &local->interfaces, list) {
+			struct ieee80211_if_managed *ifmgd;
+			if (sdata->dev != wow->netdev)
+				continue;
+			/* WoW only applies to STAs */
+			if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+				continue;
+			ifmgd = &sdata->u.mgd;
+			/*
+			 * cfg80211 should have cleared the
+			 * triggers upon disassociation.
+			 */
+			if (WARN_ON(!ifmgd->associated))
+				continue;
+			if (!local->ps_before_suspend)
+				ieee80211_send_nullfunc(local, sdata, 1);
+			wow_netdev_found = true;
+			break;
+		}
+
+		/*
+		 * WoW triggers should be cleared if the netdev claiming
+		 * it no longer exists
+		 */
+		WARN_ON(!wow_netdev_found);
+
+	}
+
+	if (wow_netdev_found)
+		printk(KERN_DEBUG "mac80211: WoW enabled interface found, "
+		       "will try to enable WoW during suspend\n");
+
+
+
 	ieee80211_stop_queues_by_reason(hw,
 			IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
@@ -69,6 +123,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
 		switch(sdata->vif.type) {
 		case NL80211_IFTYPE_STATION:
 			ieee80211_sta_quiesce(sdata);
+			/* Don't remove the interface when WoW is enabled */
+			if (sdata->dev != wow->netdev)
+				continue;
 			break;
 		case NL80211_IFTYPE_ADHOC:
 			ieee80211_ibss_quiesce(sdata);
@@ -94,9 +151,11 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
 		drv_remove_interface(local, &sdata->vif);
 	}
 
-	/* stop hardware - this must stop RX */
-	if (local->open_count)
-		ieee80211_stop_device(local);
+
+			if (wow_netdev_found)
+				ieee80211_stop_device(local, wow);
+			else if (local->open_count)
+				ieee80211_stop_device(local, NULL);
 
 	local->suspended = true;
 	/* need suspended to be visible before quiescing is false */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index bd40b11..bda9f53 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1083,26 +1083,30 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
 	return supp_rates;
 }
 
-void ieee80211_stop_device(struct ieee80211_local *local)
+void ieee80211_stop_device(struct ieee80211_local *local,  struct cfg80211_wow *wow)
 {
 	ieee80211_led_radio(local, false);
 
 	cancel_work_sync(&local->reconfig_filter);
 
 	flush_workqueue(local->workqueue);
-	drv_stop(local);
+	drv_stop(local, wow);
 }
 
-int ieee80211_reconfig(struct ieee80211_local *local)
+int ieee80211_reconfig(struct ieee80211_local *local, struct cfg80211_wow *wow)
 {
 	struct ieee80211_hw *hw = &local->hw;
 	struct ieee80211_sub_if_data *sdata;
 	struct sta_info *sta;
 	int res;
+	bool from_suspend = local->suspended;
 
 	if (local->suspended)
 		local->resuming = true;
 
+	if (from_suspend && local->ps_before_suspend)
+		local->hw.conf.flags |= IEEE80211_CONF_PS;
+
 	/* restart hardware */
 	if (local->open_count) {
 		/*
@@ -1122,11 +1126,16 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 		ieee80211_led_radio(local, true);
 	}
 
-	/* add interfaces */
+	/*
+	 * Add all interfaces back again. If we had enabled WoW we
+	 * don't need to add the interface as we never removed it
+	 * at suspend.
+	 */
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 		    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
-		    ieee80211_sdata_running(sdata))
+		    ieee80211_sdata_running(sdata) &&
+		    sdata->dev != wow->netdev)
 			res = drv_add_interface(local, &sdata->vif);
 	}
 
@@ -1235,6 +1244,18 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 		return 0;
 
 #ifdef CONFIG_PM
+
+	if (!local->ps_before_suspend) {
+		list_for_each_entry(sdata, &local->interfaces, list) {
+			struct ieee80211_if_managed *ifmgd;
+			if (sdata->vif.type != NL80211_IFTYPE_STATION)
+				continue;
+			ifmgd = &sdata->u.mgd;
+			if (ifmgd->associated)
+				ieee80211_send_nullfunc(local, sdata, 0);
+		}
+	}
+
 	/* first set suspended false, then resuming */
 	local->suspended = false;
 	mb();
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 58ab2c7..80c69b0 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -69,6 +69,9 @@ struct cfg80211_registered_device {
 
 	struct work_struct conn_work;
 	struct work_struct event_work;
+	
+	/* Used to keep track of user configurable triggers */
+	struct cfg80211_wow wow;
 
 	/* must be last because of the way we do wiphy_priv(),
 	 * and it should at least be aligned to NETDEV_ALIGN */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 85a23de..75c73b0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -142,6 +142,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
 	[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
 	[NL80211_ATTR_PID] = { .type = NLA_U32 },
+	[NL80211_ATTR_WOW_TRIGGERS_SUPPORTED] = { .type = NLA_U32 },
+	[NL80211_ATTR_WOW_TRIGGERS_ENABLED] = { .type = NLA_U32 },
 	[NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
 	[NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
 				 .len = WLAN_PMKID_LEN },
@@ -4470,6 +4472,153 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
 	return err;
 }
 
+
+static int nl80211_get_wow(struct sk_buff *skb,
+			   struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev;
+	struct net_device *dev;
+	struct wiphy *wiphy;
+	int err;
+	void *hdr;
+	struct sk_buff *msg;
+
+	rtnl_lock();
+	/* Look up our device */
+	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
+	if (err)
+		goto out_rtnl;
+
+	wiphy = &rdev->wiphy;
+
+	/* Draw up a netlink message to send back */
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg) {
+		err = -ENOBUFS;
+		goto out;
+	}
+	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
+			     NL80211_CMD_GET_WOW);
+	if (!hdr)
+		goto nla_put_failure;
+	NLA_PUT_U32(msg, NL80211_ATTR_WOW_TRIGGERS_SUPPORTED,
+		    wiphy->wow_triggers_supported);
+	NLA_PUT_U32(msg, NL80211_ATTR_WOW_TRIGGERS_ENABLED,
+		    rdev->wow.triggers_enabled);
+
+	genlmsg_end(msg, hdr);
+	err = genlmsg_reply(msg, info);
+	goto out;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	err = -EMSGSIZE;
+ out:
+	/* Cleanup */
+	cfg80211_unlock_rdev(rdev);
+	dev_put(dev);
+ out_rtnl:
+	rtnl_unlock();
+
+	return err;
+}
+
+static int nl80211_set_wow(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	struct cfg80211_registered_device *rdev;
+	struct net_device *dev;
+	struct wiphy *wiphy;
+	struct wireless_dev *wdev;
+	u32 triggers_requested;
+
+	if (!info->attrs[NL80211_ATTR_WOW_TRIGGERS_ENABLED])
+		return -EINVAL;
+
+	rtnl_lock();
+
+	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
+	if (err)
+		goto out_rtnl;
+
+	wiphy = &rdev->wiphy;
+
+	if (!wiphy->wow_triggers_supported) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	triggers_requested =
+		nla_get_u32(info->attrs[NL80211_ATTR_WOW_TRIGGERS_ENABLED]);
+
+	if (rdev->wow.netdev) {
+		if (rdev->wow.netdev != dev) {
+			err = -EALREADY;
+			goto out;
+		}
+		if (!triggers_requested) {
+			rdev->wow.triggers_enabled = 0;
+			rdev->wow.netdev = NULL;
+			goto out;
+		}
+	}
+
+	/* This would be a no-op as the rdev->wow should be unconfigured */
+	if (!triggers_requested)
+		goto out;
+
+	/* We only support magic packet right now */
+	if (triggers_requested & ~NL80211_WOW_TRIGGER_MAGIC_PACKET) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if ((triggers_requested & wiphy->wow_triggers_supported) !=
+	    triggers_requested) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	/*
+	 * It only makes sense to enable WoW if we're associated as a STA,
+	 * the AP should be buffering frames for us. We'll discard all frames
+	 * and only process the frames which will trigger us on in hardware.
+	 */
+	wdev = dev->ieee80211_ptr;
+
+	wdev_lock(wdev);
+
+	if (wdev->iftype != NL80211_IFTYPE_STATION) {
+		err = -EINVAL;
+		wdev_unlock(wdev);
+		goto out;
+	}
+
+	if (wdev->sme_state != CFG80211_SME_CONNECTED) {
+		err = -ENOTCONN;
+		wdev_unlock(wdev);
+		goto out;
+	}
+
+	wdev_unlock(wdev);
+
+	/*
+	 * Apply changes. This information gets passed to the
+	 * drivers during suspend.
+	 */
+	rdev->wow.netdev = dev;
+	rdev->wow.triggers_enabled = triggers_requested;
+
+ out:
+	/* cleanup */
+	cfg80211_unlock_rdev(rdev);
+	dev_put(dev);
+ out_rtnl:
+	rtnl_unlock();
+
+	return err;
+ }
+
 static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev;
@@ -5154,6 +5303,22 @@ static struct genl_ops nl80211_ops[] = {
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 	},
+
+
+	{
+		.cmd = NL80211_CMD_GET_WOW,
+		.doit = nl80211_get_wow,
+		.policy = nl80211_policy,
+		/* can be retrieved by unprivileged users */
+	},
+	{
+		.cmd = NL80211_CMD_SET_WOW,
+		.doit = nl80211_set_wow,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+
+
 	{
 		.cmd = NL80211_CMD_GET_INTERFACE,
 		.doit = nl80211_get_interface,
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index a8c2d6b..ec066a6 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -704,7 +704,21 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
 	wdev->wext.connect.ssid_len = 0;
 #endif
 
+/*
+	 * If we're not associated we cannot possibly get frames
+	 * to generate a WoW trigger. We also do this for security
+	 * purposes as with 802.11 we can roam to untrusted networks.
+	 * We require userspace to send a request to enable WoW for
+	 * each BSS.
+	 */
+	if (rdev->wow.netdev && rdev->wow.netdev == dev) {
+		rdev->wow.netdev = NULL;
+		rdev->wow.triggers_enabled = 0;
+	}
+
 	schedule_work(&cfg80211_disconnect_work);
+	
+
 }
 
 void cfg80211_disconnected(struct net_device *dev, u16 reason,
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 74a9e3c..31807e2 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -84,7 +84,7 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
 
 	if (rdev->ops->suspend) {
 		rtnl_lock();
-		ret = rdev->ops->suspend(&rdev->wiphy);
+		ret = rdev->ops->suspend(&rdev->wiphy, &rdev->wow);
 		rtnl_unlock();
 	}
 
@@ -103,7 +103,7 @@ static int wiphy_resume(struct device *dev)
 
 	if (rdev->ops->resume) {
 		rtnl_lock();
-		ret = rdev->ops->resume(&rdev->wiphy);
+		ret = rdev->ops->resume(&rdev->wiphy, &rdev->wow);
 		rtnl_unlock();
 	}
 
-- 
1.7.0.4


[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 7083 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [ath9k-devel] [PATCH 4/5] mac80211: add WoW support
  2010-09-14  9:53       ` AW: " Simsek, Burak
@ 2010-09-14 14:33         ` Luis R. Rodriguez
  0 siblings, 0 replies; 7+ messages in thread
From: Luis R. Rodriguez @ 2010-09-14 14:33 UTC (permalink / raw)
  To: Simsek, Burak; +Cc: Luis Rodriguez, linux-wireless

On Tue, Sep 14, 2010 at 2:53 AM, Simsek, Burak
<burak.simsek@fokus.fraunhofer.de> wrote:
> Hi Luis,
>
> so far we could not find any device that worked. We ordered new ones... Will let you know in case we get something working.
> Attached you can find two patch files. Since we could not get any device working yet, I am not sure whether the patch is prepared correctly. But all your previous changes (from the first patch file) should be in. And we did not get compilation errors.
>
> Apple is interesting. We might give it a try as well. I ordered 2 mini-pci cards from sparklan (http://www.sparklan.com/product.php?func=view&prod_id=63) and (http://www.oxfordtec.com/us/p127/SparkLAN-WMIA-199N-WLAN-802.11n-draft-wifi-%202.4/5Ghz-dual-band-3T/3R-Module-%28Atheros-AR9001-AR9160-XSPAN%29-Wireless-miniP%20CI-card/product_info.html ) that I hope support wow.

Can you re-spllit all the WoW patches as I did into separate patches
and post a link to a directoy where I can download each one?

  Luis

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-09-14 14:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <804B13F8F3D94A4AB18B9B01ACB68FA1037B5158@EXCHSRV.fokus.fraunhofer.de>
2010-07-27 17:20 ` [ath9k-devel] [PATCH 4/5] mac80211: add WoW support Luis R. Rodriguez
     [not found]   ` <804B13F8F3D94A4AB18B9B01ACB68FA1037B526B@EXCHSRV.fokus.fraunhofer.de>
2010-07-29 15:31     ` Luis R. Rodriguez
2010-07-29 20:56       ` Luis R. Rodriguez
2010-09-13 17:11   ` AW: " Simsek, Burak
2010-09-13 17:29     ` Luis R. Rodriguez
2010-09-14  9:53       ` AW: " Simsek, Burak
2010-09-14 14:33         ` Luis R. Rodriguez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).