Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v2] rtl8xxxu: Fix for agressive power saving by rtl8723bu wireless IC
From: John Heenan @ 2016-11-01  7:24 UTC (permalink / raw)
  To: Jes Sorensen, Kalle Valo, linux-wireless, netdev; +Cc: linux-kernel

The rtl8723bu wireless IC shows evidence of a more agressive approach to
power saving, powering down its RF side when there is no wireless
interfacing but leaving USB interfacing intact. This makes the wireless
IC more suitable for use in devices which need to keep their power use
as low as practical, such as tablets and Surface Pro type devices.

In effect this means that a full initialisation must be performed
whenever a wireless interface is brought up. It also means that
interpretations of power status from general wireless registers should
not be relied on to influence an init sequence.

The patch works by forcing a fuller initialisation and forcing it to
occur more often in code paths (such as occurs during a low level
authentication that initiates wireless interfacing).

The initialisation sequence is now more consistent with code based
directly on vendor code. For example while the vendor derived code
interprets a register as indcating a particular powered state, it does
not use this information to influence its init sequence.

Only devices that use the rtl8723bu driver are affected by this patch.

With this patch wpa_supplicant reliably and consistently connects with
an AP. Before a workaround such as executing rmmod and modprobe before
each call to wpa_supplicant worked with some distributions.

Signed-off-by: John Heenan <john@zgus.com>
---
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 04141e5..ab2f2ef 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -3900,7 +3900,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
 	 * Fix 92DU-VC S3 hang with the reason is that secondary mac is not
 	 * initialized. First MAC returns 0xea, second MAC returns 0x00
 	 */
-	if (val8 == 0xea)
+	if (val8 == 0xea || priv->fops == &rtl8723bu_fops)
 		macpower = false;
 	else
 		macpower = true;
@@ -5779,6 +5779,12 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw)
 
 	ret = 0;
 
+	if(priv->fops == &rtl8723bu_fops) {
+		ret = rtl8xxxu_init_device(hw);
+		if (ret)
+			goto error_out;
+	}
+
 	init_usb_anchor(&priv->rx_anchor);
 	init_usb_anchor(&priv->tx_anchor);
 	init_usb_anchor(&priv->int_anchor);
@@ -6080,9 +6086,11 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
 		goto exit;
 	}
 
-	ret = rtl8xxxu_init_device(hw);
-	if (ret)
-		goto exit;
+	if(priv->fops != &rtl8723bu_fops) {
+		ret = rtl8xxxu_init_device(hw);
+		if (ret)
+			goto exit;
+	}
 
 	hw->wiphy->max_scan_ssids = 1;
 	hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
-- 
2.10.1

^ permalink raw reply related

* Re: [PATCH v2] rtl8xxxu: Fix for agressive power saving by rtl8723bu wireless IC
From: Rafał Miłecki @ 2016-11-01  7:31 UTC (permalink / raw)
  To: John Heenan
  Cc: Jes Sorensen, Kalle Valo, linux-wireless@vger.kernel.org,
	Network Development, Linux Kernel Mailing List
In-Reply-To: <20161101072447.GA21575@cube>

On 1 November 2016 at 08:24, John Heenan <john@zgus.com> wrote:
> @@ -5779,6 +5779,12 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw)
>
>         ret =3D 0;
>
> +       if(priv->fops =3D=3D &rtl8723bu_fops) {

OK, let me be the first. Documentation/CodingStyle also says to use
space between "if" and "(" ;)


> @@ -6080,9 +6086,11 @@ static int rtl8xxxu_probe(struct usb_interface *in=
terface,
>                 goto exit;
>         }
>
> -       ret =3D rtl8xxxu_init_device(hw);
> -       if (ret)
> -               goto exit;
> +       if(priv->fops !=3D &rtl8723bu_fops) {

Same here.

I reviewed style only.

--=20
Rafa=C5=82

^ permalink raw reply

* "silent" TL-WDN4200 (RT593 usb) devices
From: Jonas Gorski @ 2016-11-01  9:33 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org
  Cc: Stanislaw Gruszka, Helmut Schaa, Gabor Juhos

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

Hi,

I have a bunch of rt5393 based TL-WDN4200 devices of which only one is
working as expected, and the rest fail to tx with rt2800-usb, using
latest master of lede (but also older verions). They are working fine
with the windows drivers.

Symptoms are:
1. Scanning works fine (so RX seems to work)
2. Trying to assoc in STA mode will time out
3. In AP mode it won't show up on scan by other devices

I tried listening with tcpdump (from an ath9k card, with encryption
disabled), but didn't see anything on the air from the non-working
sticks.

I also tried comparing the rt3593 ralink driver with rt2x00, and
couldn't find any differences on a first glance, so I'm a bit stumped.
Any pointers what else I can try/test would be good.

For comparison, I attached the eeprom contents from a working and a
non working stick, in hope it will help. If needed, I can try to
create a usb trace on windows.


Regards
Jonas

[-- Attachment #2: nonworking.txt --]
[-- Type: text/plain, Size: 2304 bytes --]

0:      0x3573 0x0100 0xdee8 0x2027
4:      0xafd4 0x0000 0x0000 0x0000
8:      0xffff 0xffff 0xffff 0xffff
12:     0xffff 0xffff 0xffff 0x0000
16:     0x0000 0x0000 0x0000 0x0000
20:     0x0000 0x0000 0x0000 0x0000
24:     0x0000 0x0000 0x0d33 0x008e
28:     0x0033 0x0000 0x0000 0x0601
32:     0xffff 0x0116 0x0124 0x5555
36:     0xbbd9 0xffbb 0x0a0a 0x0808
40:     0x0000 0x0000 0x0000 0x0000
44:     0x0000 0x0000 0x0000 0x0000
48:     0x0d0d 0x0e0d 0x0e0e 0x0f0e
52:     0x100f 0x1010 0x1010 0x0d0d
56:     0x0e0d 0x0e0e 0x0e0e 0x0f0f
60:     0x0f0f 0x0e0e 0x0d0d 0x0e0e
64:     0x0f0f 0x1010 0x1111 0x1212
68:     0x1111 0xb8c9 0x88a1 0x6871
72:     0x4555 0x0130 0x0500 0x0d0d
76:     0x0c0d 0x0c0c 0x0b0b 0x0b0b
80:     0x0a0a 0x0607 0x0606 0x0506
84:     0x0505 0x0405 0x0404 0x0303
88:     0x0303 0x0202 0x0101 0x0101
92:     0x0001 0x0000 0x0000 0x0000
96:     0x0000 0x0000 0x0000 0x0000
100:    0x0000 0x0707 0x0707 0x0707
104:    0x0707 0x0707 0x0707 0x0606
108:    0x0606 0x0606 0x0606 0x0606
112:    0x0506 0x0505 0x0505 0x0505
116:    0x0505 0x0505 0x0005 0x0000
120:    0x0000 0x0000 0x0000 0x0000
124:    0x0000 0x0000 0x0000 0x0808
128:    0x0808 0x0808 0x0808 0x0808
132:    0x0808 0x0808 0x0808 0x0808
136:    0x0808 0x0808 0x0808 0x0808
140:    0x0808 0x0808 0x0808 0x0808
144:    0x0008 0x0000 0x0000 0x0000
148:    0x0000 0x0000 0x0000 0x0000
152:    0x0000 0x0000 0xb8c9 0x88a2
156:    0x6571 0x4355 0x0135 0x0000
160:    0xac66 0x0668 0x68ac 0x8ac6
164:    0xac66 0x0668 0x68ac 0x0006
168:    0xac00 0x0668 0x68ac 0x8ac6
172:    0xac66 0x0668 0x68ac 0x0006
176:    0xac00 0x0668 0x68ac 0x8ac6
180:    0xac66 0x0668 0x68ac 0x0006
184:    0xac00 0x0668 0x68ac 0x8ac6
188:    0xac66 0x0668 0x68ac 0x0006
192:    0x0000 0x0000 0x0000 0x0000
196:    0x0000 0x0000 0x0000 0xffff
200:    0xffff 0xffff 0xffff 0xffff
204:    0xffff 0xffff 0xffff 0xffff
208:    0xffff 0xffff 0xffff 0xffff
212:    0xffff 0xffff 0xffff 0xffff
216:    0xffff 0xffff 0xffff 0xffff
220:    0xffff 0xffff 0xffff 0xffff
224:    0xffff 0xffff 0xffff 0xffff
228:    0xffff 0xffff 0xffff 0xffff
232:    0xffff 0xffff 0xffff 0xffff
236:    0xffff 0xffff 0xffff 0xffff
240:    0xffff 0xffff 0xffff 0xffff
244:    0xffff 0xffff 0xffff 0xffff
248:    0xffff 0xffff 0xffff 0xffff
252:    0xffff 0xffff 0xffff 0xffff

[-- Attachment #3: working.txt --]
[-- Type: text/plain, Size: 2304 bytes --]

0:      0x3573 0x0100 0xdee8 0x1d27
4:      0x1137 0x0000 0x0000 0x0000
8:      0xffff 0xffff 0xffff 0xffff
12:     0xffff 0xffff 0xffff 0x0000
16:     0x0000 0x0000 0x0000 0x0000
20:     0x0000 0x0000 0x0000 0x0000
24:     0x0000 0x0000 0x0d33 0x008e
28:     0x0033 0x0000 0x0000 0x0601
32:     0xffff 0x0116 0x0128 0x5555
36:     0xbbd9 0xffbb 0x0a0a 0x0808
40:     0x0000 0x0000 0x0000 0x0000
44:     0x0000 0x0000 0x0000 0x0000
48:     0x0c0c 0x0d0c 0x0d0d 0x0e0d
52:     0x0f0e 0x0f0f 0x0f0f 0x0d0d
56:     0x0e0e 0x0f0f 0x0f0f 0x1010
60:     0x1010 0x0f0f 0x0f0f 0x1010
64:     0x1111 0x1212 0x1313 0x1314
68:     0x1213 0xb8c9 0x88a1 0x6871
72:     0x4555 0x0130 0x0500 0x0d0d
76:     0x0c0d 0x0c0c 0x0b0b 0x0a0b
80:     0x0a0a 0x0606 0x0506 0x0505
84:     0x0404 0x0404 0x0303 0x0203
88:     0x0202 0x0101 0x0000 0x0000
92:     0x0000 0x0000 0x0000 0x0000
96:     0x0000 0x0000 0x0000 0x0000
100:    0x0000 0x0404 0x0404 0x0404
104:    0x0404 0x0404 0x0404 0x0303
108:    0x0303 0x0303 0x0303 0x0303
112:    0x0303 0x0303 0x0303 0x0303
116:    0x0303 0x0303 0x0003 0x0000
120:    0x0000 0x0000 0x0000 0x0000
124:    0x0000 0x0000 0x0000 0x0505
128:    0x0505 0x0505 0x0505 0x0505
132:    0x0505 0x0606 0x0606 0x0606
136:    0x0606 0x0606 0x0706 0x0707
140:    0x0707 0x0707 0x0707 0x0707
144:    0x0007 0x0000 0x0000 0x0000
148:    0x0000 0x0000 0x0000 0x0000
152:    0x0000 0x0000 0xb8c9 0x88a2
156:    0x6571 0x4355 0x0135 0x0000
160:    0xac66 0x0668 0x68ac 0x8ac6
164:    0xac66 0x0668 0x68ac 0x0006
168:    0xac00 0x0668 0x68ac 0x8ac6
172:    0xac66 0x0668 0x68ac 0x0006
176:    0xac00 0x0668 0x68ac 0x8ac6
180:    0xac66 0x0668 0x68ac 0x0006
184:    0xac00 0x0668 0x68ac 0x8ac6
188:    0xac66 0x0668 0x68ac 0x0006
192:    0x0000 0x0000 0x0000 0x0000
196:    0x0000 0x0000 0x0000 0xffff
200:    0xffff 0xffff 0xffff 0xffff
204:    0xffff 0xffff 0xffff 0xffff
208:    0xffff 0xffff 0xffff 0xffff
212:    0xffff 0xffff 0xffff 0xffff
216:    0xffff 0xffff 0xffff 0xffff
220:    0xffff 0xffff 0xffff 0xffff
224:    0xffff 0xffff 0xffff 0xffff
228:    0xffff 0xffff 0xffff 0xffff
232:    0xffff 0xffff 0xffff 0xffff
236:    0xffff 0xffff 0xffff 0xffff
240:    0xffff 0xffff 0xffff 0xffff
244:    0xffff 0xffff 0xffff 0xffff
248:    0xffff 0xffff 0xffff 0xffff
252:    0xffff 0xffff 0xffff 0xffff

^ permalink raw reply

* Re: [PATCH v2] rtl8xxxu: Fix for agressive power saving by rtl8723bu wireless IC
From: Barry Day @ 2016-11-01  9:54 UTC (permalink / raw)
  To: John Heenan; +Cc: Jes Sorensen, Kalle Valo, linux-wireless
In-Reply-To: <20161101072447.GA21575@cube>

On Tue, Nov 01, 2016 at 05:24:47PM +1000, John Heenan wrote:
> The rtl8723bu wireless IC shows evidence of a more agressive approach to
> power saving, powering down its RF side when there is no wireless
> interfacing but leaving USB interfacing intact. This makes the wireless
> IC more suitable for use in devices which need to keep their power use
> as low as practical, such as tablets and Surface Pro type devices.
> 
> In effect this means that a full initialisation must be performed
> whenever a wireless interface is brought up. It also means that
> interpretations of power status from general wireless registers should
> not be relied on to influence an init sequence.
> 
> The patch works by forcing a fuller initialisation and forcing it to
> occur more often in code paths (such as occurs during a low level
> authentication that initiates wireless interfacing).
> 
> The initialisation sequence is now more consistent with code based
> directly on vendor code. For example while the vendor derived code
> interprets a register as indcating a particular powered state, it does
> not use this information to influence its init sequence.
> 
> Only devices that use the rtl8723bu driver are affected by this patch.
> 
> With this patch wpa_supplicant reliably and consistently connects with
> an AP. Before a workaround such as executing rmmod and modprobe before
> each call to wpa_supplicant worked with some distributions.
> 
> Signed-off-by: John Heenan <john@zgus.com>
> ---
>  drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 16 ++++++++++++----
>  1 file changed, 12 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> index 04141e5..ab2f2ef 100644
> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
> @@ -3900,7 +3900,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
>  	 * Fix 92DU-VC S3 hang with the reason is that secondary mac is not
>  	 * initialized. First MAC returns 0xea, second MAC returns 0x00
>  	 */
> -	if (val8 == 0xea)
> +	if (val8 == 0xea || priv->fops == &rtl8723bu_fops)
>  		macpower = false;
>  	else
>  		macpower = true;
> @@ -5779,6 +5779,12 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw)
>  
>  	ret = 0;
>  
> +	if(priv->fops == &rtl8723bu_fops) {
> +		ret = rtl8xxxu_init_device(hw);
> +		if (ret)
> +			goto error_out;
> +	}
> +
>  	init_usb_anchor(&priv->rx_anchor);
>  	init_usb_anchor(&priv->tx_anchor);
>  	init_usb_anchor(&priv->int_anchor);
> @@ -6080,9 +6086,11 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
>  		goto exit;
>  	}
>  
> -	ret = rtl8xxxu_init_device(hw);
> -	if (ret)
> -		goto exit;
> +	if(priv->fops != &rtl8723bu_fops) {
> +		ret = rtl8xxxu_init_device(hw);
> +		if (ret)
> +			goto exit;
> +	}
>  
>  	hw->wiphy->max_scan_ssids = 1;
>  	hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
> -- 
> 2.10.1
> 

I've been trying similar modifications, testing them with the 8192eu and cu.
Basically I moved all the usb stuff out of start and stop and into probe and
disconnect. I moved the call to rtl8xxxu_init_device() from probe to
start.
Doing wpa_supplicant restart tests, the 8192cu still works everytime as it did
before. The 8192eu now works at least 50% of the time, and when it fails it's
now during the 4-way handshake phase which may be a separate issue confined to
the 8192eu only.
Note these results rely on changing the macpower test to this -
	if(val8 == 0xea || val8 == 0xff)
which is different again from what you are using so I'm of the opinion we
need to come up with a different way of telling whether the mac is powered.

^ permalink raw reply

* RE: [PATCH 02/12] mwifiex: check tx_hw_pending before downloading sleep confirm
From: Xinming Hu @ 2016-11-01 10:24 UTC (permalink / raw)
  To: Brian Norris, Xinming Hu
  Cc: Linux Wireless, Kalle Valo, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Shengzhen Li
In-Reply-To: <20161101001437.GB101079@google.com>

SGkgQnJhaW4sDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogbGludXgt
d2lyZWxlc3Mtb3duZXJAdmdlci5rZXJuZWwub3JnDQo+IFttYWlsdG86bGludXgtd2lyZWxlc3Mt
b3duZXJAdmdlci5rZXJuZWwub3JnXSBPbiBCZWhhbGYgT2YgQnJpYW4gTm9ycmlzDQo+IFNlbnQ6
IDIwMTbE6jEx1MIxyNUgODoxNQ0KPiBUbzogWGlubWluZyBIdQ0KPiBDYzogTGludXggV2lyZWxl
c3M7IEthbGxlIFZhbG87IERtaXRyeSBUb3Jva2hvdjsgQW1pdGt1bWFyIEthcndhcjsgQ2F0aHkg
THVvOw0KPiBTaGVuZ3poZW4gTGkNCj4gU3ViamVjdDogUmU6IFtQQVRDSCAwMi8xMl0gbXdpZmll
eDogY2hlY2sgdHhfaHdfcGVuZGluZyBiZWZvcmUgZG93bmxvYWRpbmcNCj4gc2xlZXAgY29uZmly
bQ0KPiANCj4gT24gTW9uLCBPY3QgMzEsIDIwMTYgYXQgMDQ6MDI6MTBQTSArMDgwMCwgWGlubWlu
ZyBIdSB3cm90ZToNCj4gPiBGcm9tOiBTaGVuZ3poZW4gTGkgPHN6bGlAbWFydmVsbC5jb20+DQo+
ID4NCj4gPiBUaGlzIHBhdGNoIHdpbGwgb25seSBhbGxvdyBkb3dubG9hZGluZyBzbGVlcCBjb25m
aXJtIHdoZW4gbm8gdHggZG9uZQ0KPiA+IGludGVycnVwdCBpcyBwZW5kaW5nIGluIHRoZSBoYXJk
d2FyZS4NCj4gPg0KPiA+IFNpZ25lZC1vZmYtYnk6IENhdGh5IEx1byA8Y2x1b0BtYXJ2ZWxsLmNv
bT4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBTaGVuZ3poZW4gTGkgPHN6bGlAbWFydmVsbC5jb20+DQo+
ID4NCj4gPiBDaGFuZ2UtSWQ6IEk2ZDY5NTViNGEyZGUwYWQ3OTFjYTI4ZjBmNjM1ZDYzNmEyYzdl
NDA2DQo+IA0KPiANCj4gXl4gUmVtb3ZlIHRoaXMNCj4gDQoNCk9rLCB3aWxsIHJlbW92ZSBpbiB1
cGRhdGVkIHZlcnNpb24hDQoNCj4gPiAtLS0NCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFy
dmVsbC9td2lmaWV4L2NtZGV2dC5jIHwgNCArKy0tDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNz
L21hcnZlbGwvbXdpZmlleC9pbml0LmMgICB8IDEgKw0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVz
cy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5oICAgfCAxICsNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxl
c3MvbWFydmVsbC9td2lmaWV4L3BjaWUuYyAgIHwgNSArKysrKw0KPiA+ICA0IGZpbGVzIGNoYW5n
ZWQsIDkgaW5zZXJ0aW9ucygrKSwgMiBkZWxldGlvbnMoLSkNCj4gPg0KPiA+IGRpZmYgLS1naXQg
YS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvY21kZXZ0LmMNCj4gPiBiL2Ry
aXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9jbWRldnQuYw0KPiA+IGluZGV4IDkw
NzViZTUuLjI1YTc0NzUgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFy
dmVsbC9td2lmaWV4L2NtZGV2dC5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFy
dmVsbC9td2lmaWV4L2NtZGV2dC5jDQo+ID4gQEAgLTExMTgsMTQgKzExMTgsMTQgQEAgbXdpZmll
eF9jYW5jZWxfcGVuZGluZ19pb2N0bChzdHJ1Y3QNCj4gPiBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0
ZXIpICB2b2lkICBtd2lmaWV4X2NoZWNrX3BzX2NvbmQoc3RydWN0DQo+ID4gbXdpZmlleF9hZGFw
dGVyICphZGFwdGVyKSAgew0KPiA+IC0JaWYgKCFhZGFwdGVyLT5jbWRfc2VudCAmJg0KPiA+ICsJ
aWYgKCFhZGFwdGVyLT5jbWRfc2VudCAmJiAhYXRvbWljX3JlYWQoJmFkYXB0ZXItPnR4X2h3X3Bl
bmRpbmcpICYmDQo+IA0KPiBIb3cgaXMgdGhpcyBkaWZmZXJlbnQgZnJvbSB0aGUgZm9sbG93aW5n
Pw0KPiANCj4gaHR0cHM6Ly9wYXRjaHdvcmsua2VybmVsLm9yZy9wYXRjaC85Mzg5NDg1Lw0KPiAN
Cj4gQW5kIHBhcml0dWNsYXJseSwgdGhleSBjb25mbGljdCBvbiB0aGlzIGxpbmUsIHNvIHlvdSBu
ZWVkIHRvIHJlc29sdmUgdGhhdA0KPiBzb21laG93Li4uDQo+IA0KPiBBbmQgaWYgdGhlIGxpbmtl
ZCBwYXRjaCBzZXJ2ZXMgdGhlIHNhbWUgcHVycG9zZSwgdGhlbiBJJ2QgcmF0aGVyIHRha2UgaXQs
IHNpbmNlDQo+IGl0J3MgbXVjaCBzaW1wbGVyLg0KPiANCj4gQnJpYW4NCj4gDQoNClRoaXMgcGF0
Y2ggaXMgYW4gZW5oYW5jZWQgdmVyc2lvbiBjb21wYXJlZCB3aXRoIGh0dHBzOi8vcGF0Y2h3b3Jr
Lmtlcm5lbC5vcmcvcGF0Y2gvOTM4OTQ4NS8gLCANCk13aWZpZXggcGNpZSB0cnkgdG8gImFnZ3Jl
Z2F0ZSIgdHggcmluZyBidWZmZXJzLCBiZWZvcmUgbm90aWZ5IGZpcm13YXJlIGRhdGEgcmVhZHku
DQpkYXRhX3NlbnQgd2lsbCBvbmx5IGJlIHNldCB0cnVlIHdoZW4gcGNpZSBhZ2dyZWdhdGlvbiBp
cyBkb25lLg0KRHVyaW5nIHRoZSAicGNpZSBhZ2dyZWdhdGlvbiIgc3RhZ2UsIGRhdGFfc2VudCBp
cyBub3Qgc2V0LCBkcml2ZXIgc3RpbGwgYmUgYWJsZSB0byBkb3dubG9hZCBzbGVlcCBjb25maXJt
IGluIGFub3RoZXIgdGhyZWFkLCANCkluIHRoaXMgY2FzZSwgd2Ugd2lsbCBzdGlsbCBtZWV0IGtl
cm5lbCBjcmFzaCBjYXVzZWQgYnkgY29uY3VycmVudCBleGVjdXRpb24gYmV0d2VlbiBQTSBoYW5k
c2hha2UgYW5kIHByb2Nlc3NpbmcgdHggZG9uZSBpbnRlcnJ1cHQuIA0KdHhfaHdfcGVuZGluZyB3
aWxsIGJlIGEgYmV0dGVyIHNvbHV0aW9uIHRvIG1hdGNoIHRoaXMgY2FzZS4gDQoNCj4gPiAgCSAg
ICAhYWRhcHRlci0+Y3Vycl9jbWQgJiYgIUlTX0NBUkRfUlhfUkNWRChhZGFwdGVyKSkNCj4gPiAg
CQltd2lmaWV4X2RubGRfc2xlZXBfY29uZmlybV9jbWQoYWRhcHRlcik7DQo+ID4gIAllbHNlDQo+
ID4gIAkJbXdpZmlleF9kYmcoYWRhcHRlciwgQ01ELA0KPiA+ICAJCQkgICAgImNtZDogRGVsYXkg
U2xlZXAgQ29uZmlybSAoJXMlcyVzJXMpXG4iLA0KPiA+ICAJCQkgICAgKGFkYXB0ZXItPmNtZF9z
ZW50KSA/ICJEIiA6ICIiLA0KPiA+IC0JCQkgICAgKGFkYXB0ZXItPmRhdGFfc2VudCkgPyAiVCIg
OiAiIiwNCj4gPiArCQkJICAgIGF0b21pY19yZWFkKCZhZGFwdGVyLT50eF9od19wZW5kaW5nKSA/
ICJUIiA6ICIiLA0KPiA+ICAJCQkgICAgKGFkYXB0ZXItPmN1cnJfY21kKSA/ICJDIiA6ICIiLA0K
PiA+ICAJCQkgICAgKElTX0NBUkRfUlhfUkNWRChhZGFwdGVyKSkgPyAiUiIgOiAiIik7ICB9IGRp
ZmYgLS1naXQNCj4gPiBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9pbml0
LmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9pbml0LmMNCj4g
PiBpbmRleCA4MjgzOWQ5Li5iMzZjYjNmIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dp
cmVsZXNzL21hcnZlbGwvbXdpZmlleC9pbml0LmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJl
bGVzcy9tYXJ2ZWxsL213aWZpZXgvaW5pdC5jDQo+ID4gQEAgLTI3MCw2ICsyNzAsNyBAQCBzdGF0
aWMgdm9pZCBtd2lmaWV4X2luaXRfYWRhcHRlcihzdHJ1Y3QNCj4gbXdpZmlleF9hZGFwdGVyICph
ZGFwdGVyKQ0KPiA+ICAJYWRhcHRlci0+YWRob2NfMTFuX2VuYWJsZWQgPSBmYWxzZTsNCj4gPg0K
PiA+ICAJbXdpZmlleF93bW1faW5pdChhZGFwdGVyKTsNCj4gPiArCWF0b21pY19zZXQoJmFkYXB0
ZXItPnR4X2h3X3BlbmRpbmcsIDApOw0KPiA+DQo+ID4gIAlzbGVlcF9jZm1fYnVmID0gKHN0cnVj
dCBtd2lmaWV4X29wdF9zbGVlcF9jb25maXJtICopDQo+ID4gIAkJCQkJYWRhcHRlci0+c2xlZXBf
Y2ZtLT5kYXRhOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxs
L213aWZpZXgvbWFpbi5oDQo+ID4gYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZp
ZXgvbWFpbi5oDQo+ID4gaW5kZXggZDYxZmUzYS4uN2Y2N2YyMyAxMDA2NDQNCj4gPiAtLS0gYS9k
cml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5oDQo+ID4gKysrIGIvZHJp
dmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21haW4uaA0KPiA+IEBAIC04NTcsNiAr
ODU3LDcgQEAgc3RydWN0IG13aWZpZXhfYWRhcHRlciB7DQo+ID4gIAlhdG9taWNfdCByeF9wZW5k
aW5nOw0KPiA+ICAJYXRvbWljX3QgdHhfcGVuZGluZzsNCj4gPiAgCWF0b21pY190IGNtZF9wZW5k
aW5nOw0KPiA+ICsJYXRvbWljX3QgdHhfaHdfcGVuZGluZzsNCj4gPiAgCXN0cnVjdCB3b3JrcXVl
dWVfc3RydWN0ICp3b3JrcXVldWU7DQo+ID4gIAlzdHJ1Y3Qgd29ya19zdHJ1Y3QgbWFpbl93b3Jr
Ow0KPiA+ICAJc3RydWN0IHdvcmtxdWV1ZV9zdHJ1Y3QgKnJ4X3dvcmtxdWV1ZTsgZGlmZiAtLWdp
dA0KPiA+IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3BjaWUuYw0KPiA+
IGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3BjaWUuYw0KPiA+IGluZGV4
IDA2M2M3MDcuLjRhYTVkOTEgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3Mv
bWFydmVsbC9td2lmaWV4L3BjaWUuYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21h
cnZlbGwvbXdpZmlleC9wY2llLmMNCj4gPiBAQCAtNTE2LDYgKzUxNiw3IEBAIHN0YXRpYyBpbnQg
bXdpZmlleF9wY2llX2VuYWJsZV9ob3N0X2ludChzdHJ1Y3QNCj4gbXdpZmlleF9hZGFwdGVyICph
ZGFwdGVyKQ0KPiA+ICAJCX0NCj4gPiAgCX0NCj4gPg0KPiA+ICsJYXRvbWljX3NldCgmYWRhcHRl
ci0+dHhfaHdfcGVuZGluZywgMCk7DQo+ID4gIAlyZXR1cm4gMDsNCj4gPiAgfQ0KPiA+DQo+ID4g
QEAgLTY4OSw2ICs2OTAsNyBAQCBzdGF0aWMgdm9pZCBtd2lmaWV4X2NsZWFudXBfdHhxX3Jpbmco
c3RydWN0DQo+IG13aWZpZXhfYWRhcHRlciAqYWRhcHRlcikNCj4gPiAgCQljYXJkLT50eF9idWZf
bGlzdFtpXSA9IE5VTEw7DQo+ID4gIAl9DQo+ID4NCj4gPiArCWF0b21pY19zZXQoJmFkYXB0ZXIt
PnR4X2h3X3BlbmRpbmcsIDApOw0KPiA+ICAJcmV0dXJuOw0KPiA+ICB9DQo+ID4NCj4gPiBAQCAt
MTEyNiw2ICsxMTI4LDcgQEAgc3RhdGljIGludCBtd2lmaWV4X3BjaWVfc2VuZF9kYXRhX2NvbXBs
ZXRlKHN0cnVjdA0KPiBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIpDQo+ID4gIAkJCQkJCQkgICAg
LTEpOw0KPiA+ICAJCQllbHNlDQo+ID4gIAkJCQltd2lmaWV4X3dyaXRlX2RhdGFfY29tcGxldGUo
YWRhcHRlciwgc2tiLCAwLCAwKTsNCj4gPiArCQkJYXRvbWljX2RlYygmYWRhcHRlci0+dHhfaHdf
cGVuZGluZyk7DQo+ID4gIAkJfQ0KPiA+DQo+ID4gIAkJY2FyZC0+dHhfYnVmX2xpc3Rbd3Jkb25l
aWR4XSA9IE5VTEw7IEBAIC0xMjE4LDYgKzEyMjEsNyBAQA0KPiA+IG13aWZpZXhfcGNpZV9zZW5k
X2RhdGEoc3RydWN0IG13aWZpZXhfYWRhcHRlciAqYWRhcHRlciwgc3RydWN0IHNrX2J1ZmYNCj4g
KnNrYiwNCj4gPiAgCQl3cmluZHggPSAoY2FyZC0+dHhiZF93cnB0ciAmIHJlZy0+dHhfbWFzaykg
Pj4gcmVnLT50eF9zdGFydF9wdHI7DQo+ID4gIAkJYnVmX3BhID0gTVdJRklFWF9TS0JfRE1BX0FE
RFIoc2tiKTsNCj4gPiAgCQljYXJkLT50eF9idWZfbGlzdFt3cmluZHhdID0gc2tiOw0KPiA+ICsJ
CWF0b21pY19pbmMoJmFkYXB0ZXItPnR4X2h3X3BlbmRpbmcpOw0KPiA+DQo+ID4gIAkJaWYgKHJl
Zy0+cGZ1X2VuYWJsZWQpIHsNCj4gPiAgCQkJZGVzYzIgPSBjYXJkLT50eGJkX3Jpbmdbd3JpbmR4
XTsNCj4gPiBAQCAtMTI5NSw2ICsxMjk5LDcgQEAgbXdpZmlleF9wY2llX3NlbmRfZGF0YShzdHJ1
Y3QgbXdpZmlleF9hZGFwdGVyDQo+ID4gKmFkYXB0ZXIsIHN0cnVjdCBza19idWZmICpza2IsDQo+
ID4gIGRvbmVfdW5tYXA6DQo+ID4gIAltd2lmaWV4X3VubWFwX3BjaV9tZW1vcnkoYWRhcHRlciwg
c2tiLCBQQ0lfRE1BX1RPREVWSUNFKTsNCj4gPiAgCWNhcmQtPnR4X2J1Zl9saXN0W3dyaW5keF0g
PSBOVUxMOw0KPiA+ICsJYXRvbWljX2RlYygmYWRhcHRlci0+dHhfaHdfcGVuZGluZyk7DQo+ID4g
IAlpZiAocmVnLT5wZnVfZW5hYmxlZCkNCj4gPiAgCQltZW1zZXQoZGVzYzIsIDAsIHNpemVvZigq
ZGVzYzIpKTsNCj4gPiAgCWVsc2UNCj4gPiAtLQ0KPiA+IDEuOC4xLjQNCj4gPg0KDQpCZXN0IFJl
Z2FyZHMsDQpYaW5taW5nDQoNCg==

^ permalink raw reply

* RE: [PATCH 01/12] mwifiex: fix power save issue when suspend
From: Xinming Hu @ 2016-11-01 10:26 UTC (permalink / raw)
  To: Brian Norris, Xinming Hu
  Cc: Linux Wireless, Kalle Valo, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Shengzhen Li
In-Reply-To: <20161031235712.GA101079@google.com>

SGkgQnJpYW4sDQoNClRoYW5rcyBmb3IgcmV2aWV3LCB3ZSB3aWxsIGFkZHJlc3MgeW91ciBjb21t
ZW50cyBpbiB1cGRhdGVkIHZlcnNpb24uDQpTaW5jZSB3ZSBoYXZlIGFuIGVuaGFuY2VkIHZlcmlz
b24gZm9yIEZST01MSVNUOiBtd2lmaWV4OiBmaXggY29ybmVyIGNhc2UsIA0KdGhhdCBpcyBodHRw
czovL3BhdGNod29yay5rZXJuZWwub3JnL3BhdGNoLzk0MDUxMTkvICwNCnRoZSB1cGRhdGVkIHBh
dGNoIHdpbGwgYmUgcmVvcmdhbml6ZWQgdG8gZm9sbG93IGFib3ZlIHBhdGNoLg0KDQo+IC0tLS0t
T3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IGxpbnV4LXdpcmVsZXNzLW93bmVyQHZnZXIu
a2VybmVsLm9yZw0KPiBbbWFpbHRvOmxpbnV4LXdpcmVsZXNzLW93bmVyQHZnZXIua2VybmVsLm9y
Z10gT24gQmVoYWxmIE9mIEJyaWFuIE5vcnJpcw0KPiBTZW50OiAyMDE2xOoxMdTCMcjVIDc6NTcN
Cj4gVG86IFhpbm1pbmcgSHUNCj4gQ2M6IExpbnV4IFdpcmVsZXNzOyBLYWxsZSBWYWxvOyBEbWl0
cnkgVG9yb2tob3Y7IEFtaXRrdW1hciBLYXJ3YXI7IENhdGh5IEx1bzsNCj4gU2hlbmd6aGVuIExp
DQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggMDEvMTJdIG13aWZpZXg6IGZpeCBwb3dlciBzYXZlIGlz
c3VlIHdoZW4gc3VzcGVuZA0KPiANCj4gSGksDQo+IA0KPiBPbiBNb24sIE9jdCAzMSwgMjAxNiBh
dCAwNDowMjowOVBNICswODAwLCBYaW5taW5nIEh1IHdyb3RlOg0KPiA+IEZyb206IFNoZW5nemhl
biBMaSA8c3psaUBtYXJ2ZWxsLmNvbT4NCj4gPg0KPiA+IFRoaXMgcGF0Y2ggZml4ZXMgYSBjb3Ju
ZXIgY2FzZSBmb3IgIkZST01MSVNUOiBtd2lmaWV4OiBmaXggY29ybmVyIGNhc2UNCj4gDQo+IFVw
c3RyZWFtIHBhdGNoZXMgZG9uJ3Qgbm9ybWFsbHkgZ2V0IGEgJ0ZST01MSVNUJyB0YWcgd2hpbGUg
eW91J3JlIHNlbmRpbmcNCj4gdGhlbSB0byB0aGUgbWFpbGluZyBsaXN0IDopIFRoYXQgZGVzaWdu
YXRpb24gaXMgdXNlZCBmb3IgQ2hyb21lIE9TIHRyZWVzLCBzbyB3ZQ0KPiBrbm93IHdoZXJlIHRv
IGZpbmQgdGhlIHBhdGNoIHNvdXJjZS4gQnV0IHRoZSB1cHN0cmVhbSBtYWlsaW5nIGxpc3QgKmlz
KiB0aGUNCj4gc291cmNlLg0KPiANCj4gPiBwb3dlciBzYXZlIGlzc3VlIiwgbWFpbiBwcm9jZXNz
IHdpbGwgY2hlY2sgdGhlIHBvd2VyIHNhdmUgY29uZGl0aW9uIGluDQo+ID4gUFNfUFJFX1NMRUVQ
IHN0YXR1cyBzbyB0aGUgc2xlZXAgaGFuZHNoYWtlIGNvdWxkIGNvbnRpbnVlLg0KPiA+DQo+ID4g
U2lnbmVkLW9mZi1ieTogQ2F0aHkgTHVvIDxjbHVvQG1hcnZlbGwuY29tPg0KPiA+IFNpZ25lZC1v
ZmYtYnk6IFNoZW5nemhlbiBMaSA8c3psaUBtYXJ2ZWxsLmNvbT4NCj4gPiBTaWduZWQtb2ZmLWJ5
OiBBbWl0a3VtYXIgS2Fyd2FyIDxha2Fyd2FyQG1hcnZlbGwuY29tPg0KPiA+DQo+ID4gQlVHPWNo
cm9tZS1vcy1wYXJ0bmVyOjU4MTY0DQo+ID4gVEVTVD1zdHJlc3MgV2lmaSB3LyBwb3dlcl9zYXZl
IGVuYWJsZWQNCj4gPg0KPiA+IENoYW5nZS1JZDogSTVhMzZkOWVhZWI3ZmU1ZmFhY2NjNTMzZTBk
MWJhMWYzMjUzNjY2ZGMNCj4gDQo+IEluIHRoZSBzYW1lIHZlaW46IHdoaWxlIEknbSBoYXBweSB0
byBoYXZlIHRoZSBCVUc9LCBURVNUPSwgYW5kIEdlcnJpdA0KPiBDaGFuZ2UtSUQgZm9yIG91ciBD
aHJvbWUgT1MgdHJlZSwgSSBkb24ndCB0aGluayB1cHN0cmVhbSByZXZpZXdlcnMgdHlwaWNhbGx5
DQo+IGNhcmUgYWJvdXQgdGhvc2UuIFBsZWFzZSByZW1vdmUgdGhvc2UgZnJvbSB1cHN0cmVhbSBz
dWJtaXNzaW9ucyBsaWtlIHRoaXMuDQo+IA0KPiAoU2FtZSBhcHBsaWVzIHRvIHRoZSByZXN0IG9m
IHRoaXMgc2VyaWVzLiBBbHNvLCBjb25zaWRlciBydW5uaW5nDQo+IHNjcmlwdHMvY2hlY2twYXRj
aC5wbC4gSXQgd2lsbCBhdCBsZWFzdCByZW1pbmQgeW91IGFib3V0IHJlbW92aW5nIHRoZSBHZXJy
aXQNCj4gQ2hhbmdlLUlELikNCj4gDQo+ID4gLS0tDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNz
L21hcnZlbGwvbXdpZmlleC9jbWRldnQuYyB8IDMgKystDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVs
ZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmMgICB8IDUgKysrKysNCj4gPiAgMiBmaWxlcyBjaGFu
Z2VkLCA3IGluc2VydGlvbnMoKyksIDEgZGVsZXRpb24oLSkNCj4gPg0KPiA+IGRpZmYgLS1naXQg
YS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvY21kZXZ0LmMNCj4gPiBiL2Ry
aXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9jbWRldnQuYw0KPiA+IGluZGV4IDUz
NDc3MjguLjkwNzViZTUgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFy
dmVsbC9td2lmaWV4L2NtZGV2dC5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFy
dmVsbC9td2lmaWV4L2NtZGV2dC5jDQo+ID4gQEAgLTExMjMsOCArMTEyMyw5IEBAIG13aWZpZXhf
Y2hlY2tfcHNfY29uZChzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyDQo+ICphZGFwdGVyKQ0KPiA+ICAJ
CW13aWZpZXhfZG5sZF9zbGVlcF9jb25maXJtX2NtZChhZGFwdGVyKTsNCj4gPiAgCWVsc2UNCj4g
PiAgCQltd2lmaWV4X2RiZyhhZGFwdGVyLCBDTUQsDQo+ID4gLQkJCSAgICAiY21kOiBEZWxheSBT
bGVlcCBDb25maXJtICglcyVzJXMpXG4iLA0KPiA+ICsJCQkgICAgImNtZDogRGVsYXkgU2xlZXAg
Q29uZmlybSAoJXMlcyVzJXMpXG4iLA0KPiA+ICAJCQkgICAgKGFkYXB0ZXItPmNtZF9zZW50KSA/
ICJEIiA6ICIiLA0KPiA+ICsJCQkgICAgKGFkYXB0ZXItPmRhdGFfc2VudCkgPyAiVCIgOiAiIiwN
Cj4gPiAgCQkJICAgIChhZGFwdGVyLT5jdXJyX2NtZCkgPyAiQyIgOiAiIiwNCj4gPiAgCQkJICAg
IChJU19DQVJEX1JYX1JDVkQoYWRhcHRlcikpID8gIlIiIDogIiIpOyAgfSBkaWZmIC0tZ2l0DQo+
ID4gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5jDQo+ID4gYi9k
cml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5jDQo+ID4gaW5kZXggMjQ3
OGNjZC4uZjU1OWVhZCAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2
ZWxsL213aWZpZXgvbWFpbi5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVs
bC9td2lmaWV4L21haW4uYw0KPiA+IEBAIC0zMDgsNiArMzA4LDExIEBAIHByb2Nlc3Nfc3RhcnQ6
DQo+ID4gIAkJCS8qIFdlIGhhdmUgdHJpZWQgdG8gd2FrZXVwIHRoZSBjYXJkIGFscmVhZHkgKi8N
Cj4gPiAgCQkJaWYgKGFkYXB0ZXItPnBtX3dha2V1cF9md190cnkpDQo+ID4gIAkJCQlicmVhazsN
Cj4gPiArCQkJaWYgKGFkYXB0ZXItPnBzX3N0YXRlID09IFBTX1NUQVRFX1BSRV9TTEVFUCkgew0K
PiA+ICsJCQkJaWYgKCFhZGFwdGVyLT5jbWRfc2VudCAmJiAhYWRhcHRlci0+Y3Vycl9jbWQpDQo+
IA0KPiBUaGUgZW50aXJlICdpZicgY29uZGl0aW9uIGlzIHVubmVjZXNzYXJ5LiBUaGF0J3MgYWxs
IGNoZWNrZWQgYWxyZWFkeSB3aXRoaW4NCj4gbXdpZmlleF9jaGVja19wc19jb25kKCkuDQo+IA0K
PiBCcmlhbg0KPiANCj4gPiArCQkJCQltd2lmaWV4X2NoZWNrX3BzX2NvbmQoYWRhcHRlcik7DQo+
ID4gKwkJCX0NCj4gPiArDQo+ID4gIAkJCWlmIChhZGFwdGVyLT5wc19zdGF0ZSAhPSBQU19TVEFU
RV9BV0FLRSkNCj4gPiAgCQkJCWJyZWFrOw0KPiA+ICAJCQlpZiAoYWRhcHRlci0+dHhfbG9ja19m
bGFnKSB7DQo+ID4gLS0NCj4gPiAxLjguMS40DQo+ID4NCg0KQmVzdCBSZWdhcmRzLA0KU2ltb24N
Cg==

^ permalink raw reply

* [PATCH 2/2] net: rfkill-regulator: Add devicetree support
From: Paul Cercueil @ 2016-11-01 10:58 UTC (permalink / raw)
  To: Johannes Berg, David S . Miller, Rob Herring, Mark Rutland,
	netdev, devicetree, linux-kernel, linux-wireless
  Cc: Maarten ter Huurne, Paul Cercueil
In-Reply-To: <20161101105840.24313-1-paul@crapouillou.net>

This commit adds the support for probing the rfkill-regulator
from devicetree.

Information about the devicetree bindings can be found here:
Documentation/devicetree/bindings/net/rfkill-regulator.txt

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 net/rfkill/rfkill-regulator.c | 43 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c
index 50cd26a..29ded4c 100644
--- a/net/rfkill/rfkill-regulator.c
+++ b/net/rfkill/rfkill-regulator.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
@@ -60,24 +61,38 @@ static struct rfkill_ops rfkill_regulator_ops = {
 static int rfkill_regulator_probe(struct platform_device *pdev)
 {
 	struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data;
+	struct device_node *node = pdev->dev.of_node;
 	struct rfkill_regulator_data *rfkill_data;
 	struct regulator *vcc;
 	struct rfkill *rf_kill;
+	const char *name;
+	u32 type;
 	int ret = 0;
 
-	if (pdata == NULL) {
+	if (pdata) {
+		if (!pdata->name || !pdata->type) {
+			dev_err(&pdev->dev, "invalid name or type in platform data\n");
+			return -EINVAL;
+		}
+
+		name = pdata->name;
+		type = pdata->type;
+	} else if (node) {
+		ret = of_property_read_u32(node, "rfkill-type", &type);
+		if (ret < 0)
+			return ret;
+
+		ret = of_property_read_string(node, "rfkill-name", &name);
+		if (ret < 0)
+			return ret;
+	} else {
 		dev_err(&pdev->dev, "no platform data\n");
 		return -ENODEV;
 	}
 
-	if (pdata->name == NULL || pdata->type == 0) {
-		dev_err(&pdev->dev, "invalid name or type in platform data\n");
-		return -EINVAL;
-	}
-
 	vcc = regulator_get_exclusive(&pdev->dev, "vrfkill");
 	if (IS_ERR(vcc)) {
-		dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
+		dev_err(&pdev->dev, "Cannot get vcc for %s\n", name);
 		ret = PTR_ERR(vcc);
 		goto out;
 	}
@@ -88,9 +103,8 @@ static int rfkill_regulator_probe(struct platform_device *pdev)
 		goto err_data_alloc;
 	}
 
-	rf_kill = rfkill_alloc(pdata->name, &pdev->dev,
-				pdata->type,
-				&rfkill_regulator_ops, rfkill_data);
+	rf_kill = rfkill_alloc(name, &pdev->dev, type,
+			       &rfkill_regulator_ops, rfkill_data);
 	if (rf_kill == NULL) {
 		ret = -ENOMEM;
 		goto err_rfkill_alloc;
@@ -110,7 +124,7 @@ static int rfkill_regulator_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, rfkill_data);
-	dev_info(&pdev->dev, "%s initialized\n", pdata->name);
+	dev_info(&pdev->dev, "%s initialized\n", name);
 
 	return 0;
 
@@ -137,11 +151,18 @@ static int rfkill_regulator_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id rfkill_regulator_of_match[] = {
+	{ .compatible = "rfkill-regulator" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rfkill_regulator_of_match);
+
 static struct platform_driver rfkill_regulator_driver = {
 	.probe = rfkill_regulator_probe,
 	.remove = rfkill_regulator_remove,
 	.driver = {
 		.name = "rfkill-regulator",
+		.of_match_table = of_match_ptr(rfkill_regulator_of_match),
 	},
 };
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH 1/2] Documentation: devicetree: Add bindings info for rfkill-regulator
From: Paul Cercueil @ 2016-11-01 10:58 UTC (permalink / raw)
  To: Johannes Berg, David S . Miller, Rob Herring, Mark Rutland,
	netdev, devicetree, linux-kernel, linux-wireless
  Cc: Maarten ter Huurne, Paul Cercueil

This document gives information about how to write a devicetree
node that corresponds to the rfkill-regulator driver.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 .../devicetree/bindings/net/rfkill-regulator.txt       | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/rfkill-regulator.txt

diff --git a/Documentation/devicetree/bindings/net/rfkill-regulator.txt b/Documentation/devicetree/bindings/net/rfkill-regulator.txt
new file mode 100644
index 0000000..aac2fe1
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/rfkill-regulator.txt
@@ -0,0 +1,18 @@
+Device tree bindings for the rfkill-regulator driver
+
+Required properties:
+  - compatible:	should be "rfkill-regulator"
+  - rfkill-name:	the name of this rfkill device
+  - rfkill-type:	the type of this rfkill device;
+			must correspond to a valid rfkill_type from <uapi/linux/rfkill.h>
+  - vrfkill-supply:	phandle to a regulator
+
+Example:
+
+	wlan-rfkill {
+		compatible = "rfkill-regulator";
+		rfkill-name = "WLAN power switch";
+		rfkill-type = <1>;
+
+		vrfkill-supply = <&wlan_power>;
+	};
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 01/12] mwifiex: check tx_hw_pending before downloading sleep confirm
From: Xinming Hu @ 2016-11-01 12:08 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Shengzhen Li, Xinming Hu

From: Shengzhen Li <szli@marvell.com>

We may get SLEEP event from firmware even if TXDone interrupt
for last Tx packet is still pending. In this case, we may
end up accessing PCIe memory for handling TXDone after power
save handshake is completed. This causes kernel crash with
external abort.

This patch will only allow downloading sleep confirm
when no tx done interrupt is pending in the hardware.

---
v2: address format issues(Brain)
---
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Shengzhen Li <szli@marvell.com>
Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
 drivers/net/wireless/marvell/mwifiex/cmdevt.c | 5 +++--
 drivers/net/wireless/marvell/mwifiex/init.c   | 1 +
 drivers/net/wireless/marvell/mwifiex/main.h   | 1 +
 drivers/net/wireless/marvell/mwifiex/pcie.c   | 5 +++++
 4 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 5347728..25a7475 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -1118,13 +1118,14 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
 void
 mwifiex_check_ps_cond(struct mwifiex_adapter *adapter)
 {
-	if (!adapter->cmd_sent &&
+	if (!adapter->cmd_sent && !atomic_read(&adapter->tx_hw_pending) &&
 	    !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter))
 		mwifiex_dnld_sleep_confirm_cmd(adapter);
 	else
 		mwifiex_dbg(adapter, CMD,
-			    "cmd: Delay Sleep Confirm (%s%s%s)\n",
+			    "cmd: Delay Sleep Confirm (%s%s%s%s)\n",
 			    (adapter->cmd_sent) ? "D" : "",
+			    atomic_read(&adapter->tx_hw_pending) ? "T" : "",
 			    (adapter->curr_cmd) ? "C" : "",
 			    (IS_CARD_RX_RCVD(adapter)) ? "R" : "");
 }
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index 82839d9..b36cb3f 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -270,6 +270,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
 	adapter->adhoc_11n_enabled = false;
 
 	mwifiex_wmm_init(adapter);
+	atomic_set(&adapter->tx_hw_pending, 0);
 
 	sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *)
 					adapter->sleep_cfm->data;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index d61fe3a..7f67f23 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -857,6 +857,7 @@ struct mwifiex_adapter {
 	atomic_t rx_pending;
 	atomic_t tx_pending;
 	atomic_t cmd_pending;
+	atomic_t tx_hw_pending;
 	struct workqueue_struct *workqueue;
 	struct work_struct main_work;
 	struct workqueue_struct *rx_workqueue;
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 063c707..4aa5d91 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -516,6 +516,7 @@ static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
 		}
 	}
 
+	atomic_set(&adapter->tx_hw_pending, 0);
 	return 0;
 }
 
@@ -689,6 +690,7 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
 		card->tx_buf_list[i] = NULL;
 	}
 
+	atomic_set(&adapter->tx_hw_pending, 0);
 	return;
 }
 
@@ -1126,6 +1128,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
 							    -1);
 			else
 				mwifiex_write_data_complete(adapter, skb, 0, 0);
+			atomic_dec(&adapter->tx_hw_pending);
 		}
 
 		card->tx_buf_list[wrdoneidx] = NULL;
@@ -1218,6 +1221,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
 		wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
 		buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 		card->tx_buf_list[wrindx] = skb;
+		atomic_inc(&adapter->tx_hw_pending);
 
 		if (reg->pfu_enabled) {
 			desc2 = card->txbd_ring[wrindx];
@@ -1295,6 +1299,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
 done_unmap:
 	mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
 	card->tx_buf_list[wrindx] = NULL;
+	atomic_dec(&adapter->tx_hw_pending);
 	if (reg->pfu_enabled)
 		memset(desc2, 0, sizeof(*desc2));
 	else
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 02/12] mwifiex: complete blocked power save handshake in main process
From: Xinming Hu @ 2016-11-01 12:08 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Shengzhen Li, Xinming Hu
In-Reply-To: <1478002098-14189-1-git-send-email-huxinming820@marvell.com>

From: Shengzhen Li <szli@marvell.com>

Power save handshake with firmware might be blocked by on-going
data transfer.
this patch check the PS status in main process and complete
previous blocked PS handshake.
this patch also remove redudant check before call
mwifiex_check_ps_cond fuction.

---
v2: 1. remove redudant check(Brain)
	3. reorgnized to follow tx_hw_pending patch
---
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Shengzhen Li <szli@marvell.com>
Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
---
 drivers/net/wireless/marvell/mwifiex/main.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 2478ccd..d700c44 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -308,6 +308,9 @@ process_start:
 			/* We have tried to wakeup the card already */
 			if (adapter->pm_wakeup_fw_try)
 				break;
+			if (adapter->ps_state == PS_STATE_PRE_SLEEP)
+				mwifiex_check_ps_cond(adapter);
+
 			if (adapter->ps_state != PS_STATE_AWAKE)
 				break;
 			if (adapter->tx_lock_flag) {
@@ -355,10 +358,8 @@ process_start:
 
 		/* Check if we need to confirm Sleep Request
 		   received previously */
-		if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
-			if (!adapter->cmd_sent && !adapter->curr_cmd)
-				mwifiex_check_ps_cond(adapter);
-		}
+		if (adapter->ps_state == PS_STATE_PRE_SLEEP)
+			mwifiex_check_ps_cond(adapter);
 
 		/* * The ps_state may have been changed during processing of
 		 * Sleep Request event.
-- 
1.8.1.4

^ permalink raw reply related

* Re: "silent" TL-WDN4200 (RT593 usb) devices
From: Stanislaw Gruszka @ 2016-11-01 12:38 UTC (permalink / raw)
  To: Jonas Gorski; +Cc: linux-wireless@vger.kernel.org, Helmut Schaa, Gabor Juhos
In-Reply-To: <CAOiHx=nbLZHW94MF+ki8CXO9n_S5b26t1O9p_pFPu6Z1mZmOtw@mail.gmail.com>

Hi

On Tue, Nov 01, 2016 at 10:33:14AM +0100, Jonas Gorski wrote:
> I have a bunch of rt5393 based TL-WDN4200 devices of which only one is
> working as expected, and the rest fail to tx with rt2800-usb, using
> latest master of lede (but also older verions). They are working fine
> with the windows drivers.
> 
> Symptoms are:
> 1. Scanning works fine (so RX seems to work)
> 2. Trying to assoc in STA mode will time out
> 3. In AP mode it won't show up on scan by other devices
> 
> I tried listening with tcpdump (from an ath9k card, with encryption
> disabled), but didn't see anything on the air from the non-working
> sticks.
> 
> I also tried comparing the rt3593 ralink driver with rt2x00, and
> couldn't find any differences on a first glance, so I'm a bit stumped.
> Any pointers what else I can try/test would be good.
> 
> For comparison, I attached the eeprom contents from a working and a
> non working stick, in hope it will help. 

I can not see anything unusual in EEPROM dumps and I not sure if
that makes difference. It could not be a good idea, but you can
try to hardcode EEPROM from good device in the driver and
run that on bad device and see what happens.

>If needed, I can try to
> create a usb trace on windows.

I have dump tool for compare registers programing of ralink usb
drivers, however it works with linux usbmon (I use it compare
vendor linux driver with rt2x00). Not sure how much changes
it will require to make it work with usb dump from windows.

https://github.com/sgruszka/rt2x00usb_dump

Stanislaw

^ permalink raw reply

* [PATCH net-next] rtl8xxxu: Fix non static symbol warning
From: Wei Yongjun @ 2016-11-01 14:48 UTC (permalink / raw)
  To: Jes Sorensen, Kalle Valo; +Cc: Wei Yongjun, linux-wireless

From: Wei Yongjun <weiyongjun1@huawei.com>

Fixes the following sparse warning:

drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c:1559:6: warning:
 symbol 'rtl8192eu_power_off' was not declared. Should it be static?

Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
index a793fed..a1178c5 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
@@ -1556,7 +1556,7 @@ static int rtl8192eu_power_on(struct rtl8xxxu_priv *priv)
 	return ret;
 }
 
-void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
+static void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
 {
 	u8 val8;
 	u16 val16;

^ permalink raw reply related

* [PATCH net-next] rtlwifi: Use dev_kfree_skb_irq instead of kfree_skb
From: Wei Yongjun @ 2016-11-01 14:48 UTC (permalink / raw)
  To: Larry Finger, Chaoming Li, Kalle Valo; +Cc: Wei Yongjun, linux-wireless

From: Wei Yongjun <weiyongjun1@huawei.com>

It is not allowed to call kfree_skb() from hardware interrupt
context or with interrupts being disabled, spin_lock_irqsave()
make sure always in irq disable context. So the kfree_skb()
should be replaced with dev_kfree_skb_irq().

This is detected by Coccinelle semantic patch.

Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
 drivers/net/wireless/realtek/rtlwifi/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index 8e7f23c..e89681d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1832,7 +1832,7 @@ bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
 
 	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 	pskb = __skb_dequeue(&ring->queue);
-	kfree_skb(pskb);
+	dev_kfree_skb_irq(pskb);
 
 	/*this is wrong, fill_tx_cmddesc needs update*/
 	pdesc = &ring->desc[0];

^ permalink raw reply related

* RE: [PATCH 1/2] mwifiex: fix corner case power save issue
From: Amitkumar Karwar @ 2016-11-01 16:41 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org
  Cc: Cathy Luo, Nishant Sarmukadam, Brian Norris, Xinming Hu
In-Reply-To: <1477062948-8558-1-git-send-email-akarwar@marvell.com>

Hi Kalle,

> From: Amitkumar Karwar [mailto:akarwar@marvell.com]
> Sent: Friday, October 21, 2016 8:46 PM
> To: linux-wireless@vger.kernel.org
> Cc: Cathy Luo; Nishant Sarmukadam; Amitkumar Karwar
> Subject: [PATCH 1/2] mwifiex: fix corner case power save issue
> 
> We may get SLEEP event from firmware even if TXDone for last Tx packet
> is still pending. In this case, we may end up accessing PCIe memory for
> handling TXDone after power save handshake is completed. This causes
> kernel crash with external abort.
> 
> We will delay sending SLEEP confirm to firmware in this case to resolve
> the problem.
> 
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> ---
>  drivers/net/wireless/marvell/mwifiex/cmdevt.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Please drop this patch.
Xinming Hu has better and complete solution for this issue as discussed at https://patchwork.kernel.org/patch/9405119/

Regards,
Amitkumar

^ permalink raw reply

* Re: [PATCH] rtl8xxxu: Fix for agressive power saving by rtl8723bu wireless IC
From: John Heenan @ 2016-11-02  1:13 UTC (permalink / raw)
  To: Jes Sorensen, Barry Day, Rafał Miłecki
  Cc: Kalle Valo, linux-wireless, netdev, linux-kernel
In-Reply-To: <CAAye0QNjYY5gBzSdc+0_rhy1OHk7iQ-CVp0Svph1DR7+mgVWGg@mail.gmail.com>

Barry Day has submitted real world reports for the 8192eu and 8192cu.
This needs to be acknowledged. I have submitted real world reports for
the 8723bu.

When it comes down to it, it looks like the kernel code changes are
really going to be very trivial to fix this problem and we need to
take the focus off dramatic outbursts over style issues to a strategy
for getting usable results from real world testing.

Addressing style issues in a dramatic manner to me looks like a mean
sport for maintainers who line up to easy target first time
contributors. This mean attitude comes from the top with a well known
comment about "publicly making fun of people". The polite comments
over style from Joe Perches and Rafa=C5=82 Mi=C5=82ecki are welcomed.

An effective strategy would be to insert some printk statements to
trace what init steps vendor derived drivers do each time
wpa_supplicant is called and ask real world testers to report their
results. This is a lot more productive and less error prone than
laboriously pouring over vendor source code. Alternative drivers that
use vendor code from Realtek is enormously complicated and a huge pain
to make sense of.

Joe Sorensen's driver code is far easier to make sense of and it is a
shame Realtek don't come to the party. Joe Sorensens's code take takes
advantage of the excellent work of kernel contributors to the mac80211
driver.

Previous comments I made about enable_rf, rtl8xxxu_start,
rtl8xxxu_init_device etc should be clarified. I will leave it for the
moment as it currently serves no direct useful purpose.


John Heenan

On 1 November 2016 at 17:24, John Heenan <john@zgus.com> wrote:
> I have a prepared another patch that is not USB VID/PID dependent for
> rtl8723bu devices. It is more elegant. I will send it after this
> email.
>
> If I have more patches is it preferable I just put them on github only
> and notify a link address until there might be some resolution?
>
> What I meant below about not finding a matching function is that I
> cannot find matching actions to take on any function calls in
> rtl8xxxu_stop as for rtl8xxxu_start.
>
> The function that is called later and potentially more than once for
> rtl8723bu devices is rtl8xxxu_init_device. There is no corresponding
> rtl8xxxu_deinit_device function.
>
> enable_rf is called in rtl8xxxu_start, not in the delayed call to
> rtl8xxxu_init_device. The corresponding disable_rf is called in
> rtl8xxxu_stop. So no matching issue here. However please see below for
> another potential issue.
>
> power_on is called in rtl8xxxu_init_device. power_off is called in
> rtl8xxxu_disconnect. Does not appear to be an issue if calling
> power_on has no real effect if already on.
>
> The following should be looked at though. For all devices enable_rf is
> only called once. For the proposed patch the first call to
> rtl8xxxu_init_device is called after the single call to enable_rf for
> rtl8723bu devices. Without the patch enable_rf is called after
> rtl8xxxu_init_device for all devices
>
> Perhaps enable_rf just configures RF modes to start up when RF is
> powered on or if called after power_on then enters requested RF modes.
>
> So I cannot see appropriate additional matching action to take.
>
> Below is some background for anyone interested
>
> rtl8xxxu_start and rtl8xxxu_stop are assigned to rtl8xxxu_ops.
>
> rtl8xxxu_probe assigns rtl8xxxu_ops to its driver layer with
> ieee80211_register_hw.
>
> rtl8xxxu_disconnect unassigns rtl8xxxu_ops from its driver layer with
> ieee80211_unregister_hw.
>
> rtl8xxxu_probe and rtl8xxxu_disconnect are USB driver functions
>
> John Heenan
>
>
> On 1 November 2016 at 08:15, John Heenan <john@zgus.com> wrote:
>> On 1 November 2016 at 07:25, Jes Sorensen <Jes.Sorensen@redhat.com> wrot=
e:
>>> John Heenan <john@zgus.com> writes:
>>
>>>
>>>> @@ -5776,9 +5781,17 @@ static int rtl8xxxu_start(struct ieee80211_hw *=
hw)
>>>>       struct rtl8xxxu_tx_urb *tx_urb;
>>>>       unsigned long flags;
>>>>       int ret, i;
>>>> +     struct usb_device_descriptor *udesc =3D &priv->udev->descriptor;
>>>>
>>>>       ret =3D 0;
>>>>
>>>> +     if(udesc->idVendor =3D=3D USB_VENDOR_ID_REALTEK
>>>> +                     && udesc->idProduct =3D=3D USB_PRODUCT_ID_RTL872=
3BU) {
>>>> +             ret =3D rtl8xxxu_init_device(hw);
>>>> +             if (ret)
>>>> +                     goto error_out;
>>>> +     }
>>>> +
>>>
>>> As mentioned previously, if this is to be changed here, it has to be
>>> matched in the _stop section too.
>>
>> I looked at this and could not find a matching function. I will have a
>> look again.
>>

^ permalink raw reply

* [PATCH v2 03/12] mwifiex: don't do unbalanced free()'ing in cleanup_if()
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Brian Norris

From: Brian Norris <briannorris@chromium.org>

The cleanup_if() callback is the inverse of init_if(). We allocate our
'card' interface structure in the probe() function, but we free it in
cleanup_if(). That gives a few problems:
(a) we leak this memory if probe() fails before we reach init_if()
(b) we can't safely utilize 'card' after cleanup_if() -- namely, in
    remove() or suspend(), both of which might race with the cleanup
    paths in our asynchronous FW initialization path

Solution: just use devm_kzalloc(), which will free this structure
properly when the device is removed -- and drop the set_drvdata(...,
NULL), since the driver core does this for us. This also removes the
temptation to use drvdata == NULL as a hack for checking if the device
has been "cleaned up."

This is a preparatory step for adding a card-level completion structure
to handle our FW init vs. remove/suspend races, in addition to fixing
memory leaks.

I *do* leave the set_drvdata(..., NULL) for the hacky SDIO
mwifiex_recreate_adapter(), since the device core won't be able to clear
that one for us.

---
v2: Same as v1
---
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/pcie.c |  5 +----
 drivers/net/wireless/marvell/mwifiex/sdio.c | 16 ++++++++++------
 drivers/net/wireless/marvell/mwifiex/usb.c  |  7 +------
 3 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 4aa5d91..e6bea02 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -189,7 +189,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
 	pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
 		 pdev->vendor, pdev->device, pdev->revision);
 
-	card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL);
+	card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
 	if (!card)
 		return -ENOMEM;
 
@@ -2820,7 +2820,6 @@ err_req_region0:
 err_set_dma_mask:
 	pci_disable_device(pdev);
 err_enable_dev:
-	pci_set_drvdata(pdev, NULL);
 	return ret;
 }
 
@@ -2854,9 +2853,7 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
 		pci_disable_device(pdev);
 		pci_release_region(pdev, 2);
 		pci_release_region(pdev, 0);
-		pci_set_drvdata(pdev, NULL);
 	}
-	kfree(card);
 }
 
 static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 8718950..f04cf5a 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -152,7 +152,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
 	pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
 		 func->vendor, func->device, func->class, func->num);
 
-	card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
+	card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
 	if (!card)
 		return -ENOMEM;
 
@@ -185,7 +185,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
 
 	if (ret) {
 		dev_err(&func->dev, "failed to enable function\n");
-		goto err_free;
+		return ret;
 	}
 
 	/* device tree node parsing and platform specific configuration*/
@@ -210,8 +210,6 @@ err_disable:
 	sdio_claim_host(func);
 	sdio_disable_func(func);
 	sdio_release_host(func);
-err_free:
-	kfree(card);
 
 	return ret;
 }
@@ -2240,8 +2238,6 @@ static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter)
 	kfree(card->mpa_rx.len_arr);
 	kfree(card->mpa_tx.buf);
 	kfree(card->mpa_rx.buf);
-	sdio_set_drvdata(card->func, NULL);
-	kfree(card);
 }
 
 /*
@@ -2291,6 +2287,14 @@ static void mwifiex_recreate_adapter(struct sdio_mmc_card *card)
 
 	mwifiex_sdio_remove(func);
 
+	/*
+	 * Normally, we would let the driver core take care of releasing these.
+	 * But we're not letting the driver core handle this one. See above
+	 * TODO.
+	 */
+	sdio_set_drvdata(func, NULL);
+	devm_kfree(&func->dev, card);
+
 	/* power cycle the adapter */
 	sdio_claim_host(func);
 	mmc_hw_reset(func->card->host);
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 73eb084..57ed834 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -382,7 +382,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
 	struct usb_card_rec *card;
 	u16 id_vendor, id_product, bcd_device, bcd_usb;
 
-	card = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
+	card = devm_kzalloc(&intf->dev, sizeof(*card), GFP_KERNEL);
 	if (!card)
 		return -ENOMEM;
 
@@ -480,7 +480,6 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
 	if (ret) {
 		pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
 		usb_reset_device(udev);
-		kfree(card);
 		return ret;
 	}
 
@@ -630,11 +629,7 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 		    "%s: removing card\n", __func__);
 	mwifiex_remove_card(adapter, &add_remove_card_sem);
 
-	usb_set_intfdata(intf, NULL);
 	usb_put_dev(interface_to_usbdev(intf));
-	kfree(card);
-
-	return;
 }
 
 static struct usb_driver mwifiex_usb_driver = {
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 04/12] mwifiex: resolve races between async FW init (failure) and device removal
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Brian Norris
In-Reply-To: <1478053488-16042-1-git-send-email-huxinming820@marvell.com>

From: Brian Norris <briannorris@chromium.org>

It's possible for the FW init sequence to fail, which will trigger a
device cleanup sequence in mwifiex_fw_dpc(). This sequence can race with
device suspend() or remove() (e.g., reboot or unbind), and can trigger
use-after-free issues. Currently, this driver attempts (poorly) to
synchronize remove() using a semaphore, but it doesn't protect some of
the critical sections properly. Particularly, we grab a pointer to the
adapter struct (card->adapter) without checking if it's being freed or
not. We later do a NULL check on the adapter, but that doesn't work if
the adapter was freed.

Also note that the PCIe interface driver doesn't ever set card->adapter
to NULL, so even if we get the synchronization right, we still might try
to redo the cleanup in ->remove(), even if the FW init failure sequence
already did it.

This patch replaces the static semaphore with a per-device completion
struct, and uses that completion to synchronize the remove() thread with
the mwifiex_fw_dpc(). A future patch will utilize this completion to
synchronize the suspend() thread as well.

---
v2: Same as v1
---
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/main.c | 46 ++++++++++-------------------
 drivers/net/wireless/marvell/mwifiex/main.h | 10 +++++--
 drivers/net/wireless/marvell/mwifiex/pcie.c | 18 +++++------
 drivers/net/wireless/marvell/mwifiex/pcie.h |  2 ++
 drivers/net/wireless/marvell/mwifiex/sdio.c | 18 +++++------
 drivers/net/wireless/marvell/mwifiex/sdio.h |  2 ++
 drivers/net/wireless/marvell/mwifiex/usb.c  | 23 +++++++--------
 drivers/net/wireless/marvell/mwifiex/usb.h  |  2 ++
 8 files changed, 53 insertions(+), 68 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index d700c44..58074ef 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -521,7 +521,6 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 	struct mwifiex_private *priv;
 	struct mwifiex_adapter *adapter = context;
 	struct mwifiex_fw_image fw;
-	struct semaphore *sem = adapter->card_sem;
 	bool init_failed = false;
 	struct wireless_dev *wdev;
 
@@ -670,7 +669,8 @@ done:
 	}
 	if (init_failed)
 		mwifiex_free_adapter(adapter);
-	up(sem);
+	/* Tell all current and future waiters we're finished */
+	complete_all(adapter->fw_done);
 	return;
 }
 
@@ -1365,7 +1365,7 @@ static void mwifiex_main_work_queue(struct work_struct *work)
  * code is extracted from mwifiex_remove_card()
  */
 static int
-mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
+mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
 {
 	struct mwifiex_private *priv;
 	int i;
@@ -1373,8 +1373,9 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
 	if (!adapter)
 		goto exit_return;
 
-	if (down_interruptible(sem))
-		goto exit_sem_err;
+	wait_for_completion(adapter->fw_done);
+	/* Caller should ensure we aren't suspending while this happens */
+	reinit_completion(adapter->fw_done);
 
 	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 	mwifiex_deauthenticate(priv, NULL);
@@ -1431,8 +1432,6 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
 		rtnl_unlock();
 	}
 
-	up(sem);
-exit_sem_err:
 	mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
 exit_return:
 	return 0;
@@ -1442,21 +1441,18 @@ exit_return:
  * code is extracted from mwifiex_add_card()
  */
 static int
-mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct semaphore *sem,
+mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct completion *fw_done,
 		  struct mwifiex_if_ops *if_ops, u8 iface_type)
 {
 	char fw_name[32];
 	struct pcie_service_card *card = adapter->card;
 
-	if (down_interruptible(sem))
-		goto exit_sem_err;
-
 	mwifiex_init_lock_list(adapter);
 	if (adapter->if_ops.up_dev)
 		adapter->if_ops.up_dev(adapter);
 
 	adapter->iface_type = iface_type;
-	adapter->card_sem = sem;
+	adapter->fw_done = fw_done;
 
 	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
 	adapter->surprise_removed = false;
@@ -1507,7 +1503,8 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct semaphore *sem,
 	}
 	strcpy(adapter->fw_name, fw_name);
 	mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
-	up(sem);
+
+	complete_all(adapter->fw_done);
 	return 0;
 
 err_init_fw:
@@ -1527,8 +1524,7 @@ err_init_fw:
 err_kmalloc:
 	mwifiex_terminate_workqueue(adapter);
 	adapter->surprise_removed = true;
-	up(sem);
-exit_sem_err:
+	complete_all(adapter->fw_done);
 	mwifiex_dbg(adapter, INFO, "%s, error\n", __func__);
 
 	return -1;
@@ -1543,12 +1539,12 @@ void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare)
 	struct mwifiex_if_ops if_ops;
 
 	if (!prepare) {
-		mwifiex_reinit_sw(adapter, adapter->card_sem, &if_ops,
+		mwifiex_reinit_sw(adapter, adapter->fw_done, &if_ops,
 				  adapter->iface_type);
 	} else {
 		memcpy(&if_ops, &adapter->if_ops,
 		       sizeof(struct mwifiex_if_ops));
-		mwifiex_shutdown_sw(adapter, adapter->card_sem);
+		mwifiex_shutdown_sw(adapter);
 	}
 }
 EXPORT_SYMBOL_GPL(mwifiex_do_flr);
@@ -1567,21 +1563,18 @@ EXPORT_SYMBOL_GPL(mwifiex_do_flr);
  *      - Add logical interfaces
  */
 int
-mwifiex_add_card(void *card, struct semaphore *sem,
+mwifiex_add_card(void *card, struct completion *fw_done,
 		 struct mwifiex_if_ops *if_ops, u8 iface_type)
 {
 	struct mwifiex_adapter *adapter;
 
-	if (down_interruptible(sem))
-		goto exit_sem_err;
-
 	if (mwifiex_register(card, if_ops, (void **)&adapter)) {
 		pr_err("%s: software init failed\n", __func__);
 		goto err_init_sw;
 	}
 
 	adapter->iface_type = iface_type;
-	adapter->card_sem = sem;
+	adapter->fw_done = fw_done;
 
 	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
 	adapter->surprise_removed = false;
@@ -1650,9 +1643,7 @@ err_kmalloc:
 	mwifiex_free_adapter(adapter);
 
 err_init_sw:
-	up(sem);
 
-exit_sem_err:
 	return -1;
 }
 EXPORT_SYMBOL_GPL(mwifiex_add_card);
@@ -1668,14 +1659,11 @@ EXPORT_SYMBOL_GPL(mwifiex_add_card);
  *      - Unregister the device
  *      - Free the adapter structure
  */
-int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
+int mwifiex_remove_card(struct mwifiex_adapter *adapter)
 {
 	struct mwifiex_private *priv = NULL;
 	int i;
 
-	if (down_trylock(sem))
-		goto exit_sem_err;
-
 	if (!adapter)
 		goto exit_remove;
 
@@ -1745,8 +1733,6 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
 	mwifiex_free_adapter(adapter);
 
 exit_remove:
-	up(sem);
-exit_sem_err:
 	return 0;
 }
 EXPORT_SYMBOL_GPL(mwifiex_remove_card);
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 7f67f23..bbd8d63 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -20,6 +20,7 @@
 #ifndef _MWIFIEX_MAIN_H_
 #define _MWIFIEX_MAIN_H_
 
+#include <linux/completion.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/sched.h>
@@ -985,7 +986,10 @@ struct mwifiex_adapter {
 	u32 usr_dot_11ac_mcs_support;
 
 	atomic_t pending_bridged_pkts;
-	struct semaphore *card_sem;
+
+	/* For synchronizing FW initialization with device lifecycle. */
+	struct completion *fw_done;
+
 	bool ext_scan;
 	u8 fw_api_ver;
 	u8 key_api_major_ver, key_api_minor_ver;
@@ -1413,8 +1417,8 @@ static inline u8 mwifiex_is_tdls_link_setup(u8 status)
 
 int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
 			     u32 func_init_shutdown);
-int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
-int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
+int mwifiex_add_card(void *, struct completion *, struct mwifiex_if_ops *, u8);
+int mwifiex_remove_card(struct mwifiex_adapter *);
 
 void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
 			 int maxlen);
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index e6bea02..5507c89 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -35,8 +35,6 @@ static u8 user_rmmod;
 
 static struct mwifiex_if_ops pcie_ops;
 
-static struct semaphore add_remove_card_sem;
-
 static int
 mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
 		       size_t size, int flags)
@@ -193,6 +191,8 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
 	if (!card)
 		return -ENOMEM;
 
+	init_completion(&card->fw_done);
+
 	card->dev = pdev;
 
 	if (ent->driver_data) {
@@ -206,7 +206,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
 		card->pcie.can_ext_scan = data->can_ext_scan;
 	}
 
-	if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
+	if (mwifiex_add_card(card, &card->fw_done, &pcie_ops,
 			     MWIFIEX_PCIE)) {
 		pr_err("%s failed\n", __func__);
 		return -1;
@@ -228,6 +228,8 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
 	if (!card)
 		return;
 
+	wait_for_completion(&card->fw_done);
+
 	adapter = card->adapter;
 	if (!adapter || !adapter->priv_num)
 		return;
@@ -247,7 +249,7 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
 		mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
 	}
 
-	mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+	mwifiex_remove_card(adapter);
 }
 
 static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
@@ -3151,8 +3153,7 @@ static struct mwifiex_if_ops pcie_ops = {
 /*
  * This function initializes the PCIE driver module.
  *
- * This initiates the semaphore and registers the device with
- * PCIE bus.
+ * This registers the device with PCIE bus.
  */
 static int mwifiex_pcie_init_module(void)
 {
@@ -3160,8 +3161,6 @@ static int mwifiex_pcie_init_module(void)
 
 	pr_debug("Marvell PCIe Driver\n");
 
-	sema_init(&add_remove_card_sem, 1);
-
 	/* Clear the flag in case user removes the card. */
 	user_rmmod = 0;
 
@@ -3185,9 +3184,6 @@ static int mwifiex_pcie_init_module(void)
  */
 static void mwifiex_pcie_cleanup_module(void)
 {
-	if (!down_interruptible(&add_remove_card_sem))
-		up(&add_remove_card_sem);
-
 	/* Set the flag as user is removing this module. */
 	user_rmmod = 1;
 
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
index 46f99ca..ae3365d 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
@@ -22,6 +22,7 @@
 #ifndef	_MWIFIEX_PCIE_H
 #define	_MWIFIEX_PCIE_H
 
+#include    <linux/completion.h>
 #include    <linux/pci.h>
 #include    <linux/interrupt.h>
 
@@ -345,6 +346,7 @@ struct pcie_service_card {
 	struct pci_dev *dev;
 	struct mwifiex_adapter *adapter;
 	struct mwifiex_pcie_device pcie;
+	struct completion fw_done;
 
 	u8 txbd_flush;
 	u32 txbd_wrptr;
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index f04cf5a..1f6ebde 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -49,8 +49,6 @@ static u8 user_rmmod;
 static struct mwifiex_if_ops sdio_ops;
 static unsigned long iface_work_flags;
 
-static struct semaphore add_remove_card_sem;
-
 static struct memory_type_mapping generic_mem_type_map[] = {
 	{"DUMP", NULL, 0, 0xDD},
 };
@@ -156,6 +154,8 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
 	if (!card)
 		return -ENOMEM;
 
+	init_completion(&card->fw_done);
+
 	card->func = func;
 	card->device_id = id;
 
@@ -197,7 +197,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
 		}
 	}
 
-	ret = mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
+	ret = mwifiex_add_card(card, &card->fw_done, &sdio_ops,
 			       MWIFIEX_SDIO);
 	if (ret) {
 		dev_err(&func->dev, "add card failed\n");
@@ -283,6 +283,8 @@ mwifiex_sdio_remove(struct sdio_func *func)
 	if (!card)
 		return;
 
+	wait_for_completion(&card->fw_done);
+
 	adapter = card->adapter;
 	if (!adapter || !adapter->priv_num)
 		return;
@@ -300,7 +302,7 @@ mwifiex_sdio_remove(struct sdio_func *func)
 		mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
 	}
 
-	mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+	mwifiex_remove_card(adapter);
 }
 
 /*
@@ -2771,14 +2773,11 @@ static struct mwifiex_if_ops sdio_ops = {
 /*
  * This function initializes the SDIO driver.
  *
- * This initiates the semaphore and registers the device with
- * SDIO bus.
+ * This registers the device with SDIO bus.
  */
 static int
 mwifiex_sdio_init_module(void)
 {
-	sema_init(&add_remove_card_sem, 1);
-
 	/* Clear the flag in case user removes the card. */
 	user_rmmod = 0;
 
@@ -2797,9 +2796,6 @@ mwifiex_sdio_init_module(void)
 static void
 mwifiex_sdio_cleanup_module(void)
 {
-	if (!down_interruptible(&add_remove_card_sem))
-		up(&add_remove_card_sem);
-
 	/* Set the flag as user is removing this module. */
 	user_rmmod = 1;
 	cancel_work_sync(&sdio_work);
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h
index db837f1..cc0aac8 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.h
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.h
@@ -21,6 +21,7 @@
 #define	_MWIFIEX_SDIO_H
 
 
+#include <linux/completion.h>
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio_func.h>
@@ -244,6 +245,7 @@ struct sdio_mmc_card {
 	struct mwifiex_adapter *adapter;
 	struct device_node *plt_of_node;
 	struct mwifiex_plt_wake_cfg *plt_wake_cfg;
+	struct completion fw_done;
 
 	const char *firmware;
 	const struct mwifiex_sdio_card_reg *reg;
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 57ed834..c20ff2f 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -24,7 +24,6 @@
 
 static u8 user_rmmod;
 static struct mwifiex_if_ops usb_ops;
-static struct semaphore add_remove_card_sem;
 
 static struct usb_device_id mwifiex_usb_table[] = {
 	/* 8766 */
@@ -386,6 +385,8 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
 	if (!card)
 		return -ENOMEM;
 
+	init_completion(&card->fw_done);
+
 	id_vendor = le16_to_cpu(udev->descriptor.idVendor);
 	id_product = le16_to_cpu(udev->descriptor.idProduct);
 	bcd_device = le16_to_cpu(udev->descriptor.bcdDevice);
@@ -475,7 +476,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
 
 	usb_set_intfdata(intf, card);
 
-	ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops,
+	ret = mwifiex_add_card(card, &card->fw_done, &usb_ops,
 			       MWIFIEX_USB);
 	if (ret) {
 		pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret);
@@ -601,13 +602,15 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 	struct usb_card_rec *card = usb_get_intfdata(intf);
 	struct mwifiex_adapter *adapter;
 
-	if (!card || !card->adapter) {
-		pr_err("%s: card or card->adapter is NULL\n", __func__);
+	if (!card) {
+		dev_err(&intf->dev, "%s: card is NULL\n", __func__);
 		return;
 	}
 
+	wait_for_completion(&card->fw_done);
+
 	adapter = card->adapter;
-	if (!adapter->priv_num)
+	if (!adapter || !adapter->priv_num)
 		return;
 
 	if (user_rmmod && !adapter->mfg_mode) {
@@ -627,7 +630,7 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 
 	mwifiex_dbg(adapter, FATAL,
 		    "%s: removing card\n", __func__);
-	mwifiex_remove_card(adapter, &add_remove_card_sem);
+	mwifiex_remove_card(adapter);
 
 	usb_put_dev(interface_to_usbdev(intf));
 }
@@ -1201,8 +1204,7 @@ static struct mwifiex_if_ops usb_ops = {
 
 /* This function initializes the USB driver module.
  *
- * This initiates the semaphore and registers the device with
- * USB bus.
+ * This registers the device with USB bus.
  */
 static int mwifiex_usb_init_module(void)
 {
@@ -1210,8 +1212,6 @@ static int mwifiex_usb_init_module(void)
 
 	pr_debug("Marvell USB8797 Driver\n");
 
-	sema_init(&add_remove_card_sem, 1);
-
 	ret = usb_register(&mwifiex_usb_driver);
 	if (ret)
 		pr_err("Driver register failed!\n");
@@ -1231,9 +1231,6 @@ static int mwifiex_usb_init_module(void)
  */
 static void mwifiex_usb_cleanup_module(void)
 {
-	if (!down_interruptible(&add_remove_card_sem))
-		up(&add_remove_card_sem);
-
 	/* set the flag as user is removing this module */
 	user_rmmod = 1;
 
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.h b/drivers/net/wireless/marvell/mwifiex/usb.h
index 30e8eb8..e5f204e 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.h
+++ b/drivers/net/wireless/marvell/mwifiex/usb.h
@@ -20,6 +20,7 @@
 #ifndef _MWIFIEX_USB_H
 #define _MWIFIEX_USB_H
 
+#include <linux/completion.h>
 #include <linux/usb.h>
 
 #define USB8XXX_VID		0x1286
@@ -75,6 +76,7 @@ struct usb_card_rec {
 	struct mwifiex_adapter *adapter;
 	struct usb_device *udev;
 	struct usb_interface *intf;
+	struct completion fw_done;
 	u8 rx_cmd_ep;
 	struct urb_context rx_cmd;
 	atomic_t rx_cmd_urb_pending;
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 05/12] mwifiex: remove redundant pdev check in suspend/resume handlers
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Brian Norris
In-Reply-To: <1478053488-16042-1-git-send-email-huxinming820@marvell.com>

From: Amitkumar Karwar <akarwar@marvell.com>

to_pci_dev() would just do struct offset arithmetic on struct
device to get 'pdev' pointer. We never get NULL pdev pointer.

---
v2: Same as v1
---
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 5507c89..fb34b99 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -101,14 +101,9 @@ static int mwifiex_pcie_suspend(struct device *dev)
 	struct pcie_service_card *card;
 	struct pci_dev *pdev = to_pci_dev(dev);
 
-	if (pdev) {
-		card = pci_get_drvdata(pdev);
-		if (!card || !card->adapter) {
-			pr_err("Card or adapter structure is not valid\n");
-			return 0;
-		}
-	} else {
-		pr_err("PCIE device is not specified\n");
+	card = pci_get_drvdata(pdev);
+	if (!card || !card->adapter) {
+		pr_err("Card or adapter structure is not valid\n");
 		return 0;
 	}
 
@@ -145,14 +140,9 @@ static int mwifiex_pcie_resume(struct device *dev)
 	struct pcie_service_card *card;
 	struct pci_dev *pdev = to_pci_dev(dev);
 
-	if (pdev) {
-		card = pci_get_drvdata(pdev);
-		if (!card || !card->adapter) {
-			pr_err("Card or adapter structure is not valid\n");
-			return 0;
-		}
-	} else {
-		pr_err("PCIE device is not specified\n");
+	card = pci_get_drvdata(pdev);
+	if (!card || !card->adapter) {
+		dev_err(dev, "Card or adapter structure is not valid\n");
 		return 0;
 	}
 
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 06/12] mwifiex: don't pretend to resume while remove()'ing
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Brian Norris
In-Reply-To: <1478053488-16042-1-git-send-email-huxinming820@marvell.com>

From: Brian Norris <briannorris@chromium.org>

The device core will not allow suspend() to race with remove().

---
v2: Same as v1
---
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 5 -----
 drivers/net/wireless/marvell/mwifiex/sdio.c | 3 ---
 drivers/net/wireless/marvell/mwifiex/usb.c  | 5 -----
 3 files changed, 13 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index fb34b99..32fbb91 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -225,11 +225,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
 		return;
 
 	if (user_rmmod && !adapter->mfg_mode) {
-#ifdef CONFIG_PM_SLEEP
-		if (adapter->is_suspended)
-			mwifiex_pcie_resume(&pdev->dev);
-#endif
-
 		mwifiex_deauthenticate_all(adapter);
 
 		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 1f6ebde..a750edb 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -292,9 +292,6 @@ mwifiex_sdio_remove(struct sdio_func *func)
 	mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
 
 	if (user_rmmod && !adapter->mfg_mode) {
-		if (adapter->is_suspended)
-			mwifiex_sdio_resume(adapter->dev);
-
 		mwifiex_deauthenticate_all(adapter);
 
 		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index c20ff2f..a61455c 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -614,11 +614,6 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 		return;
 
 	if (user_rmmod && !adapter->mfg_mode) {
-#ifdef CONFIG_PM
-		if (adapter->is_suspended)
-			mwifiex_usb_resume(intf);
-#endif
-
 		mwifiex_deauthenticate_all(adapter);
 
 		mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 07/12] mwifiex: resolve suspend() race with async FW init failure
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Brian Norris
In-Reply-To: <1478053488-16042-1-git-send-email-huxinming820@marvell.com>

From: Brian Norris <briannorris@chromium.org>

---
v2: Same as v1
---
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 11 +++++++++--
 drivers/net/wireless/marvell/mwifiex/sdio.c | 11 +++++++++--
 drivers/net/wireless/marvell/mwifiex/usb.c  | 12 ++++++++++--
 3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 32fbb91..b635563 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -102,12 +102,19 @@ static int mwifiex_pcie_suspend(struct device *dev)
 	struct pci_dev *pdev = to_pci_dev(dev);
 
 	card = pci_get_drvdata(pdev);
-	if (!card || !card->adapter) {
-		pr_err("Card or adapter structure is not valid\n");
+	if (!card) {
+		dev_err(dev, "adapter structure is not valid\n");
 		return 0;
 	}
 
+	/* Might still be loading firmware */
+	wait_for_completion(&card->fw_done);
+
 	adapter = card->adapter;
+	if (!adapter) {
+		dev_err(dev, "card is not valid\n");
+		return 0;
+	}
 
 	/* Enable the Host Sleep */
 	if (!mwifiex_enable_hs(adapter)) {
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index a750edb..4d314c1 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -331,8 +331,8 @@ static int mwifiex_sdio_suspend(struct device *dev)
 		}
 
 		card = sdio_get_drvdata(func);
-		if (!card || !card->adapter) {
-			pr_err("suspend: invalid card or adapter\n");
+		if (!card) {
+			dev_err(dev, "suspend: invalid card\n");
 			return 0;
 		}
 	} else {
@@ -340,7 +340,14 @@ static int mwifiex_sdio_suspend(struct device *dev)
 		return 0;
 	}
 
+	/* Might still be loading firmware */
+	wait_for_completion(&card->fw_done);
+
 	adapter = card->adapter;
+	if (!adapter) {
+		dev_err(dev, "card is not valid\n");
+		return 0;
+	}
 
 	/* Enable platform specific wakeup interrupt */
 	if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index a61455c..70126c3 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -503,11 +503,19 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
 	struct usb_tx_data_port *port;
 	int i, j;
 
-	if (!card || !card->adapter) {
-		pr_err("%s: card or card->adapter is NULL\n", __func__);
+	if (!card) {
+		dev_err(&intf->dev, "%s: card is NULL\n", __func__);
 		return 0;
 	}
+
+	/* Might still be loading firmware */
+	wait_for_completion(&card->fw_done);
+
 	adapter = card->adapter;
+	if (!adapter) {
+		dev_err(&intf->dev, "card is not valid\n");
+		return 0;
+	}
 
 	if (unlikely(adapter->is_suspended))
 		mwifiex_dbg(adapter, WARN,
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 08/12] mwifiex: reset card->adapter during device unregister
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Xinming Hu, Brian Norris
In-Reply-To: <1478053488-16042-1-git-send-email-huxinming820@marvell.com>

From: Xinming Hu <huxm@marvell.com>

card->adapter gets initialized in mwifiex_register_dev(). As it's not
cleared in mwifiex_unregister_dev(), we may end up accessing the memory
which is already free in below scenario.

Scenario: Driver initialization is failed due to incorrect firmware or
some other reason. Meanwhile device reboot/unload occurs.

This is safe, now that we've properly synchronized suspend() and
remove() with the FW initialization thread; now that code can simply
check for 'card->adapter == NULL' and exit safely.

---
v2: Same as v1
---
Signed-off-by: Xinming Hu <huxm@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 1 +
 drivers/net/wireless/marvell/mwifiex/sdio.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index b635563..04b9961 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -3017,6 +3017,7 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
 			if (card->msi_enable)
 				pci_disable_msi(pdev);
 	       }
+		card->adapter = NULL;
 	}
 }
 
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 4d314c1..375d0a5 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -2070,6 +2070,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
 	struct sdio_mmc_card *card = adapter->card;
 
 	if (adapter->card) {
+		card->adapter = NULL;
 		sdio_claim_host(card->func);
 		sdio_disable_func(card->func);
 		sdio_release_host(card->func);
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 09/12] mwifiex: usb: handle HS failures
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Brian Norris
In-Reply-To: <1478053488-16042-1-git-send-email-huxinming820@marvell.com>

From: Brian Norris <briannorris@chromium.org>

SDIO and PCIe drivers handle this. Let's imitate it.

Not tested.

---
v2: Same as v1
---
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/usb.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index 70126c3..c26daf4 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -521,7 +521,14 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
 		mwifiex_dbg(adapter, WARN,
 			    "Device already suspended\n");
 
-	mwifiex_enable_hs(adapter);
+	/* Enable the Host Sleep */
+	if (!mwifiex_enable_hs(adapter)) {
+		mwifiex_dbg(adapter, ERROR,
+			    "cmd: failed to suspend\n");
+		adapter->hs_enabling = false;
+		return -EFAULT;
+	}
+
 
 	/* 'is_suspended' flag indicates device is suspended.
 	 * It must be set here before the usb_kill_urb() calls. Reason
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 10/12] mwifiex: sdio: don't check for NULL sdio_func
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Brian Norris
In-Reply-To: <1478053488-16042-1-git-send-email-huxinming820@marvell.com>

From: Brian Norris <briannorris@chromium.org>

sdio_func is retrieved via container_of() and should never be NULL.
Checking for NULL just makes the logic more confusing than necessary.
Stop doing that.

---
v2: Same as v1
---
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/sdio.c | 40 +++++++++++------------------
 1 file changed, 15 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 375d0a5..8f0f072 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -231,15 +231,10 @@ static int mwifiex_sdio_resume(struct device *dev)
 	struct mwifiex_adapter *adapter;
 	mmc_pm_flag_t pm_flag = 0;
 
-	if (func) {
-		pm_flag = sdio_get_host_pm_caps(func);
-		card = sdio_get_drvdata(func);
-		if (!card || !card->adapter) {
-			pr_err("resume: invalid card or adapter\n");
-			return 0;
-		}
-	} else {
-		pr_err("resume: sdio_func is not specified\n");
+	pm_flag = sdio_get_host_pm_caps(func);
+	card = sdio_get_drvdata(func);
+	if (!card || !card->adapter) {
+		dev_err(dev, "resume: invalid card or adapter\n");
 		return 0;
 	}
 
@@ -320,23 +315,18 @@ static int mwifiex_sdio_suspend(struct device *dev)
 	mmc_pm_flag_t pm_flag = 0;
 	int ret = 0;
 
-	if (func) {
-		pm_flag = sdio_get_host_pm_caps(func);
-		pr_debug("cmd: %s: suspend: PM flag = 0x%x\n",
-			 sdio_func_id(func), pm_flag);
-		if (!(pm_flag & MMC_PM_KEEP_POWER)) {
-			pr_err("%s: cannot remain alive while host is"
-				" suspended\n", sdio_func_id(func));
-			return -ENOSYS;
-		}
+	pm_flag = sdio_get_host_pm_caps(func);
+	pr_debug("cmd: %s: suspend: PM flag = 0x%x\n",
+		 sdio_func_id(func), pm_flag);
+	if (!(pm_flag & MMC_PM_KEEP_POWER)) {
+		dev_err(dev, "%s: cannot remain alive while host is"
+			" suspended\n", sdio_func_id(func));
+		return -ENOSYS;
+	}
 
-		card = sdio_get_drvdata(func);
-		if (!card) {
-			dev_err(dev, "suspend: invalid card\n");
-			return 0;
-		}
-	} else {
-		pr_err("suspend: sdio_func is not specified\n");
+	card = sdio_get_drvdata(func);
+	if (!card) {
+		dev_err(dev, "suspend: invalid card\n");
 		return 0;
 	}
 
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 11/12] mwifiex: stop checking for NULL drvata/intfdata
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Brian Norris
In-Reply-To: <1478053488-16042-1-git-send-email-huxinming820@marvell.com>

From: Brian Norris <briannorris@chromium.org>

These are never NULL, so stop making people think they might be.

I don't change this for SDIO because SDIO has a racy card-reset handler
that reallocates this struct. I'd rather not touch that mess right now.

---
v2: Same as v1
---
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 14 +++++---------
 drivers/net/wireless/marvell/mwifiex/usb.c  | 15 +++------------
 2 files changed, 8 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 04b9961..c061d00 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -102,10 +102,6 @@ static int mwifiex_pcie_suspend(struct device *dev)
 	struct pci_dev *pdev = to_pci_dev(dev);
 
 	card = pci_get_drvdata(pdev);
-	if (!card) {
-		dev_err(dev, "adapter structure is not valid\n");
-		return 0;
-	}
 
 	/* Might still be loading firmware */
 	wait_for_completion(&card->fw_done);
@@ -148,8 +144,9 @@ static int mwifiex_pcie_resume(struct device *dev)
 	struct pci_dev *pdev = to_pci_dev(dev);
 
 	card = pci_get_drvdata(pdev);
-	if (!card || !card->adapter) {
-		dev_err(dev, "Card or adapter structure is not valid\n");
+
+	if (!card->adapter) {
+		dev_err(dev, "adapter structure is not valid\n");
 		return 0;
 	}
 
@@ -222,8 +219,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
 	struct mwifiex_private *priv;
 
 	card = pci_get_drvdata(pdev);
-	if (!card)
-		return;
 
 	wait_for_completion(&card->fw_done);
 
@@ -2216,7 +2211,8 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
 	}
 
 	card = pci_get_drvdata(pdev);
-	if (!card || !card->adapter) {
+
+	if (!card->adapter) {
 		pr_err("info: %s: card=%p adapter=%p\n", __func__, card,
 		       card ? card->adapter : NULL);
 		goto exit;
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
index c26daf4..78b46fa 100644
--- a/drivers/net/wireless/marvell/mwifiex/usb.c
+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -503,11 +503,6 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
 	struct usb_tx_data_port *port;
 	int i, j;
 
-	if (!card) {
-		dev_err(&intf->dev, "%s: card is NULL\n", __func__);
-		return 0;
-	}
-
 	/* Might still be loading firmware */
 	wait_for_completion(&card->fw_done);
 
@@ -574,8 +569,9 @@ static int mwifiex_usb_resume(struct usb_interface *intf)
 	struct mwifiex_adapter *adapter;
 	int i;
 
-	if (!card || !card->adapter) {
-		pr_err("%s: card or card->adapter is NULL\n", __func__);
+	if (!card->adapter) {
+		dev_err(&intf->dev, "%s: card->adapter is NULL\n",
+			__func__);
 		return 0;
 	}
 	adapter = card->adapter;
@@ -617,11 +613,6 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 	struct usb_card_rec *card = usb_get_intfdata(intf);
 	struct mwifiex_adapter *adapter;
 
-	if (!card) {
-		dev_err(&intf->dev, "%s: card is NULL\n", __func__);
-		return;
-	}
-
 	wait_for_completion(&card->fw_done);
 
 	adapter = card->adapter;
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH v2 12/12] mwifiex: pcie: stop checking for NULL adapter->card
From: Xinming Hu @ 2016-11-02  2:24 UTC (permalink / raw)
  To: Linux Wireless
  Cc: Kalle Valo, Brian Norris, Dmitry Torokhov, Amitkumar Karwar,
	Cathy Luo, Brian Norris
In-Reply-To: <1478053488-16042-1-git-send-email-huxinming820@marvell.com>

From: Brian Norris <briannorris@chromium.org>

It should never be NULL here, and to think otherwise makes things
confusing.

---
v2: Same as v1
---
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 55 +++++++++++++----------------
 1 file changed, 24 insertions(+), 31 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index c061d00..86e8ce6 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2990,31 +2990,28 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
 static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
 {
 	struct pcie_service_card *card = adapter->card;
-	struct pci_dev *pdev;
+	struct pci_dev *pdev = card->dev;
 	int i;
 
-	if (card) {
-		pdev = card->dev;
-		if (card->msix_enable) {
-			for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
-				synchronize_irq(card->msix_entries[i].vector);
+	if (card->msix_enable) {
+		for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
+			synchronize_irq(card->msix_entries[i].vector);
 
-			for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
-				free_irq(card->msix_entries[i].vector,
-					 &card->msix_ctx[i]);
+		for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
+			free_irq(card->msix_entries[i].vector,
+				 &card->msix_ctx[i]);
 
-			card->msix_enable = 0;
-			pci_disable_msix(pdev);
-	       } else {
-			mwifiex_dbg(adapter, INFO,
-				    "%s(): calling free_irq()\n", __func__);
-		       free_irq(card->dev->irq, &card->share_irq_ctx);
+		card->msix_enable = 0;
+		pci_disable_msix(pdev);
+       } else {
+		mwifiex_dbg(adapter, INFO,
+			    "%s(): calling free_irq()\n", __func__);
+	       free_irq(card->dev->irq, &card->share_irq_ctx);
 
-			if (card->msi_enable)
-				pci_disable_msi(pdev);
-	       }
-		card->adapter = NULL;
-	}
+		if (card->msi_enable)
+			pci_disable_msi(pdev);
+       }
+	card->adapter = NULL;
 }
 
 /* This function initializes the PCI-E host memory space, WCB rings, etc.
@@ -3097,18 +3094,14 @@ static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter)
 	adapter->seq_num = 0;
 	adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
 
-	if (card) {
-		if (reg->sleep_cookie)
-			mwifiex_pcie_delete_sleep_cookie_buf(adapter);
-
-		mwifiex_pcie_delete_cmdrsp_buf(adapter);
-		mwifiex_pcie_delete_evtbd_ring(adapter);
-		mwifiex_pcie_delete_rxbd_ring(adapter);
-		mwifiex_pcie_delete_txbd_ring(adapter);
-		card->cmdrsp_buf = NULL;
-	}
+	if (reg->sleep_cookie)
+		mwifiex_pcie_delete_sleep_cookie_buf(adapter);
 
-	return;
+	mwifiex_pcie_delete_cmdrsp_buf(adapter);
+	mwifiex_pcie_delete_evtbd_ring(adapter);
+	mwifiex_pcie_delete_rxbd_ring(adapter);
+	mwifiex_pcie_delete_txbd_ring(adapter);
+	card->cmdrsp_buf = NULL;
 }
 
 static struct mwifiex_if_ops pcie_ops = {
-- 
1.8.1.4

^ permalink raw reply related


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