Subject: [PATCH 1/4] ath6kl: Refactor ath6kl_init_hw_start() and ath6kl_init_hw_stop()

So that these functions will be used to re-initialize the fw
upon detecting fw error. This refactoring moves ar->state
setting out of core stop/start functionality.

Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
---
drivers/net/wireless/ath/ath6kl/init.c | 28 +++++++++++++++++++++++-----
1 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index eb3677b..be27ebe 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1546,7 +1546,7 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
return NULL;
}

-int ath6kl_init_hw_start(struct ath6kl *ar)
+static int __ath6kl_init_hw_start(struct ath6kl *ar)
{
long timeleft;
int ret, i;
@@ -1642,8 +1642,6 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
goto err_htc_stop;
}

- ar->state = ATH6KL_STATE_ON;
-
return 0;

err_htc_stop:
@@ -1656,7 +1654,18 @@ err_power_off:
return ret;
}

-int ath6kl_init_hw_stop(struct ath6kl *ar)
+int ath6kl_init_hw_start(struct ath6kl *ar)
+{
+ int err;
+
+ err = __ath6kl_init_hw_start(ar);
+ if (err)
+ return err;
+ ar->state = ATH6KL_STATE_ON;
+ return 0;
+}
+
+static int __ath6kl_init_hw_stop(struct ath6kl *ar)
{
int ret;

@@ -1672,8 +1681,17 @@ int ath6kl_init_hw_stop(struct ath6kl *ar)
if (ret)
ath6kl_warn("failed to power off hif: %d\n", ret);

- ar->state = ATH6KL_STATE_OFF;
+ return 0;
+}

+int ath6kl_init_hw_stop(struct ath6kl *ar)
+{
+ int err;
+
+ err = __ath6kl_init_hw_stop(ar);
+ if (err)
+ return err;
+ ar->state = ATH6KL_STATE_OFF;
return 0;
}

--
1.7.0.4



2012-08-31 15:46:16

by Jin, Navy

[permalink] [raw]
Subject: Re: [PATCH 2/4] ath6kl: Recover from fw crash

Q2FuIHRoaXMgZmVhdHVyZSBiZSBkaXNhYmxlZCBieSBzb21lIGNvbnRyb2wgYml0IG9yIG1vZHVs
ZSBwYXJhbWV0ZXJzP09uY2UgZW5hYmxlZCxpdCBpcyBiZXR0ZXIgZm9yIHVzZXIsYnV0IG1vcmUg
aGFyZCB0byBmaW5kIHRoZSByb290IGNhdXNlLG9yIGxvZyBjaGlwIGluZm8gYmVmb3JlIHJlY292
ZXJ5Pw0KUmVnYXJkc6OsDQpoYWlqdW4NCg0KIlRoaWFnYXJhamFuLCBWYXNhbnRoYWt1bWFyIiA8
dnRoaWFnYXJAcWNhLnF1YWxjb21tLmNvbT6x4NC0o7oNCg0KDQpSZS1pbml0aWFsaXplIHRoZSB0
YXJnZXQgd2hlbiBmdyBjcmFzaCBpcyByZXBvcnRlZC4NClRoaXMgd291bGQgbWFrZSB0aGUgZGV2
aWNlIGZ1bmN0aW9uYWwgYWdhaW4gYWZ0ZXINCnRhcmdldCBjcmFzaC4gRHVyaW5nIHRoZSB0YXJn
ZXQgcmUtaW5pdGlhbGl6YXRpb24NCml0IGlzIG1hZGUgc3VyZSB0aGF0IHRhcmdldCBpcyBub3Qg
YnVnZ2VkIHdpdGggZGF0YS9jbWQNCnJlcXVlc3QsIGFyLT5zdGF0ZSBBVEg2S0xfU1RBVEVfUkVD
T1ZFUlkgaXMgdXNlZA0KZm9yIHRoaXMgcHVycG9zZS4NCg0KU2lnbmVkLW9mZi1ieTogVmFzYW50
aGFrdW1hciBUaGlhZ2FyYWphbiA8dnRoaWFnYXJAcWNhLnF1YWxjb21tLmNvbT4NCi0tLQ0KIGRy
aXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvTWFrZWZpbGUgICB8ICAgIDEgKw0KIGRyaXZl
cnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvY2ZnODAyMTEuYyB8ICAgMTcgKysrKysrKy0NCiBk
cml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2NvcmUuYyAgICAgfCAgICA0ICsrDQogZHJp
dmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDZrbC9jb3JlLmggICAgIHwgICAxOCArKysrKysrKw0K
IGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvZGVidWcuaCAgICB8ICAgIDEgKw0KIGRy
aXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvaGlmLmMgICAgICB8ICAgIDEgKw0KIGRyaXZl
cnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvaW5pdC5jICAgICB8ICAgMTkgKysrKysrKysNCiBk
cml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL3JlY292ZXJ5LmMgfCAgIDYyICsrKysrKysr
KysrKysrKysrKysrKysrKysrKysNCiBkcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL3Nk
aW8uYyAgICAgfCAgICAzICsNCiBkcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL3R4cngu
YyAgICAgfCAgICAzICstDQogMTAgZmlsZXMgY2hhbmdlZCwgMTI2IGluc2VydGlvbnMoKyksIDMg
ZGVsZXRpb25zKC0pDQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvbmV0L3dpcmVsZXNzL2F0
aC9hdGg2a2wvcmVjb3ZlcnkuYw0KDQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3Mv
YXRoL2F0aDZrbC9NYWtlZmlsZSBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvTWFr
ZWZpbGUNCmluZGV4IDhjYWU4ODguLmNhYjBlYzAgMTAwNjQ0DQotLS0gYS9kcml2ZXJzL25ldC93
aXJlbGVzcy9hdGgvYXRoNmtsL01ha2VmaWxlDQorKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9h
dGgvYXRoNmtsL01ha2VmaWxlDQpAQCAtMzQsNiArMzQsNyBAQCBhdGg2a2xfY29yZS15ICs9IG1h
aW4ubw0KIGF0aDZrbF9jb3JlLXkgKz0gdHhyeC5vDQogYXRoNmtsX2NvcmUteSArPSB3bWkubw0K
IGF0aDZrbF9jb3JlLXkgKz0gY29yZS5vDQorYXRoNmtsX2NvcmUteSArPSByZWNvdmVyeS5vDQog
YXRoNmtsX2NvcmUtJChDT05GSUdfTkw4MDIxMV9URVNUTU9ERSkgKz0gdGVzdG1vZGUubw0KDQog
b2JqLSQoQ09ORklHX0FUSDZLTF9TRElPKSArPSBhdGg2a2xfc2Rpby5vDQpkaWZmIC0tZ2l0IGEv
ZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDZrbC9jZmc4MDIxMS5jIGIvZHJpdmVycy9uZXQv
d2lyZWxlc3MvYXRoL2F0aDZrbC9jZmc4MDIxMS5jDQppbmRleCBmYjIwZmY2Li5iNGM1NDlkIDEw
MDY0NA0KLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDZrbC9jZmc4MDIxMS5jDQor
KysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2NmZzgwMjExLmMNCkBAIC0yNTEw
LDE0ICsyNTEwLDIzIEBAIHN0YXRpYyBpbnQgX19hdGg2a2xfY2ZnODAyMTFfc3VzcGVuZChzdHJ1
Y3Qgd2lwaHkgKndpcGh5LA0KIHsNCiAgICAgICAgc3RydWN0IGF0aDZrbCAqYXIgPSB3aXBoeV9w
cml2KHdpcGh5KTsNCg0KKyAgICAgICBhdGg2a2xfcmVjb3Zlcnlfc3VzcGVuZChhcik7DQorDQog
ICAgICAgIHJldHVybiBhdGg2a2xfaGlmX3N1c3BlbmQoYXIsIHdvdyk7DQogfQ0KDQogc3RhdGlj
IGludCBfX2F0aDZrbF9jZmc4MDIxMV9yZXN1bWUoc3RydWN0IHdpcGh5ICp3aXBoeSkNCiB7DQog
ICAgICAgIHN0cnVjdCBhdGg2a2wgKmFyID0gd2lwaHlfcHJpdih3aXBoeSk7DQorICAgICAgIGlu
dCBlcnI7DQorDQorICAgICAgIGVyciA9IGF0aDZrbF9oaWZfcmVzdW1lKGFyKTsNCisgICAgICAg
aWYgKGVycikNCisgICAgICAgICAgICAgICByZXR1cm4gZXJyOw0KDQotICAgICAgIHJldHVybiBh
dGg2a2xfaGlmX3Jlc3VtZShhcik7DQorICAgICAgIGFyLT5md19yZWNvdmVyeS5lbmFibGUgPSB0
cnVlOw0KKw0KKyAgICAgICByZXR1cm4gMDsNCiB9DQoNCiAvKg0KQEAgLTM0NDEsNiArMzQ1MCwx
MCBAQCB2b2lkIGF0aDZrbF9jZmc4MDIxMV9zdG9wKHN0cnVjdCBhdGg2a2xfdmlmICp2aWYpDQog
ICAgICAgIGNsZWFyX2JpdChDT05ORUNURUQsICZ2aWYtPmZsYWdzKTsNCiAgICAgICAgY2xlYXJf
Yml0KENPTk5FQ1RfUEVORCwgJnZpZi0+ZmxhZ3MpOw0KDQorICAgICAgIC8qIFN0b3AgbmV0ZGV2
IHF1ZXVlcywgbmVlZGVkIGR1cmluZyByZWNvdmVyeSAqLw0KKyAgICAgICBuZXRpZl9zdG9wX3F1
ZXVlKHZpZi0+bmRldik7DQorICAgICAgIG5ldGlmX2NhcnJpZXJfb2ZmKHZpZi0+bmRldik7DQor
DQogICAgICAgIC8qIGRpc2FibGUgc2Nhbm5pbmcgKi8NCiAgICAgICAgaWYgKGF0aDZrbF93bWlf
c2NhbnBhcmFtc19jbWQodmlmLT5hci0+d21pLCB2aWYtPmZ3X3ZpZl9pZHgsIDB4RkZGRiwNCiAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMCwgMCwgMCwgMCwgMCwgMCwgMCwg
MCwgMCkgIT0gMCkNCkBAIC0zNDU0LDcgKzM0NjcsNyBAQCB2b2lkIGF0aDZrbF9jZmc4MDIxMV9z
dG9wX2FsbChzdHJ1Y3QgYXRoNmtsICphcikNCiAgICAgICAgc3RydWN0IGF0aDZrbF92aWYgKnZp
ZjsNCg0KICAgICAgICB2aWYgPSBhdGg2a2xfdmlmX2ZpcnN0KGFyKTsNCi0gICAgICAgaWYgKCF2
aWYpIHsNCisgICAgICAgaWYgKCF2aWYgJiYgYXItPnN0YXRlICE9IEFUSDZLTF9TVEFURV9SRUNP
VkVSWSkgew0KICAgICAgICAgICAgICAgIC8qIHNhdmUgdGhlIGN1cnJlbnQgcG93ZXIgbW9kZSBi
ZWZvcmUgZW5hYmxpbmcgcG93ZXIgc2F2ZSAqLw0KICAgICAgICAgICAgICAgIGFyLT53bWktPnNh
dmVkX3B3cl9tb2RlID0gYXItPndtaS0+cHdyX21vZGU7DQoNCmRpZmYgLS1naXQgYS9kcml2ZXJz
L25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2NvcmUuYyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0
aC9hdGg2a2wvY29yZS5jDQppbmRleCA4MmM0ZGQyLi5hZGNhYTk2IDEwMDY0NA0KLS0tIGEvZHJp
dmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDZrbC9jb3JlLmMNCisrKyBiL2RyaXZlcnMvbmV0L3dp
cmVsZXNzL2F0aC9hdGg2a2wvY29yZS5jDQpAQCAtMjAyLDYgKzIwMiw4IEBAIGludCBhdGg2a2xf
Y29yZV9pbml0KHN0cnVjdCBhdGg2a2wgKmFyLCBlbnVtIGF0aDZrbF9odGNfdHlwZSBodGNfdHlw
ZSkNCiAgICAgICAgYXRoNmtsX2RiZyhBVEg2S0xfREJHX1RSQywgIiVzOiBuYW1lPSVzIGRldj0w
eCVwLCBhcj0weCVwXG4iLA0KICAgICAgICAgICAgICAgICAgIF9fZnVuY19fLCB3ZGV2LT5uZXRk
ZXYtPm5hbWUsIHdkZXYtPm5ldGRldiwgYXIpOw0KDQorICAgICAgIGF0aDZrbF9yZWNvdmVyeV9p
bml0KGFyKTsNCisNCiAgICAgICAgcmV0dXJuIHJldDsNCg0KIGVycl9yeGJ1Zl9jbGVhbnVwOg0K
QEAgLTI5MSw2ICsyOTMsOCBAQCB2b2lkIGF0aDZrbF9jb3JlX2NsZWFudXAoc3RydWN0IGF0aDZr
bCAqYXIpDQogew0KICAgICAgICBhdGg2a2xfaGlmX3Bvd2VyX29mZihhcik7DQoNCisgICAgICAg
YXRoNmtsX3JlY292ZXJ5X2NsZWFudXAoYXIpOw0KKw0KICAgICAgICBkZXN0cm95X3dvcmtxdWV1
ZShhci0+YXRoNmtsX3dxKTsNCg0KICAgICAgICBpZiAoYXItPmh0Y190YXJnZXQpDQpkaWZmIC0t
Z2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDZrbC9jb3JlLmggYi9kcml2ZXJzL25l
dC93aXJlbGVzcy9hdGgvYXRoNmtsL2NvcmUuaA0KaW5kZXggOGIzMWI5YS4uYzdkY2RhZCAxMDA2
NDQNCi0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvY29yZS5oDQorKysgYi9k
cml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2NvcmUuaA0KQEAgLTY0NSw2ICs2NDUsMTIg
QEAgZW51bSBhdGg2a2xfc3RhdGUgew0KICAgICAgICBBVEg2S0xfU1RBVEVfREVFUFNMRUVQLA0K
ICAgICAgICBBVEg2S0xfU1RBVEVfQ1VUUE9XRVIsDQogICAgICAgIEFUSDZLTF9TVEFURV9XT1cs
DQorICAgICAgIEFUSDZLTF9TVEFURV9SRUNPVkVSWSwNCit9Ow0KKw0KKy8qIEZ3IGVycm9yIHJl
Y292ZXJ5ICovDQorZW51bSBhdGg2a2xfZndfZXJyIHsNCisgICAgICAgQVRINktMX0ZXX0FTU0VS
VCwNCiB9Ow0KDQogc3RydWN0IGF0aDZrbCB7DQpAQCAtNzkwLDYgKzc5NiwxMiBAQCBzdHJ1Y3Qg
YXRoNmtsIHsNCg0KICAgICAgICBib29sIHdpcGh5X3JlZ2lzdGVyZWQ7DQoNCisgICAgICAgc3Ry
dWN0IGF0aDZrbF9md19yZWNvdmVyeSB7DQorICAgICAgICAgICAgICAgYm9vbCBlbmFibGU7DQor
ICAgICAgICAgICAgICAgc3RydWN0IHdvcmtfc3RydWN0IHJlY292ZXJ5X3dvcms7DQorICAgICAg
ICAgICAgICAgdW5zaWduZWQgbG9uZyBlcnJfcmVhc29uOw0KKyAgICAgICB9IGZ3X3JlY292ZXJ5
Ow0KKw0KICNpZmRlZiBDT05GSUdfQVRINktMX0RFQlVHDQogICAgICAgIHN0cnVjdCB7DQogICAg
ICAgICAgICAgICAgc3RydWN0IHNrX2J1ZmZfaGVhZCBmd2xvZ19xdWV1ZTsNCkBAIC05MjUsNCAr
OTM3LDEwIEBAIGludCBhdGg2a2xfY29yZV9pbml0KHN0cnVjdCBhdGg2a2wgKmFyLCBlbnVtIGF0
aDZrbF9odGNfdHlwZSBodGNfdHlwZSk7DQogdm9pZCBhdGg2a2xfY29yZV9jbGVhbnVwKHN0cnVj
dCBhdGg2a2wgKmFyKTsNCiB2b2lkIGF0aDZrbF9jb3JlX2Rlc3Ryb3koc3RydWN0IGF0aDZrbCAq
YXIpOw0KDQorLyogRncgZXJyb3IgcmVjb3ZlcnkgKi8NCit2b2lkIGF0aDZrbF9pbml0X2h3X3Jl
c3RhcnQoc3RydWN0IGF0aDZrbCAqYXIpOw0KK3ZvaWQgYXRoNmtsX3JlY292ZXJ5X2Vycl9ub3Rp
Znkoc3RydWN0IGF0aDZrbCAqYXIsIGVudW0gYXRoNmtsX2Z3X2VyciByZWFzb24pOw0KK3ZvaWQg
YXRoNmtsX3JlY292ZXJ5X2luaXQoc3RydWN0IGF0aDZrbCAqYXIpOw0KK3ZvaWQgYXRoNmtsX3Jl
Y292ZXJ5X2NsZWFudXAoc3RydWN0IGF0aDZrbCAqYXIpOw0KK3ZvaWQgYXRoNmtsX3JlY292ZXJ5
X3N1c3BlbmQoc3RydWN0IGF0aDZrbCAqYXIpOw0KICNlbmRpZiAvKiBDT1JFX0ggKi8NCmRpZmYg
LS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2RlYnVnLmggYi9kcml2ZXJz
L25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2RlYnVnLmgNCmluZGV4IDQ5NjM5ZDguLmY5N2NkNGUg
MTAwNjQ0DQotLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2RlYnVnLmgNCisr
KyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvZGVidWcuaA0KQEAgLTQ0LDYgKzQ0
LDcgQEAgZW51bSBBVEg2S19ERUJVR19NQVNLIHsNCiAgICAgICAgQVRINktMX0RCR19TVVNQRU5E
ICAgICAgPSBCSVQoMjApLA0KICAgICAgICBBVEg2S0xfREJHX1VTQiAgICAgICAgICA9IEJJVCgy
MSksDQogICAgICAgIEFUSDZLTF9EQkdfVVNCX0JVTEsgICAgID0gQklUKDIyKSwNCisgICAgICAg
QVRINktMX0RCR19SRUNPVkVSWSAgICAgPSBCSVQoMjMpLA0KICAgICAgICBBVEg2S0xfREJHX0FO
WSAgICAgICAgICA9IDB4ZmZmZmZmZmYgIC8qIGVuYWJsZSBhbGwgbG9ncyAqLw0KIH07DQoNCmRp
ZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2hpZi5jIGIvZHJpdmVy
cy9uZXQvd2lyZWxlc3MvYXRoL2F0aDZrbC9oaWYuYw0KaW5kZXggNjhlZDZjMi4uMDI5OTE0YSAx
MDA2NDQNCi0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvaGlmLmMNCisrKyBi
L2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvaGlmLmMNCkBAIC0xMzYsNiArMTM2LDcg
QEAgc3RhdGljIGludCBhdGg2a2xfaGlmX3Byb2NfZGJnX2ludHIoc3RydWN0IGF0aDZrbF9kZXZp
Y2UgKmRldikNCg0KICAgICAgICBhdGg2a2xfaGlmX2R1bXBfZndfY3Jhc2goZGV2LT5hcik7DQog
ICAgICAgIGF0aDZrbF9yZWFkX2Z3bG9ncyhkZXYtPmFyKTsNCisgICAgICAgYXRoNmtsX3JlY292
ZXJ5X2Vycl9ub3RpZnkoZGV2LT5hciwgQVRINktMX0ZXX0FTU0VSVCk7DQoNCiAgICAgICAgcmV0
dXJuIHJldDsNCiB9DQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDZr
bC9pbml0LmMgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2luaXQuYw0KaW5kZXgg
YmUyN2ViZS4uMzAxNDQzYyAxMDA2NDQNCi0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9h
dGg2a2wvaW5pdC5jDQorKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL2luaXQu
Yw0KQEAgLTE2OTUsNiArMTY5NSwyNSBAQCBpbnQgYXRoNmtsX2luaXRfaHdfc3RvcChzdHJ1Y3Qg
YXRoNmtsICphcikNCiAgICAgICAgcmV0dXJuIDA7DQogfQ0KDQordm9pZCBhdGg2a2xfaW5pdF9o
d19yZXN0YXJ0KHN0cnVjdCBhdGg2a2wgKmFyKQ0KK3sNCisNCisgICAgICAgYXItPnN0YXRlID0g
QVRINktMX1NUQVRFX1JFQ09WRVJZOw0KKw0KKyAgICAgICBhdGg2a2xfY2ZnODAyMTFfc3RvcF9h
bGwoYXIpOw0KKw0KKyAgICAgICBpZiAoX19hdGg2a2xfaW5pdF9od19zdG9wKGFyKSkNCisgICAg
ICAgICAgICAgICByZXR1cm47DQorDQorICAgICAgIGlmIChfX2F0aDZrbF9pbml0X2h3X3N0YXJ0
KGFyKSkgew0KKyAgICAgICAgICAgICAgIGF0aDZrbF9kYmcoQVRINktMX0RCR19SRUNPVkVSWSwg
IkZhaWxlZCB0byByZXN0YXJ0IGR1cmluZyBmdyBlcnJvciByZWNvdmVyeVxuIik7DQorICAgICAg
ICAgICAgICAgcmV0dXJuOw0KKyAgICAgICB9DQorDQorICAgICAgIGFyLT5zdGF0ZSA9IEFUSDZL
TF9TVEFURV9PTjsNCisgICAgICAgYXItPmZ3X3JlY292ZXJ5LmVycl9yZWFzb24gPSAwOw0KK30N
CisNCiAvKiBGSVhNRTogbW92ZSB0aGlzIHRvIGNmZzgwMjExLmMgYW5kIHJlbmFtZSB0byBhdGg2
a2xfY2ZnODAyMTFfdmlmX3N0b3AoKSAqLw0KIHZvaWQgYXRoNmtsX2NsZWFudXBfdmlmKHN0cnVj
dCBhdGg2a2xfdmlmICp2aWYsIGJvb2wgd21pX3JlYWR5KQ0KIHsNCmRpZmYgLS1naXQgYS9kcml2
ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL3JlY292ZXJ5LmMgYi9kcml2ZXJzL25ldC93aXJl
bGVzcy9hdGgvYXRoNmtsL3JlY292ZXJ5LmMNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQppbmRleCAw
MDAwMDAwLi5jMjI1ZmM0DQotLS0gL2Rldi9udWxsDQorKysgYi9kcml2ZXJzL25ldC93aXJlbGVz
cy9hdGgvYXRoNmtsL3JlY292ZXJ5LmMNCkBAIC0wLDAgKzEsNjIgQEANCisvKg0KKyAqIENvcHly
aWdodCAoYykgMjAxMiBRdWFsY29tbSBBdGhlcm9zLCBJbmMuDQorICoNCisgKiBQZXJtaXNzaW9u
IHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZv
ciBhbnkNCisgKiBwdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQs
IHByb3ZpZGVkIHRoYXQgdGhlIGFib3ZlDQorICogY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBw
ZXJtaXNzaW9uIG5vdGljZSBhcHBlYXIgaW4gYWxsIGNvcGllcy4NCisgKg0KKyAqIFRIRSBTT0ZU
V0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FS
UkFOVElFUw0KKyAqIFdJVEggUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJ
TVBMSUVEIFdBUlJBTlRJRVMgT0YNCisgKiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MuIElO
IE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUg0KKyAqIEFOWSBTUEVDSUFM
LCBESVJFQ1QsIElORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFH
RVMNCisgKiBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NIExPU1MgT0YgVVNFLCBEQVRBIE9SIFBS
T0ZJVFMsIFdIRVRIRVIgSU4gQU4NCisgKiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0Ug
T1IgT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRg0KKyAqIE9SIElOIENPTk5F
Q1RJT04gV0lUSCBUSEUgVVNFIE9SIFBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuDQorICov
DQorDQorI2luY2x1ZGUgImNvcmUuaCINCisjaW5jbHVkZSAiY2ZnODAyMTEuaCINCisjaW5jbHVk
ZSAiZGVidWcuaCINCisNCitzdGF0aWMgdm9pZCBhdGg2a2xfcmVjb3Zlcnlfd29yayhzdHJ1Y3Qg
d29ya19zdHJ1Y3QgKndvcmspDQorew0KKyAgICAgICBzdHJ1Y3QgYXRoNmtsICphciA9IGNvbnRh
aW5lcl9vZih3b3JrLCBzdHJ1Y3QgYXRoNmtsLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICBmd19yZWNvdmVyeS5yZWNvdmVyeV93b3JrKTsNCisNCisgICAgICAgYXRo
NmtsX2luaXRfaHdfcmVzdGFydChhcik7DQorfQ0KKw0KK3ZvaWQgYXRoNmtsX3JlY292ZXJ5X2Vy
cl9ub3RpZnkoc3RydWN0IGF0aDZrbCAqYXIsIGVudW0gYXRoNmtsX2Z3X2VyciByZWFzb24pDQor
ew0KKyAgICAgICBhdGg2a2xfZGJnKEFUSDZLTF9EQkdfUkVDT1ZFUlksICJGdyBlcnJvciBkZXRl
Y3RlZCwgcmVhc29uOiVkXG4iLA0KKyAgICAgICAgICAgICAgICAgIHJlYXNvbik7DQorDQorICAg
ICAgIHNldF9iaXQocmVhc29uLCAmYXItPmZ3X3JlY292ZXJ5LmVycl9yZWFzb24pOw0KKw0KKyAg
ICAgICBpZiAoYXItPmZ3X3JlY292ZXJ5LmVuYWJsZSAmJiBhci0+c3RhdGUgIT0gQVRINktMX1NU
QVRFX1JFQ09WRVJZKQ0KKyAgICAgICAgICAgICAgIHF1ZXVlX3dvcmsoYXItPmF0aDZrbF93cSwg
JmFyLT5md19yZWNvdmVyeS5yZWNvdmVyeV93b3JrKTsNCit9DQorDQordm9pZCBhdGg2a2xfcmVj
b3ZlcnlfaW5pdChzdHJ1Y3QgYXRoNmtsICphcikNCit7DQorICAgICAgIHN0cnVjdCBhdGg2a2xf
ZndfcmVjb3ZlcnkgKnJlY292ZXJ5ID0gJmFyLT5md19yZWNvdmVyeTsNCisNCisgICAgICAgcmVj
b3ZlcnktPmVuYWJsZSA9IHRydWU7DQorICAgICAgIElOSVRfV09SSygmcmVjb3ZlcnktPnJlY292
ZXJ5X3dvcmssIGF0aDZrbF9yZWNvdmVyeV93b3JrKTsNCit9DQorDQordm9pZCBhdGg2a2xfcmVj
b3ZlcnlfY2xlYW51cChzdHJ1Y3QgYXRoNmtsICphcikNCit7DQorICAgICAgIGFyLT5md19yZWNv
dmVyeS5lbmFibGUgPSBmYWxzZTsNCisNCisgICAgICAgY2FuY2VsX3dvcmtfc3luYygmYXItPmZ3
X3JlY292ZXJ5LnJlY292ZXJ5X3dvcmspOw0KK30NCisNCit2b2lkIGF0aDZrbF9yZWNvdmVyeV9z
dXNwZW5kKHN0cnVjdCBhdGg2a2wgKmFyKQ0KK3sNCisgICAgICAgYXRoNmtsX3JlY292ZXJ5X2Ns
ZWFudXAoYXIpOw0KKw0KKyAgICAgICAvKiBQcm9jZXNzIHBlbmRpbmcgZncgZXJyb3IgZGV0ZWN0
aW9uICovDQorICAgICAgIGlmIChhci0+ZndfcmVjb3ZlcnkuZXJyX3JlYXNvbikNCisgICAgICAg
ICAgICAgICBhdGg2a2xfaW5pdF9od19yZXN0YXJ0KGFyKTsNCit9DQpkaWZmIC0tZ2l0IGEvZHJp
dmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDZrbC9zZGlvLmMgYi9kcml2ZXJzL25ldC93aXJlbGVz
cy9hdGgvYXRoNmtsL3NkaW8uYw0KaW5kZXggY2MxN2ZlMC4uYTcyYTRkMCAxMDA2NDQNCi0tLSBh
L2RyaXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvc2Rpby5jDQorKysgYi9kcml2ZXJzL25l
dC93aXJlbGVzcy9hdGgvYXRoNmtsL3NkaW8uYw0KQEAgLTkzMSw2ICs5MzEsOSBAQCBzdGF0aWMg
aW50IGF0aDZrbF9zZGlvX3Jlc3VtZShzdHJ1Y3QgYXRoNmtsICphcikNCg0KICAgICAgICBjYXNl
IEFUSDZLTF9TVEFURV9SRVNVTUlORzoNCiAgICAgICAgICAgICAgICBicmVhazsNCisNCisgICAg
ICAgY2FzZSBBVEg2S0xfU1RBVEVfUkVDT1ZFUlk6DQorICAgICAgICAgICAgICAgYnJlYWs7DQog
ICAgICAgIH0NCg0KICAgICAgICBhdGg2a2xfY2ZnODAyMTFfcmVzdW1lKGFyKTsNCmRpZmYgLS1n
aXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9hdGgvYXRoNmtsL3R4cnguYyBiL2RyaXZlcnMvbmV0
L3dpcmVsZXNzL2F0aC9hdGg2a2wvdHhyeC5jDQppbmRleCA3NDBhNDg4Li5jYmUxYTlkIDEwMDY0
NA0KLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvYXRoL2F0aDZrbC90eHJ4LmMNCisrKyBiL2Ry
aXZlcnMvbmV0L3dpcmVsZXNzL2F0aC9hdGg2a2wvdHhyeC5jDQpAQCAtMjg4LDcgKzI4OCw4IEBA
IGludCBhdGg2a2xfY29udHJvbF90eCh2b2lkICpkZXZ0LCBzdHJ1Y3Qgc2tfYnVmZiAqc2tiLA0K
ICAgICAgICBpbnQgc3RhdHVzID0gMDsNCiAgICAgICAgc3RydWN0IGF0aDZrbF9jb29raWUgKmNv
b2tpZSA9IE5VTEw7DQoNCi0gICAgICAgaWYgKFdBUk5fT05fT05DRShhci0+c3RhdGUgPT0gQVRI
NktMX1NUQVRFX1dPVykpIHsNCisgICAgICAgaWYgKFdBUk5fT05fT05DRShhci0+c3RhdGUgPT0g
QVRINktMX1NUQVRFX1dPVykgfHwNCisgICAgICAgICAgIGFyLT5zdGF0ZSA9PSBBVEg2S0xfU1RB
VEVfUkVDT1ZFUlkpIHsNCiAgICAgICAgICAgICAgICBkZXZfa2ZyZWVfc2tiKHNrYik7DQogICAg
ICAgICAgICAgICAgcmV0dXJuIC1FQUNDRVM7DQogICAgICAgIH0NCi0tDQoxLjcuMC40DQoNCg==

Subject: [PATCH 4/4] ath6kl: Recover from "wmi ctrl ep is full" condition

In some error conditions, fw pauses HTC pipes which would
result in control endpoint full condition. When we hit this
case, most of the time the device will be unusable. Re-initialize
the target to recover from this situation.

Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
---
drivers/net/wireless/ath/ath6kl/core.h | 1 +
drivers/net/wireless/ath/ath6kl/recovery.c | 2 ++
drivers/net/wireless/ath/ath6kl/txrx.c | 1 +
3 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index b2cbecf..ac90b31 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -660,6 +660,7 @@ enum ath6kl_state {
enum ath6kl_fw_err {
ATH6KL_FW_ASSERT,
ATH6KL_FW_HB_RESP_FAILURE,
+ ATH6KL_FW_EP_FULL,
};

struct ath6kl {
diff --git a/drivers/net/wireless/ath/ath6kl/recovery.c b/drivers/net/wireless/ath/ath6kl/recovery.c
index 9161d84..26e0816 100644
--- a/drivers/net/wireless/ath/ath6kl/recovery.c
+++ b/drivers/net/wireless/ath/ath6kl/recovery.c
@@ -30,6 +30,8 @@ static void ath6kl_recovery_work(struct work_struct *work)
ath6kl_init_hw_restart(ar);

ar->state = ATH6KL_STATE_ON;
+ clear_bit(WMI_CTRL_EP_FULL, &ar->flag);
+
ar->fw_recovery.err_reason = 0;

if (ar->fw_recovery.enable)
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index cbe1a9d..e867193 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -594,6 +594,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
*/
set_bit(WMI_CTRL_EP_FULL, &ar->flag);
ath6kl_err("wmi ctrl ep is full\n");
+ ath6kl_recovery_err_notify(ar, ATH6KL_FW_EP_FULL);
return action;
}

--
1.7.0.4


2012-08-30 09:27:53

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/4] ath6kl: Refactor ath6kl_init_hw_start() and ath6kl_init_hw_stop()

On 08/29/2012 05:10 PM, Vasanthakumar Thiagarajan wrote:
> So that these functions will be used to re-initialize the fw
> upon detecting fw error. This refactoring moves ar->state
> setting out of core stop/start functionality.
>
> Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>

Thanks, all four patches applied.

I had to fix one parenthesis alignment in patch 3, but that was easy to do.

Kalle

Subject: [PATCH 3/4] ath6kl: Add support to detect fw error through heart beat

This patch adds support to detect fw error condition by sending
periodic message (heart beat challenge) to firmware. Upon reception
of the message, fw would send a response event to driver. When
there are no reponses from fw for about 5 cmd driver would
trigger the recovery logic assuming that fw has gone into an
error state.

Capable fw will advertise this capability through
ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL bit. This feature
is disabled by default, can be enabled through a modparam
(heart_beat_poll). This modparam also confiures the polling
interval in msecs.

Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +-
drivers/net/wireless/ath/ath6kl/core.c | 9 +++
drivers/net/wireless/ath/ath6kl/core.h | 16 +++++
drivers/net/wireless/ath/ath6kl/init.c | 6 --
drivers/net/wireless/ath/ath6kl/recovery.c | 89 +++++++++++++++++++++++++++-
drivers/net/wireless/ath/ath6kl/wmi.c | 14 ++++
drivers/net/wireless/ath/ath6kl/wmi.h | 2 +
7 files changed, 129 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index b4c549d..7c652ff 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2524,7 +2524,7 @@ static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
if (err)
return err;

- ar->fw_recovery.enable = true;
+ ath6kl_recovery_resume(ar);

return 0;
}
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index adcaa96..fd5dd3a 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -33,6 +33,7 @@ static unsigned int wow_mode;
static unsigned int uart_debug;
static unsigned int ath6kl_p2p;
static unsigned int testmode;
+static unsigned int heart_beat_poll;

module_param(debug_mask, uint, 0644);
module_param(suspend_mode, uint, 0644);
@@ -40,6 +41,9 @@ module_param(wow_mode, uint, 0644);
module_param(uart_debug, uint, 0644);
module_param(ath6kl_p2p, uint, 0644);
module_param(testmode, uint, 0644);
+module_param(heart_beat_poll, uint, 0644);
+MODULE_PARM_DESC(heart_beat_poll, "Enable fw error detection periodic" \
+ "polling. This also specifies the polling interval in msecs");

void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb)
{
@@ -202,6 +206,11 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
__func__, wdev->netdev->name, wdev->netdev, ar);

+ if (heart_beat_poll &&
+ test_bit(ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
+ ar->fw_capabilities))
+ ar->fw_recovery.hb_poll = heart_beat_poll;
+
ath6kl_recovery_init(ar);

return ret;
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index c7dcdad..b2cbecf 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -130,6 +130,12 @@ enum ath6kl_fw_capability {
/* Firmware supports sched scan decoupled from host sleep */
ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2,

+ /*
+ * Firmware capability for hang detection through heart beat
+ * challenge messages.
+ */
+ ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
+
/* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX,
};
@@ -649,8 +655,11 @@ enum ath6kl_state {
};

/* Fw error recovery */
+#define ATH6KL_HB_RESP_MISS_THRES 5
+
enum ath6kl_fw_err {
ATH6KL_FW_ASSERT,
+ ATH6KL_FW_HB_RESP_FAILURE,
};

struct ath6kl {
@@ -800,6 +809,11 @@ struct ath6kl {
bool enable;
struct work_struct recovery_work;
unsigned long err_reason;
+ unsigned long hb_poll;
+ struct timer_list hb_timer;
+ u32 seq_num;
+ bool hb_pending;
+ u8 hb_misscnt;
} fw_recovery;

#ifdef CONFIG_ATH6KL_DEBUG
@@ -940,7 +954,9 @@ void ath6kl_core_destroy(struct ath6kl *ar);
/* Fw error recovery */
void ath6kl_init_hw_restart(struct ath6kl *ar);
void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason);
+void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie);
void ath6kl_recovery_init(struct ath6kl *ar);
void ath6kl_recovery_cleanup(struct ath6kl *ar);
void ath6kl_recovery_suspend(struct ath6kl *ar);
+void ath6kl_recovery_resume(struct ath6kl *ar);
#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 301443c..6e270fa 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1697,9 +1697,6 @@ int ath6kl_init_hw_stop(struct ath6kl *ar)

void ath6kl_init_hw_restart(struct ath6kl *ar)
{
-
- ar->state = ATH6KL_STATE_RECOVERY;
-
ath6kl_cfg80211_stop_all(ar);

if (__ath6kl_init_hw_stop(ar))
@@ -1709,9 +1706,6 @@ void ath6kl_init_hw_restart(struct ath6kl *ar)
ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to restart during fw error recovery\n");
return;
}
-
- ar->state = ATH6KL_STATE_ON;
- ar->fw_recovery.err_reason = 0;
}

/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */
diff --git a/drivers/net/wireless/ath/ath6kl/recovery.c b/drivers/net/wireless/ath/ath6kl/recovery.c
index c225fc4..9161d84 100644
--- a/drivers/net/wireless/ath/ath6kl/recovery.c
+++ b/drivers/net/wireless/ath/ath6kl/recovery.c
@@ -23,7 +23,18 @@ static void ath6kl_recovery_work(struct work_struct *work)
struct ath6kl *ar = container_of(work, struct ath6kl,
fw_recovery.recovery_work);

+ ar->state = ATH6KL_STATE_RECOVERY;
+
+ del_timer_sync(&ar->fw_recovery.hb_timer);
+
ath6kl_init_hw_restart(ar);
+
+ ar->state = ATH6KL_STATE_ON;
+ ar->fw_recovery.err_reason = 0;
+
+ if (ar->fw_recovery.enable)
+ mod_timer(&ar->fw_recovery.hb_timer, jiffies +
+ msecs_to_jiffies(ar->fw_recovery.hb_poll));
}

void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason)
@@ -37,18 +48,72 @@ void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason)
queue_work(ar->ath6kl_wq, &ar->fw_recovery.recovery_work);
}

+void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie)
+{
+ if (cookie == ar->fw_recovery.seq_num)
+ ar->fw_recovery.hb_pending = false;
+}
+
+static void ath6kl_recovery_hb_timer(unsigned long data)
+{
+ struct ath6kl *ar = (struct ath6kl *) data;
+ int err;
+
+ if (!ar->fw_recovery.enable)
+ return;
+
+ if (ar->fw_recovery.hb_pending)
+ ar->fw_recovery.hb_misscnt++;
+ else
+ ar->fw_recovery.hb_misscnt = 0;
+
+ if (ar->fw_recovery.hb_misscnt > ATH6KL_HB_RESP_MISS_THRES) {
+ ar->fw_recovery.hb_misscnt = 0;
+ ar->fw_recovery.seq_num = 0;
+ ar->fw_recovery.hb_pending = false;
+ ath6kl_recovery_err_notify(ar, ATH6KL_FW_HB_RESP_FAILURE);
+ return;
+ }
+
+ ar->fw_recovery.seq_num++;
+ ar->fw_recovery.hb_pending = true;
+
+ err = ath6kl_wmi_get_challenge_resp_cmd(ar->wmi,
+ ar->fw_recovery.seq_num, 0);
+ if (err)
+ ath6kl_warn("Failed to send hb challenge request, err:%d\n",
+ err);
+
+ if ((ar->state == ATH6KL_STATE_RECOVERY) || !ar->fw_recovery.enable)
+ return;
+
+ mod_timer(&ar->fw_recovery.hb_timer, jiffies +
+ msecs_to_jiffies(ar->fw_recovery.hb_poll));
+}
+
void ath6kl_recovery_init(struct ath6kl *ar)
{
struct ath6kl_fw_recovery *recovery = &ar->fw_recovery;

recovery->enable = true;
INIT_WORK(&recovery->recovery_work, ath6kl_recovery_work);
+ recovery->seq_num = 0;
+ recovery->hb_misscnt = 0;
+ ar->fw_recovery.hb_pending = false;
+ ar->fw_recovery.hb_timer.function = ath6kl_recovery_hb_timer;
+ ar->fw_recovery.hb_timer.data = (unsigned long) ar;
+ init_timer_deferrable(&ar->fw_recovery.hb_timer);
+
+ if (ar->fw_recovery.hb_poll)
+ mod_timer(&ar->fw_recovery.hb_timer, jiffies +
+ msecs_to_jiffies(ar->fw_recovery.hb_poll));
}

void ath6kl_recovery_cleanup(struct ath6kl *ar)
{
ar->fw_recovery.enable = false;

+ del_timer_sync(&ar->fw_recovery.hb_timer);
cancel_work_sync(&ar->fw_recovery.recovery_work);
}

@@ -56,7 +121,27 @@ void ath6kl_recovery_suspend(struct ath6kl *ar)
{
ath6kl_recovery_cleanup(ar);

+ if (!ar->fw_recovery.err_reason)
+ return;
+
/* Process pending fw error detection */
- if (ar->fw_recovery.err_reason)
- ath6kl_init_hw_restart(ar);
+ ar->fw_recovery.err_reason = 0;
+ WARN_ON(ar->state != ATH6KL_STATE_ON);
+ ar->state = ATH6KL_STATE_RECOVERY;
+ ath6kl_init_hw_restart(ar);
+ ar->state = ATH6KL_STATE_ON;
+}
+
+void ath6kl_recovery_resume(struct ath6kl *ar)
+{
+ ar->fw_recovery.enable = true;
+
+ if (!ar->fw_recovery.hb_poll)
+ return;
+
+ ar->fw_recovery.hb_pending = false;
+ ar->fw_recovery.seq_num = 0;
+ ar->fw_recovery.hb_misscnt = 0;
+ mod_timer(&ar->fw_recovery.hb_timer,
+ jiffies + msecs_to_jiffies(ar->fw_recovery.hb_poll));
}
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index e95b035..2624ce8 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -3756,6 +3756,19 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout)
NO_SYNC_WMIFLAG);
}

+static void ath6kl_wmi_hb_challenge_resp_event(struct wmi *wmi, u8 *datap,
+ int len)
+{
+ struct wmix_hb_challenge_resp_cmd *cmd;
+
+ if (len < sizeof(struct wmix_hb_challenge_resp_cmd))
+ return;
+
+ cmd = (struct wmix_hb_challenge_resp_cmd *) datap;
+ ath6kl_recovery_hb_event(wmi->parent_dev,
+ le32_to_cpu(cmd->cookie));
+}
+
static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
{
struct wmix_cmd_hdr *cmd;
@@ -3780,6 +3793,7 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
switch (id) {
case WMIX_HB_CHALLENGE_RESP_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n");
+ ath6kl_wmi_hb_challenge_resp_event(wmi, datap, len);
break;
case WMIX_DBGLOG_EVENTID:
ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index a791b1b..3d239b3 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -2714,6 +2714,8 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout);

void ath6kl_wmi_sscan_timer(unsigned long ptr);

+int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source);
+
struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx);
void *ath6kl_wmi_init(struct ath6kl *devt);
void ath6kl_wmi_shutdown(struct wmi *wmi);
--
1.7.0.4


Subject: [PATCH 2/4] ath6kl: Recover from fw crash

Re-initialize the target when fw crash is reported.
This would make the device functional again after
target crash. During the target re-initialization
it is made sure that target is not bugged with data/cmd
request, ar->state ATH6KL_STATE_RECOVERY is used
for this purpose.

Signed-off-by: Vasanthakumar Thiagarajan <[email protected]>
---
drivers/net/wireless/ath/ath6kl/Makefile | 1 +
drivers/net/wireless/ath/ath6kl/cfg80211.c | 17 +++++++-
drivers/net/wireless/ath/ath6kl/core.c | 4 ++
drivers/net/wireless/ath/ath6kl/core.h | 18 ++++++++
drivers/net/wireless/ath/ath6kl/debug.h | 1 +
drivers/net/wireless/ath/ath6kl/hif.c | 1 +
drivers/net/wireless/ath/ath6kl/init.c | 19 ++++++++
drivers/net/wireless/ath/ath6kl/recovery.c | 62 ++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath6kl/sdio.c | 3 +
drivers/net/wireless/ath/ath6kl/txrx.c | 3 +-
10 files changed, 126 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/wireless/ath/ath6kl/recovery.c

diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index 8cae888..cab0ec0 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -34,6 +34,7 @@ ath6kl_core-y += main.o
ath6kl_core-y += txrx.o
ath6kl_core-y += wmi.o
ath6kl_core-y += core.o
+ath6kl_core-y += recovery.o
ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o

obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index fb20ff6..b4c549d 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2510,14 +2510,23 @@ static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
{
struct ath6kl *ar = wiphy_priv(wiphy);

+ ath6kl_recovery_suspend(ar);
+
return ath6kl_hif_suspend(ar, wow);
}

static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
{
struct ath6kl *ar = wiphy_priv(wiphy);
+ int err;
+
+ err = ath6kl_hif_resume(ar);
+ if (err)
+ return err;

- return ath6kl_hif_resume(ar);
+ ar->fw_recovery.enable = true;
+
+ return 0;
}

/*
@@ -3441,6 +3450,10 @@ void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
clear_bit(CONNECTED, &vif->flags);
clear_bit(CONNECT_PEND, &vif->flags);

+ /* Stop netdev queues, needed during recovery */
+ netif_stop_queue(vif->ndev);
+ netif_carrier_off(vif->ndev);
+
/* disable scanning */
if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
@@ -3454,7 +3467,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
struct ath6kl_vif *vif;

vif = ath6kl_vif_first(ar);
- if (!vif) {
+ if (!vif && ar->state != ATH6KL_STATE_RECOVERY) {
/* save the current power mode before enabling power save */
ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;

diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index 82c4dd2..adcaa96 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -202,6 +202,8 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
__func__, wdev->netdev->name, wdev->netdev, ar);

+ ath6kl_recovery_init(ar);
+
return ret;

err_rxbuf_cleanup:
@@ -291,6 +293,8 @@ void ath6kl_core_cleanup(struct ath6kl *ar)
{
ath6kl_hif_power_off(ar);

+ ath6kl_recovery_cleanup(ar);
+
destroy_workqueue(ar->ath6kl_wq);

if (ar->htc_target)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 8b31b9a..c7dcdad 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -645,6 +645,12 @@ enum ath6kl_state {
ATH6KL_STATE_DEEPSLEEP,
ATH6KL_STATE_CUTPOWER,
ATH6KL_STATE_WOW,
+ ATH6KL_STATE_RECOVERY,
+};
+
+/* Fw error recovery */
+enum ath6kl_fw_err {
+ ATH6KL_FW_ASSERT,
};

struct ath6kl {
@@ -790,6 +796,12 @@ struct ath6kl {

bool wiphy_registered;

+ struct ath6kl_fw_recovery {
+ bool enable;
+ struct work_struct recovery_work;
+ unsigned long err_reason;
+ } fw_recovery;
+
#ifdef CONFIG_ATH6KL_DEBUG
struct {
struct sk_buff_head fwlog_queue;
@@ -925,4 +937,10 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type);
void ath6kl_core_cleanup(struct ath6kl *ar);
void ath6kl_core_destroy(struct ath6kl *ar);

+/* Fw error recovery */
+void ath6kl_init_hw_restart(struct ath6kl *ar);
+void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason);
+void ath6kl_recovery_init(struct ath6kl *ar);
+void ath6kl_recovery_cleanup(struct ath6kl *ar);
+void ath6kl_recovery_suspend(struct ath6kl *ar);
#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 49639d8..f97cd4e 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -44,6 +44,7 @@ enum ATH6K_DEBUG_MASK {
ATH6KL_DBG_SUSPEND = BIT(20),
ATH6KL_DBG_USB = BIT(21),
ATH6KL_DBG_USB_BULK = BIT(22),
+ ATH6KL_DBG_RECOVERY = BIT(23),
ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */
};

diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c
index 68ed6c2..029914a 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.c
+++ b/drivers/net/wireless/ath/ath6kl/hif.c
@@ -136,6 +136,7 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)

ath6kl_hif_dump_fw_crash(dev->ar);
ath6kl_read_fwlogs(dev->ar);
+ ath6kl_recovery_err_notify(dev->ar, ATH6KL_FW_ASSERT);

return ret;
}
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index be27ebe..301443c 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1695,6 +1695,25 @@ int ath6kl_init_hw_stop(struct ath6kl *ar)
return 0;
}

+void ath6kl_init_hw_restart(struct ath6kl *ar)
+{
+
+ ar->state = ATH6KL_STATE_RECOVERY;
+
+ ath6kl_cfg80211_stop_all(ar);
+
+ if (__ath6kl_init_hw_stop(ar))
+ return;
+
+ if (__ath6kl_init_hw_start(ar)) {
+ ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to restart during fw error recovery\n");
+ return;
+ }
+
+ ar->state = ATH6KL_STATE_ON;
+ ar->fw_recovery.err_reason = 0;
+}
+
/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */
void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
{
diff --git a/drivers/net/wireless/ath/ath6kl/recovery.c b/drivers/net/wireless/ath/ath6kl/recovery.c
new file mode 100644
index 0000000..c225fc4
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/recovery.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "cfg80211.h"
+#include "debug.h"
+
+static void ath6kl_recovery_work(struct work_struct *work)
+{
+ struct ath6kl *ar = container_of(work, struct ath6kl,
+ fw_recovery.recovery_work);
+
+ ath6kl_init_hw_restart(ar);
+}
+
+void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason)
+{
+ ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Fw error detected, reason:%d\n",
+ reason);
+
+ set_bit(reason, &ar->fw_recovery.err_reason);
+
+ if (ar->fw_recovery.enable && ar->state != ATH6KL_STATE_RECOVERY)
+ queue_work(ar->ath6kl_wq, &ar->fw_recovery.recovery_work);
+}
+
+void ath6kl_recovery_init(struct ath6kl *ar)
+{
+ struct ath6kl_fw_recovery *recovery = &ar->fw_recovery;
+
+ recovery->enable = true;
+ INIT_WORK(&recovery->recovery_work, ath6kl_recovery_work);
+}
+
+void ath6kl_recovery_cleanup(struct ath6kl *ar)
+{
+ ar->fw_recovery.enable = false;
+
+ cancel_work_sync(&ar->fw_recovery.recovery_work);
+}
+
+void ath6kl_recovery_suspend(struct ath6kl *ar)
+{
+ ath6kl_recovery_cleanup(ar);
+
+ /* Process pending fw error detection */
+ if (ar->fw_recovery.err_reason)
+ ath6kl_init_hw_restart(ar);
+}
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index cc17fe0..a72a4d0 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -931,6 +931,9 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)

case ATH6KL_STATE_RESUMING:
break;
+
+ case ATH6KL_STATE_RECOVERY:
+ break;
}

ath6kl_cfg80211_resume(ar);
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 740a488..cbe1a9d 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -288,7 +288,8 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb,
int status = 0;
struct ath6kl_cookie *cookie = NULL;

- if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) {
+ if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW) ||
+ ar->state == ATH6KL_STATE_RECOVERY) {
dev_kfree_skb(skb);
return -EACCES;
}
--
1.7.0.4


Subject: Re: [PATCH 2/4] ath6kl: Recover from fw crash



On Friday 31 August 2012 09:15 PM, Jin, Navy wrote:
> Can this feature be disabled by some control bit or module parameters?Once enabled,it is better for user,but more hard to find the root cause,or log chip info before recovery?
> Regards??

Good point, i'll send a follow up patch. thanks!.

Vasanth