diff options
author | David S. Miller <davem@davemloft.net> | 2011-10-11 15:39:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-11 15:39:21 -0400 |
commit | 9687c637388f63b87fcc18eee6e65bcfca4f49ca (patch) | |
tree | 0929bb8dc602c4f86b6b2e95bca94015de2b0868 /drivers | |
parent | 258daca2bc9f97ace65c9480c901fddfce1e20cf (diff) | |
parent | 094daf7db7c47861009899ce23f9177d761e20b0 (diff) |
Merge branch 'for-davem' of git://git.infradead.org/users/linville/wireless-next
Diffstat (limited to 'drivers')
80 files changed, 4489 insertions, 2029 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 9cbac6b445e1..675246a6f7ef 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -60,6 +60,9 @@ static struct usb_device_id btusb_table[] = { | |||
60 | /* Generic Bluetooth USB device */ | 60 | /* Generic Bluetooth USB device */ |
61 | { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, | 61 | { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, |
62 | 62 | ||
63 | /* Broadcom SoftSailing reporting vendor specific */ | ||
64 | { USB_DEVICE(0x05ac, 0x21e1) }, | ||
65 | |||
63 | /* Apple MacBookPro 7,1 */ | 66 | /* Apple MacBookPro 7,1 */ |
64 | { USB_DEVICE(0x05ac, 0x8213) }, | 67 | { USB_DEVICE(0x05ac, 0x8213) }, |
65 | 68 | ||
@@ -708,8 +711,7 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
708 | break; | 711 | break; |
709 | 712 | ||
710 | case HCI_ACLDATA_PKT: | 713 | case HCI_ACLDATA_PKT: |
711 | if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 && | 714 | if (!data->bulk_tx_ep) |
712 | hdev->conn_hash.le_num < 1)) | ||
713 | return -ENODEV; | 715 | return -ENODEV; |
714 | 716 | ||
715 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 717 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 7bba6a82b875..4cf0ad312da1 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
@@ -41,7 +41,7 @@ obj-$(CONFIG_ADM8211) += adm8211.o | |||
41 | 41 | ||
42 | obj-$(CONFIG_MWL8K) += mwl8k.o | 42 | obj-$(CONFIG_MWL8K) += mwl8k.o |
43 | 43 | ||
44 | obj-$(CONFIG_IWLAGN) += iwlwifi/ | 44 | obj-$(CONFIG_IWLWIFI) += iwlwifi/ |
45 | obj-$(CONFIG_IWLWIFI_LEGACY) += iwlegacy/ | 45 | obj-$(CONFIG_IWLWIFI_LEGACY) += iwlegacy/ |
46 | obj-$(CONFIG_RT2X00) += rt2x00/ | 46 | obj-$(CONFIG_RT2X00) += rt2x00/ |
47 | 47 | ||
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 298601436ee2..39322d4121b7 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -500,10 +500,9 @@ exit: | |||
500 | 500 | ||
501 | #define HEX2STR_BUFFERS 4 | 501 | #define HEX2STR_BUFFERS 4 |
502 | #define HEX2STR_MAX_LEN 64 | 502 | #define HEX2STR_MAX_LEN 64 |
503 | #define BIN2HEX(x) ((x) < 10 ? '0' + (x) : (x) + 'A' - 10) | ||
504 | 503 | ||
505 | /* Convert binary data into hex string */ | 504 | /* Convert binary data into hex string */ |
506 | static char *hex2str(void *buf, int len) | 505 | static char *hex2str(void *buf, size_t len) |
507 | { | 506 | { |
508 | static atomic_t a = ATOMIC_INIT(0); | 507 | static atomic_t a = ATOMIC_INIT(0); |
509 | static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1]; | 508 | static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1]; |
@@ -514,18 +513,17 @@ static char *hex2str(void *buf, int len) | |||
514 | if (len > HEX2STR_MAX_LEN) | 513 | if (len > HEX2STR_MAX_LEN) |
515 | len = HEX2STR_MAX_LEN; | 514 | len = HEX2STR_MAX_LEN; |
516 | 515 | ||
517 | if (len <= 0) { | 516 | if (len == 0) |
518 | ret[0] = '\0'; | 517 | goto exit; |
519 | return ret; | ||
520 | } | ||
521 | 518 | ||
522 | while (len--) { | 519 | while (len--) { |
523 | *obuf++ = BIN2HEX(*ibuf >> 4); | 520 | obuf = pack_hex_byte(obuf, *ibuf++); |
524 | *obuf++ = BIN2HEX(*ibuf & 0xf); | ||
525 | *obuf++ = '-'; | 521 | *obuf++ = '-'; |
526 | ibuf++; | ||
527 | } | 522 | } |
528 | *(--obuf) = '\0'; | 523 | obuf--; |
524 | |||
525 | exit: | ||
526 | *obuf = '\0'; | ||
529 | 527 | ||
530 | return ret; | 528 | return ret; |
531 | } | 529 | } |
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index bba4f6fcf7e2..6ed4c0717e3e 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -563,7 +563,7 @@ ath5k_get_stats(struct ieee80211_hw *hw, | |||
563 | 563 | ||
564 | 564 | ||
565 | static int | 565 | static int |
566 | ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 566 | ath5k_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, |
567 | const struct ieee80211_tx_queue_params *params) | 567 | const struct ieee80211_tx_queue_params *params) |
568 | { | 568 | { |
569 | struct ath5k_hw *ah = hw->priv; | 569 | struct ath5k_hw *ah = hw->priv; |
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index e1bb07ea8e80..8f7a0d1c290c 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile | |||
@@ -31,5 +31,7 @@ ath6kl-y += init.o | |||
31 | ath6kl-y += main.o | 31 | ath6kl-y += main.o |
32 | ath6kl-y += txrx.o | 32 | ath6kl-y += txrx.o |
33 | ath6kl-y += wmi.o | 33 | ath6kl-y += wmi.o |
34 | ath6kl-y += node.o | ||
35 | ath6kl-y += sdio.o | 34 | ath6kl-y += sdio.o |
35 | ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o | ||
36 | |||
37 | ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c index 84676697d7eb..c5d11cc536e0 100644 --- a/drivers/net/wireless/ath/ath6kl/bmi.c +++ b/drivers/net/wireless/ath/ath6kl/bmi.c | |||
@@ -62,14 +62,14 @@ static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar) | |||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar, bool need_timeout) | 65 | static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar) |
66 | { | 66 | { |
67 | unsigned long timeout; | 67 | unsigned long timeout; |
68 | u32 rx_word = 0; | 68 | u32 rx_word = 0; |
69 | int ret = 0; | 69 | int ret = 0; |
70 | 70 | ||
71 | timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); | 71 | timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); |
72 | while ((!need_timeout || time_before(jiffies, timeout)) && !rx_word) { | 72 | while (time_before(jiffies, timeout) && !rx_word) { |
73 | ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS, | 73 | ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS, |
74 | (u8 *)&rx_word, sizeof(rx_word), | 74 | (u8 *)&rx_word, sizeof(rx_word), |
75 | HIF_RD_SYNC_BYTE_INC); | 75 | HIF_RD_SYNC_BYTE_INC); |
@@ -109,8 +109,7 @@ static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len) | |||
109 | return ret; | 109 | return ret; |
110 | } | 110 | } |
111 | 111 | ||
112 | static int ath6kl_bmi_recv_buf(struct ath6kl *ar, | 112 | static int ath6kl_bmi_recv_buf(struct ath6kl *ar, u8 *buf, u32 len) |
113 | u8 *buf, u32 len, bool want_timeout) | ||
114 | { | 113 | { |
115 | int ret; | 114 | int ret; |
116 | u32 addr; | 115 | u32 addr; |
@@ -162,7 +161,7 @@ static int ath6kl_bmi_recv_buf(struct ath6kl *ar, | |||
162 | * a function of Host processor speed. | 161 | * a function of Host processor speed. |
163 | */ | 162 | */ |
164 | if (len >= 4) { /* NB: Currently, always true */ | 163 | if (len >= 4) { /* NB: Currently, always true */ |
165 | ret = ath6kl_bmi_get_rx_lkahd(ar, want_timeout); | 164 | ret = ath6kl_bmi_get_rx_lkahd(ar); |
166 | if (ret) | 165 | if (ret) |
167 | return ret; | 166 | return ret; |
168 | } | 167 | } |
@@ -220,7 +219,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, | |||
220 | } | 219 | } |
221 | 220 | ||
222 | ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version, | 221 | ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version, |
223 | sizeof(targ_info->version), true); | 222 | sizeof(targ_info->version)); |
224 | if (ret) { | 223 | if (ret) { |
225 | ath6kl_err("Unable to recv target info: %d\n", ret); | 224 | ath6kl_err("Unable to recv target info: %d\n", ret); |
226 | return ret; | 225 | return ret; |
@@ -230,8 +229,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, | |||
230 | /* Determine how many bytes are in the Target's targ_info */ | 229 | /* Determine how many bytes are in the Target's targ_info */ |
231 | ret = ath6kl_bmi_recv_buf(ar, | 230 | ret = ath6kl_bmi_recv_buf(ar, |
232 | (u8 *)&targ_info->byte_count, | 231 | (u8 *)&targ_info->byte_count, |
233 | sizeof(targ_info->byte_count), | 232 | sizeof(targ_info->byte_count)); |
234 | true); | ||
235 | if (ret) { | 233 | if (ret) { |
236 | ath6kl_err("unable to read target info byte count: %d\n", | 234 | ath6kl_err("unable to read target info byte count: %d\n", |
237 | ret); | 235 | ret); |
@@ -252,8 +250,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, | |||
252 | ((u8 *)targ_info) + | 250 | ((u8 *)targ_info) + |
253 | sizeof(targ_info->byte_count), | 251 | sizeof(targ_info->byte_count), |
254 | sizeof(*targ_info) - | 252 | sizeof(*targ_info) - |
255 | sizeof(targ_info->byte_count), | 253 | sizeof(targ_info->byte_count)); |
256 | true); | ||
257 | 254 | ||
258 | if (ret) { | 255 | if (ret) { |
259 | ath6kl_err("Unable to read target info (%d bytes): %d\n", | 256 | ath6kl_err("Unable to read target info (%d bytes): %d\n", |
@@ -311,7 +308,7 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) | |||
311 | ret); | 308 | ret); |
312 | return ret; | 309 | return ret; |
313 | } | 310 | } |
314 | ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len, true); | 311 | ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len); |
315 | if (ret) { | 312 | if (ret) { |
316 | ath6kl_err("Unable to read from the device: %d\n", | 313 | ath6kl_err("Unable to read from the device: %d\n", |
317 | ret); | 314 | ret); |
@@ -424,7 +421,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param) | |||
424 | return ret; | 421 | return ret; |
425 | } | 422 | } |
426 | 423 | ||
427 | ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), false); | 424 | ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param)); |
428 | if (ret) { | 425 | if (ret) { |
429 | ath6kl_err("Unable to read from the device: %d\n", ret); | 426 | ath6kl_err("Unable to read from the device: %d\n", ret); |
430 | return ret; | 427 | return ret; |
@@ -504,7 +501,7 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param) | |||
504 | return ret; | 501 | return ret; |
505 | } | 502 | } |
506 | 503 | ||
507 | ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), true); | 504 | ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param)); |
508 | if (ret) { | 505 | if (ret) { |
509 | ath6kl_err("Unable to read from the device: %d\n", ret); | 506 | ath6kl_err("Unable to read from the device: %d\n", ret); |
510 | return ret; | 507 | return ret; |
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h index 83546d76d979..96851d5df24b 100644 --- a/drivers/net/wireless/ath/ath6kl/bmi.h +++ b/drivers/net/wireless/ath/ath6kl/bmi.h | |||
@@ -139,8 +139,8 @@ | |||
139 | */ | 139 | */ |
140 | 140 | ||
141 | #define TARGET_VERSION_SENTINAL 0xffffffff | 141 | #define TARGET_VERSION_SENTINAL 0xffffffff |
142 | #define TARGET_TYPE_AR6003 3 | 142 | #define TARGET_TYPE_AR6003 3 |
143 | 143 | #define TARGET_TYPE_AR6004 5 | |
144 | #define BMI_ROMPATCH_INSTALL 9 | 144 | #define BMI_ROMPATCH_INSTALL 9 |
145 | /* | 145 | /* |
146 | * Semantics: Install a ROM Patch. | 146 | * Semantics: Install a ROM Patch. |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 14559ffb1453..3aff36bad5d3 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -17,6 +17,12 @@ | |||
17 | #include "core.h" | 17 | #include "core.h" |
18 | #include "cfg80211.h" | 18 | #include "cfg80211.h" |
19 | #include "debug.h" | 19 | #include "debug.h" |
20 | #include "hif-ops.h" | ||
21 | #include "testmode.h" | ||
22 | |||
23 | static unsigned int ath6kl_p2p; | ||
24 | |||
25 | module_param(ath6kl_p2p, uint, 0644); | ||
20 | 26 | ||
21 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ | 27 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ |
22 | .bitrate = (_rate), \ | 28 | .bitrate = (_rate), \ |
@@ -152,8 +158,7 @@ static int ath6kl_set_auth_type(struct ath6kl *ar, | |||
152 | break; | 158 | break; |
153 | 159 | ||
154 | case NL80211_AUTHTYPE_AUTOMATIC: | 160 | case NL80211_AUTHTYPE_AUTOMATIC: |
155 | ar->dot11_auth_mode = OPEN_AUTH; | 161 | ar->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH; |
156 | ar->auto_auth_stage = AUTH_OPEN_IN_PROGRESS; | ||
157 | break; | 162 | break; |
158 | 163 | ||
159 | default: | 164 | default: |
@@ -167,7 +172,8 @@ static int ath6kl_set_auth_type(struct ath6kl *ar, | |||
167 | static int ath6kl_set_cipher(struct ath6kl *ar, u32 cipher, bool ucast) | 172 | static int ath6kl_set_cipher(struct ath6kl *ar, u32 cipher, bool ucast) |
168 | { | 173 | { |
169 | u8 *ar_cipher = ucast ? &ar->prwise_crypto : &ar->grp_crypto; | 174 | u8 *ar_cipher = ucast ? &ar->prwise_crypto : &ar->grp_crypto; |
170 | u8 *ar_cipher_len = ucast ? &ar->prwise_crypto_len : &ar->grp_crpto_len; | 175 | u8 *ar_cipher_len = ucast ? &ar->prwise_crypto_len : |
176 | &ar->grp_crypto_len; | ||
171 | 177 | ||
172 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n", | 178 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n", |
173 | __func__, cipher, ucast); | 179 | __func__, cipher, ucast); |
@@ -354,6 +360,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
354 | } | 360 | } |
355 | 361 | ||
356 | if (!ar->usr_bss_filter) { | 362 | if (!ar->usr_bss_filter) { |
363 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); | ||
357 | if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) { | 364 | if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) { |
358 | ath6kl_err("couldn't set bss filtering\n"); | 365 | ath6kl_err("couldn't set bss filtering\n"); |
359 | up(&ar->sem); | 366 | up(&ar->sem); |
@@ -370,14 +377,14 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
370 | __func__, | 377 | __func__, |
371 | ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto, | 378 | ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto, |
372 | ar->prwise_crypto_len, ar->grp_crypto, | 379 | ar->prwise_crypto_len, ar->grp_crypto, |
373 | ar->grp_crpto_len, ar->ch_hint); | 380 | ar->grp_crypto_len, ar->ch_hint); |
374 | 381 | ||
375 | ar->reconnect_flag = 0; | 382 | ar->reconnect_flag = 0; |
376 | status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type, | 383 | status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type, |
377 | ar->dot11_auth_mode, ar->auth_mode, | 384 | ar->dot11_auth_mode, ar->auth_mode, |
378 | ar->prwise_crypto, | 385 | ar->prwise_crypto, |
379 | ar->prwise_crypto_len, | 386 | ar->prwise_crypto_len, |
380 | ar->grp_crypto, ar->grp_crpto_len, | 387 | ar->grp_crypto, ar->grp_crypto_len, |
381 | ar->ssid_len, ar->ssid, | 388 | ar->ssid_len, ar->ssid, |
382 | ar->req_bssid, ar->ch_hint, | 389 | ar->req_bssid, ar->ch_hint, |
383 | ar->connect_ctrl_flags); | 390 | ar->connect_ctrl_flags); |
@@ -407,6 +414,53 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
407 | return 0; | 414 | return 0; |
408 | } | 415 | } |
409 | 416 | ||
417 | static int ath6kl_add_bss_if_needed(struct ath6kl *ar, const u8 *bssid, | ||
418 | struct ieee80211_channel *chan, | ||
419 | const u8 *beacon_ie, size_t beacon_ie_len) | ||
420 | { | ||
421 | struct cfg80211_bss *bss; | ||
422 | u8 *ie; | ||
423 | |||
424 | bss = cfg80211_get_bss(ar->wdev->wiphy, chan, bssid, | ||
425 | ar->ssid, ar->ssid_len, WLAN_CAPABILITY_ESS, | ||
426 | WLAN_CAPABILITY_ESS); | ||
427 | if (bss == NULL) { | ||
428 | /* | ||
429 | * Since cfg80211 may not yet know about the BSS, | ||
430 | * generate a partial entry until the first BSS info | ||
431 | * event becomes available. | ||
432 | * | ||
433 | * Prepend SSID element since it is not included in the Beacon | ||
434 | * IEs from the target. | ||
435 | */ | ||
436 | ie = kmalloc(2 + ar->ssid_len + beacon_ie_len, GFP_KERNEL); | ||
437 | if (ie == NULL) | ||
438 | return -ENOMEM; | ||
439 | ie[0] = WLAN_EID_SSID; | ||
440 | ie[1] = ar->ssid_len; | ||
441 | memcpy(ie + 2, ar->ssid, ar->ssid_len); | ||
442 | memcpy(ie + 2 + ar->ssid_len, beacon_ie, beacon_ie_len); | ||
443 | bss = cfg80211_inform_bss(ar->wdev->wiphy, chan, | ||
444 | bssid, 0, WLAN_CAPABILITY_ESS, 100, | ||
445 | ie, 2 + ar->ssid_len + beacon_ie_len, | ||
446 | 0, GFP_KERNEL); | ||
447 | if (bss) | ||
448 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added dummy bss for " | ||
449 | "%pM prior to indicating connect/roamed " | ||
450 | "event\n", bssid); | ||
451 | kfree(ie); | ||
452 | } else | ||
453 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss " | ||
454 | "entry\n"); | ||
455 | |||
456 | if (bss == NULL) | ||
457 | return -ENOMEM; | ||
458 | |||
459 | cfg80211_put_bss(bss); | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
410 | void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, | 464 | void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, |
411 | u8 *bssid, u16 listen_intvl, | 465 | u8 *bssid, u16 listen_intvl, |
412 | u16 beacon_intvl, | 466 | u16 beacon_intvl, |
@@ -414,19 +468,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, | |||
414 | u8 beacon_ie_len, u8 assoc_req_len, | 468 | u8 beacon_ie_len, u8 assoc_req_len, |
415 | u8 assoc_resp_len, u8 *assoc_info) | 469 | u8 assoc_resp_len, u8 *assoc_info) |
416 | { | 470 | { |
417 | u16 size = 0; | 471 | struct ieee80211_channel *chan; |
418 | u16 capability = 0; | ||
419 | struct cfg80211_bss *bss = NULL; | ||
420 | struct ieee80211_mgmt *mgmt = NULL; | ||
421 | struct ieee80211_channel *ibss_ch = NULL; | ||
422 | s32 signal = 50 * 100; | ||
423 | u8 ie_buf_len = 0; | ||
424 | unsigned char ie_buf[256]; | ||
425 | unsigned char *ptr_ie_buf = ie_buf; | ||
426 | unsigned char *ieeemgmtbuf = NULL; | ||
427 | u8 source_mac[ETH_ALEN]; | ||
428 | u16 capa_mask; | ||
429 | u16 capa_val; | ||
430 | 472 | ||
431 | /* capinfo + listen interval */ | 473 | /* capinfo + listen interval */ |
432 | u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16); | 474 | u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16); |
@@ -441,7 +483,12 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, | |||
441 | assoc_req_len -= assoc_req_ie_offset; | 483 | assoc_req_len -= assoc_req_ie_offset; |
442 | assoc_resp_len -= assoc_resp_ie_offset; | 484 | assoc_resp_len -= assoc_resp_ie_offset; |
443 | 485 | ||
444 | ar->auto_auth_stage = AUTH_IDLE; | 486 | /* |
487 | * Store Beacon interval here; DTIM period will be available only once | ||
488 | * a Beacon frame from the AP is seen. | ||
489 | */ | ||
490 | ar->assoc_bss_beacon_int = beacon_intvl; | ||
491 | clear_bit(DTIM_PERIOD_AVAIL, &ar->flag); | ||
445 | 492 | ||
446 | if (nw_type & ADHOC_NETWORK) { | 493 | if (nw_type & ADHOC_NETWORK) { |
447 | if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) { | 494 | if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) { |
@@ -452,110 +499,26 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, | |||
452 | } | 499 | } |
453 | 500 | ||
454 | if (nw_type & INFRA_NETWORK) { | 501 | if (nw_type & INFRA_NETWORK) { |
455 | if (ar->wdev->iftype != NL80211_IFTYPE_STATION) { | 502 | if (ar->wdev->iftype != NL80211_IFTYPE_STATION && |
503 | ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
456 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 504 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
457 | "%s: ath6k not in station mode\n", __func__); | 505 | "%s: ath6k not in station mode\n", __func__); |
458 | return; | 506 | return; |
459 | } | 507 | } |
460 | } | 508 | } |
461 | 509 | ||
462 | if (nw_type & ADHOC_NETWORK) { | 510 | chan = ieee80211_get_channel(ar->wdev->wiphy, (int) channel); |
463 | capa_mask = WLAN_CAPABILITY_IBSS; | ||
464 | capa_val = WLAN_CAPABILITY_IBSS; | ||
465 | } else { | ||
466 | capa_mask = WLAN_CAPABILITY_ESS; | ||
467 | capa_val = WLAN_CAPABILITY_ESS; | ||
468 | } | ||
469 | 511 | ||
470 | /* Before informing the join/connect event, make sure that | ||
471 | * bss entry is present in scan list, if it not present | ||
472 | * construct and insert into scan list, otherwise that | ||
473 | * event will be dropped on the way by cfg80211, due to | ||
474 | * this keys will not be plumbed in case of WEP and | ||
475 | * application will not be aware of join/connect status. */ | ||
476 | bss = cfg80211_get_bss(ar->wdev->wiphy, NULL, bssid, | ||
477 | ar->wdev->ssid, ar->wdev->ssid_len, | ||
478 | capa_mask, capa_val); | ||
479 | |||
480 | /* | ||
481 | * Earlier we were updating the cfg about bss by making a beacon frame | ||
482 | * only if the entry for bss is not there. This can have some issue if | ||
483 | * ROAM event is generated and a heavy traffic is ongoing. The ROAM | ||
484 | * event is handled through a work queue and by the time it really gets | ||
485 | * handled, BSS would have been aged out. So it is better to update the | ||
486 | * cfg about BSS irrespective of its entry being present right now or | ||
487 | * not. | ||
488 | */ | ||
489 | 512 | ||
490 | if (nw_type & ADHOC_NETWORK) { | 513 | if (nw_type & ADHOC_NETWORK) { |
491 | /* construct 802.11 mgmt beacon */ | 514 | cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL); |
492 | if (ptr_ie_buf) { | ||
493 | *ptr_ie_buf++ = WLAN_EID_SSID; | ||
494 | *ptr_ie_buf++ = ar->ssid_len; | ||
495 | memcpy(ptr_ie_buf, ar->ssid, ar->ssid_len); | ||
496 | ptr_ie_buf += ar->ssid_len; | ||
497 | |||
498 | *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS; | ||
499 | *ptr_ie_buf++ = 2; /* length */ | ||
500 | *ptr_ie_buf++ = 0; /* ATIM window */ | ||
501 | *ptr_ie_buf++ = 0; /* ATIM window */ | ||
502 | |||
503 | /* TODO: update ibss params and include supported rates, | ||
504 | * DS param set, extened support rates, wmm. */ | ||
505 | |||
506 | ie_buf_len = ptr_ie_buf - ie_buf; | ||
507 | } | ||
508 | |||
509 | capability |= WLAN_CAPABILITY_IBSS; | ||
510 | |||
511 | if (ar->prwise_crypto == WEP_CRYPT) | ||
512 | capability |= WLAN_CAPABILITY_PRIVACY; | ||
513 | |||
514 | memcpy(source_mac, ar->net_dev->dev_addr, ETH_ALEN); | ||
515 | ptr_ie_buf = ie_buf; | ||
516 | } else { | ||
517 | capability = *(u16 *) (&assoc_info[beacon_ie_len]); | ||
518 | memcpy(source_mac, bssid, ETH_ALEN); | ||
519 | ptr_ie_buf = assoc_req_ie; | ||
520 | ie_buf_len = assoc_req_len; | ||
521 | } | ||
522 | |||
523 | size = offsetof(struct ieee80211_mgmt, u) | ||
524 | + sizeof(mgmt->u.beacon) | ||
525 | + ie_buf_len; | ||
526 | |||
527 | ieeemgmtbuf = kzalloc(size, GFP_ATOMIC); | ||
528 | if (!ieeemgmtbuf) { | ||
529 | ath6kl_err("ieee mgmt buf alloc error\n"); | ||
530 | cfg80211_put_bss(bss); | ||
531 | return; | 515 | return; |
532 | } | 516 | } |
533 | 517 | ||
534 | mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; | 518 | if (ath6kl_add_bss_if_needed(ar, bssid, chan, assoc_info, |
535 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 519 | beacon_ie_len) < 0) { |
536 | IEEE80211_STYPE_BEACON); | 520 | ath6kl_err("could not add cfg80211 bss entry for " |
537 | memset(mgmt->da, 0xff, ETH_ALEN); /* broadcast addr */ | 521 | "connect/roamed notification\n"); |
538 | memcpy(mgmt->sa, source_mac, ETH_ALEN); | ||
539 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | ||
540 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_intvl); | ||
541 | mgmt->u.beacon.capab_info = cpu_to_le16(capability); | ||
542 | memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len); | ||
543 | |||
544 | ibss_ch = ieee80211_get_channel(ar->wdev->wiphy, (int)channel); | ||
545 | |||
546 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | ||
547 | "%s: inform bss with bssid %pM channel %d beacon_intvl %d capability 0x%x\n", | ||
548 | __func__, mgmt->bssid, ibss_ch->hw_value, | ||
549 | beacon_intvl, capability); | ||
550 | |||
551 | bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, | ||
552 | ibss_ch, mgmt, | ||
553 | size, signal, GFP_KERNEL); | ||
554 | kfree(ieeemgmtbuf); | ||
555 | cfg80211_put_bss(bss); | ||
556 | |||
557 | if (nw_type & ADHOC_NETWORK) { | ||
558 | cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL); | ||
559 | return; | 522 | return; |
560 | } | 523 | } |
561 | 524 | ||
@@ -568,7 +531,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, | |||
568 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | 531 | WLAN_STATUS_SUCCESS, GFP_KERNEL); |
569 | } else if (ar->sme_state == SME_CONNECTED) { | 532 | } else if (ar->sme_state == SME_CONNECTED) { |
570 | /* inform roam event to cfg80211 */ | 533 | /* inform roam event to cfg80211 */ |
571 | cfg80211_roamed(ar->net_dev, ibss_ch, bssid, | 534 | cfg80211_roamed(ar->net_dev, chan, bssid, |
572 | assoc_req_ie, assoc_req_len, | 535 | assoc_req_ie, assoc_req_len, |
573 | assoc_resp_ie, assoc_resp_len, GFP_KERNEL); | 536 | assoc_resp_ie, assoc_resp_len, GFP_KERNEL); |
574 | } | 537 | } |
@@ -605,6 +568,8 @@ static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy, | |||
605 | 568 | ||
606 | up(&ar->sem); | 569 | up(&ar->sem); |
607 | 570 | ||
571 | ar->sme_state = SME_DISCONNECTED; | ||
572 | |||
608 | return 0; | 573 | return 0; |
609 | } | 574 | } |
610 | 575 | ||
@@ -612,9 +577,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason, | |||
612 | u8 *bssid, u8 assoc_resp_len, | 577 | u8 *bssid, u8 assoc_resp_len, |
613 | u8 *assoc_info, u16 proto_reason) | 578 | u8 *assoc_info, u16 proto_reason) |
614 | { | 579 | { |
615 | struct ath6kl_key *key = NULL; | ||
616 | u16 status; | ||
617 | |||
618 | if (ar->scan_req) { | 580 | if (ar->scan_req) { |
619 | cfg80211_scan_done(ar->scan_req, true); | 581 | cfg80211_scan_done(ar->scan_req, true); |
620 | ar->scan_req = NULL; | 582 | ar->scan_req = NULL; |
@@ -632,164 +594,64 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason, | |||
632 | } | 594 | } |
633 | 595 | ||
634 | if (ar->nw_type & INFRA_NETWORK) { | 596 | if (ar->nw_type & INFRA_NETWORK) { |
635 | if (ar->wdev->iftype != NL80211_IFTYPE_STATION) { | 597 | if (ar->wdev->iftype != NL80211_IFTYPE_STATION && |
598 | ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
636 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 599 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
637 | "%s: ath6k not in station mode\n", __func__); | 600 | "%s: ath6k not in station mode\n", __func__); |
638 | return; | 601 | return; |
639 | } | 602 | } |
640 | } | 603 | } |
641 | 604 | ||
642 | if (!test_bit(CONNECT_PEND, &ar->flag)) { | ||
643 | if (reason != DISCONNECT_CMD) | ||
644 | ath6kl_wmi_disconnect_cmd(ar->wmi); | ||
645 | |||
646 | return; | ||
647 | } | ||
648 | |||
649 | if (reason == NO_NETWORK_AVAIL) { | ||
650 | /* connect cmd failed */ | ||
651 | ath6kl_wmi_disconnect_cmd(ar->wmi); | ||
652 | return; | ||
653 | } | ||
654 | |||
655 | if (reason != DISCONNECT_CMD) | ||
656 | return; | ||
657 | |||
658 | if (!ar->auto_auth_stage) { | ||
659 | clear_bit(CONNECT_PEND, &ar->flag); | ||
660 | |||
661 | if (ar->sme_state == SME_CONNECTING) { | ||
662 | cfg80211_connect_result(ar->net_dev, | ||
663 | bssid, NULL, 0, | ||
664 | NULL, 0, | ||
665 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
666 | GFP_KERNEL); | ||
667 | } else { | ||
668 | cfg80211_disconnected(ar->net_dev, reason, | ||
669 | NULL, 0, GFP_KERNEL); | ||
670 | } | ||
671 | |||
672 | ar->sme_state = SME_DISCONNECTED; | ||
673 | return; | ||
674 | } | ||
675 | |||
676 | if (ar->dot11_auth_mode != OPEN_AUTH) | ||
677 | return; | ||
678 | |||
679 | /* | 605 | /* |
680 | * If the current auth algorithm is open, try shared and | 606 | * Send a disconnect command to target when a disconnect event is |
681 | * make autoAuthStage idle. We do not make it leap for now | 607 | * received with reason code other than 3 (DISCONNECT_CMD - disconnect |
682 | * being. | 608 | * request from host) to make the firmware stop trying to connect even |
609 | * after giving disconnect event. There will be one more disconnect | ||
610 | * event for this disconnect command with reason code DISCONNECT_CMD | ||
611 | * which will be notified to cfg80211. | ||
683 | */ | 612 | */ |
684 | key = &ar->keys[ar->def_txkey_index]; | ||
685 | if (down_interruptible(&ar->sem)) { | ||
686 | ath6kl_err("busy, couldn't get access\n"); | ||
687 | return; | ||
688 | } | ||
689 | |||
690 | ar->dot11_auth_mode = SHARED_AUTH; | ||
691 | ar->auto_auth_stage = AUTH_IDLE; | ||
692 | 613 | ||
693 | ath6kl_wmi_addkey_cmd(ar->wmi, | 614 | if (reason != DISCONNECT_CMD) { |
694 | ar->def_txkey_index, | 615 | ath6kl_wmi_disconnect_cmd(ar->wmi); |
695 | ar->prwise_crypto, | ||
696 | GROUP_USAGE | TX_USAGE, | ||
697 | key->key_len, NULL, | ||
698 | key->key, | ||
699 | KEY_OP_INIT_VAL, NULL, | ||
700 | NO_SYNC_WMIFLAG); | ||
701 | |||
702 | status = ath6kl_wmi_connect_cmd(ar->wmi, | ||
703 | ar->nw_type, | ||
704 | ar->dot11_auth_mode, | ||
705 | ar->auth_mode, | ||
706 | ar->prwise_crypto, | ||
707 | ar->prwise_crypto_len, | ||
708 | ar->grp_crypto, | ||
709 | ar->grp_crpto_len, | ||
710 | ar->ssid_len, | ||
711 | ar->ssid, | ||
712 | ar->req_bssid, | ||
713 | ar->ch_hint, | ||
714 | ar->connect_ctrl_flags); | ||
715 | up(&ar->sem); | ||
716 | } | ||
717 | |||
718 | static inline bool is_ch_11a(u16 ch) | ||
719 | { | ||
720 | return (!((ch >= 2412) && (ch <= 2484))); | ||
721 | } | ||
722 | |||
723 | /* struct ath6kl_node_table::nt_nodelock is locked when calling this */ | ||
724 | void ath6kl_cfg80211_scan_node(struct wiphy *wiphy, struct bss *ni) | ||
725 | { | ||
726 | u16 size; | ||
727 | unsigned char *ieeemgmtbuf = NULL; | ||
728 | struct ieee80211_mgmt *mgmt; | ||
729 | struct ieee80211_channel *channel; | ||
730 | struct ieee80211_supported_band *band; | ||
731 | struct ath6kl_common_ie *cie; | ||
732 | s32 signal; | ||
733 | int freq; | ||
734 | |||
735 | cie = &ni->ni_cie; | ||
736 | |||
737 | if (is_ch_11a(cie->ie_chan)) | ||
738 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; /* 11a */ | ||
739 | else if ((cie->ie_erp) || (cie->ie_xrates)) | ||
740 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; /* 11g */ | ||
741 | else | ||
742 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; /* 11b */ | ||
743 | |||
744 | size = ni->ni_framelen + offsetof(struct ieee80211_mgmt, u); | ||
745 | ieeemgmtbuf = kmalloc(size, GFP_ATOMIC); | ||
746 | if (!ieeemgmtbuf) { | ||
747 | ath6kl_err("ieee mgmt buf alloc error\n"); | ||
748 | return; | 616 | return; |
749 | } | 617 | } |
750 | 618 | ||
751 | /* | 619 | clear_bit(CONNECT_PEND, &ar->flag); |
752 | * TODO: Update target to include 802.11 mac header while sending | ||
753 | * bss info. Target removes 802.11 mac header while sending the bss | ||
754 | * info to host, cfg80211 needs it, for time being just filling the | ||
755 | * da, sa and bssid fields alone. | ||
756 | */ | ||
757 | mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; | ||
758 | memset(mgmt->da, 0xff, ETH_ALEN); /*broadcast addr */ | ||
759 | memcpy(mgmt->sa, ni->ni_macaddr, ETH_ALEN); | ||
760 | memcpy(mgmt->bssid, ni->ni_macaddr, ETH_ALEN); | ||
761 | memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u), | ||
762 | ni->ni_buf, ni->ni_framelen); | ||
763 | |||
764 | freq = cie->ie_chan; | ||
765 | channel = ieee80211_get_channel(wiphy, freq); | ||
766 | signal = ni->ni_snr * 100; | ||
767 | 620 | ||
768 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 621 | if (ar->sme_state == SME_CONNECTING) { |
769 | "%s: bssid %pM ch %d freq %d size %d\n", __func__, | 622 | cfg80211_connect_result(ar->net_dev, |
770 | mgmt->bssid, channel->hw_value, freq, size); | 623 | bssid, NULL, 0, |
771 | cfg80211_inform_bss_frame(wiphy, channel, mgmt, | 624 | NULL, 0, |
772 | size, signal, GFP_ATOMIC); | 625 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
626 | GFP_KERNEL); | ||
627 | } else if (ar->sme_state == SME_CONNECTED) { | ||
628 | cfg80211_disconnected(ar->net_dev, reason, | ||
629 | NULL, 0, GFP_KERNEL); | ||
630 | } | ||
773 | 631 | ||
774 | kfree(ieeemgmtbuf); | 632 | ar->sme_state = SME_DISCONNECTED; |
775 | } | 633 | } |
776 | 634 | ||
777 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | 635 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, |
778 | struct cfg80211_scan_request *request) | 636 | struct cfg80211_scan_request *request) |
779 | { | 637 | { |
780 | struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); | 638 | struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); |
639 | s8 n_channels = 0; | ||
640 | u16 *channels = NULL; | ||
781 | int ret = 0; | 641 | int ret = 0; |
782 | 642 | ||
783 | if (!ath6kl_cfg80211_ready(ar)) | 643 | if (!ath6kl_cfg80211_ready(ar)) |
784 | return -EIO; | 644 | return -EIO; |
785 | 645 | ||
786 | if (!ar->usr_bss_filter) { | 646 | if (!ar->usr_bss_filter) { |
787 | if (ath6kl_wmi_bssfilter_cmd(ar->wmi, | 647 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); |
788 | (test_bit(CONNECTED, &ar->flag) ? | 648 | ret = ath6kl_wmi_bssfilter_cmd( |
789 | ALL_BUT_BSS_FILTER : | 649 | ar->wmi, |
790 | ALL_BSS_FILTER), 0) != 0) { | 650 | (test_bit(CONNECTED, &ar->flag) ? |
651 | ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0); | ||
652 | if (ret) { | ||
791 | ath6kl_err("couldn't set bss filtering\n"); | 653 | ath6kl_err("couldn't set bss filtering\n"); |
792 | return -EIO; | 654 | return ret; |
793 | } | 655 | } |
794 | } | 656 | } |
795 | 657 | ||
@@ -806,13 +668,46 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
806 | request->ssids[i].ssid); | 668 | request->ssids[i].ssid); |
807 | } | 669 | } |
808 | 670 | ||
809 | if (ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, 0, | 671 | if (request->ie) { |
810 | false, 0, 0, 0, NULL) != 0) { | 672 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_REQ, |
811 | ath6kl_err("wmi_startscan_cmd failed\n"); | 673 | request->ie, request->ie_len); |
812 | ret = -EIO; | 674 | if (ret) { |
675 | ath6kl_err("failed to set Probe Request appie for " | ||
676 | "scan"); | ||
677 | return ret; | ||
678 | } | ||
813 | } | 679 | } |
814 | 680 | ||
815 | ar->scan_req = request; | 681 | /* |
682 | * Scan only the requested channels if the request specifies a set of | ||
683 | * channels. If the list is longer than the target supports, do not | ||
684 | * configure the list and instead, scan all available channels. | ||
685 | */ | ||
686 | if (request->n_channels > 0 && | ||
687 | request->n_channels <= WMI_MAX_CHANNELS) { | ||
688 | u8 i; | ||
689 | |||
690 | n_channels = request->n_channels; | ||
691 | |||
692 | channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL); | ||
693 | if (channels == NULL) { | ||
694 | ath6kl_warn("failed to set scan channels, " | ||
695 | "scan all channels"); | ||
696 | n_channels = 0; | ||
697 | } | ||
698 | |||
699 | for (i = 0; i < n_channels; i++) | ||
700 | channels[i] = request->channels[i]->center_freq; | ||
701 | } | ||
702 | |||
703 | ret = ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, 0, | ||
704 | false, 0, 0, n_channels, channels); | ||
705 | if (ret) | ||
706 | ath6kl_err("wmi_startscan_cmd failed\n"); | ||
707 | else | ||
708 | ar->scan_req = request; | ||
709 | |||
710 | kfree(channels); | ||
816 | 711 | ||
817 | return ret; | 712 | return ret; |
818 | } | 713 | } |
@@ -831,9 +726,6 @@ void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status) | |||
831 | goto out; | 726 | goto out; |
832 | } | 727 | } |
833 | 728 | ||
834 | /* Translate data to cfg80211 mgmt format */ | ||
835 | wlan_iterate_nodes(&ar->scan_table, ar->wdev->wiphy); | ||
836 | |||
837 | cfg80211_scan_done(ar->scan_req, false); | 729 | cfg80211_scan_done(ar->scan_req, false); |
838 | 730 | ||
839 | if (ar->scan_req->n_ssids && ar->scan_req->ssids[0].ssid_len) { | 731 | if (ar->scan_req->n_ssids && ar->scan_req->ssids[0].ssid_len) { |
@@ -918,6 +810,40 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
918 | key_usage, key->seq_len); | 810 | key_usage, key->seq_len); |
919 | 811 | ||
920 | ar->def_txkey_index = key_index; | 812 | ar->def_txkey_index = key_index; |
813 | |||
814 | if (ar->nw_type == AP_NETWORK && !pairwise && | ||
815 | (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) { | ||
816 | ar->ap_mode_bkey.valid = true; | ||
817 | ar->ap_mode_bkey.key_index = key_index; | ||
818 | ar->ap_mode_bkey.key_type = key_type; | ||
819 | ar->ap_mode_bkey.key_len = key->key_len; | ||
820 | memcpy(ar->ap_mode_bkey.key, key->key, key->key_len); | ||
821 | if (!test_bit(CONNECTED, &ar->flag)) { | ||
822 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group " | ||
823 | "key configuration until AP mode has been " | ||
824 | "started\n"); | ||
825 | /* | ||
826 | * The key will be set in ath6kl_connect_ap_mode() once | ||
827 | * the connected event is received from the target. | ||
828 | */ | ||
829 | return 0; | ||
830 | } | ||
831 | } | ||
832 | |||
833 | if (ar->next_mode == AP_NETWORK && key_type == WEP_CRYPT && | ||
834 | !test_bit(CONNECTED, &ar->flag)) { | ||
835 | /* | ||
836 | * Store the key locally so that it can be re-configured after | ||
837 | * the AP mode has properly started | ||
838 | * (ath6kl_install_statioc_wep_keys). | ||
839 | */ | ||
840 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration " | ||
841 | "until AP mode has been started\n"); | ||
842 | ar->wep_key_list[key_index].key_len = key->key_len; | ||
843 | memcpy(ar->wep_key_list[key_index].key, key->key, key->key_len); | ||
844 | return 0; | ||
845 | } | ||
846 | |||
921 | status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, | 847 | status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, |
922 | key_type, key_usage, key->key_len, | 848 | key_type, key_usage, key->key_len, |
923 | key->seq, key->key, KEY_OP_INIT_VAL, | 849 | key->seq, key->key, KEY_OP_INIT_VAL, |
@@ -1002,6 +928,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, | |||
1002 | struct ath6kl_key *key = NULL; | 928 | struct ath6kl_key *key = NULL; |
1003 | int status = 0; | 929 | int status = 0; |
1004 | u8 key_usage; | 930 | u8 key_usage; |
931 | enum crypto_type key_type = NONE_CRYPT; | ||
1005 | 932 | ||
1006 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); | 933 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); |
1007 | 934 | ||
@@ -1026,9 +953,16 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, | |||
1026 | key_usage = GROUP_USAGE; | 953 | key_usage = GROUP_USAGE; |
1027 | if (ar->prwise_crypto == WEP_CRYPT) | 954 | if (ar->prwise_crypto == WEP_CRYPT) |
1028 | key_usage |= TX_USAGE; | 955 | key_usage |= TX_USAGE; |
956 | if (unicast) | ||
957 | key_type = ar->prwise_crypto; | ||
958 | if (multicast) | ||
959 | key_type = ar->grp_crypto; | ||
960 | |||
961 | if (ar->next_mode == AP_NETWORK && !test_bit(CONNECTED, &ar->flag)) | ||
962 | return 0; /* Delay until AP mode has been started */ | ||
1029 | 963 | ||
1030 | status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, | 964 | status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, |
1031 | ar->prwise_crypto, key_usage, | 965 | key_type, key_usage, |
1032 | key->key_len, key->seq, key->key, | 966 | key->key_len, key->seq, key->key, |
1033 | KEY_OP_INIT_VAL, NULL, | 967 | KEY_OP_INIT_VAL, NULL, |
1034 | SYNC_BOTH_WMIFLAG); | 968 | SYNC_BOTH_WMIFLAG); |
@@ -1183,6 +1117,15 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, | |||
1183 | case NL80211_IFTYPE_ADHOC: | 1117 | case NL80211_IFTYPE_ADHOC: |
1184 | ar->next_mode = ADHOC_NETWORK; | 1118 | ar->next_mode = ADHOC_NETWORK; |
1185 | break; | 1119 | break; |
1120 | case NL80211_IFTYPE_AP: | ||
1121 | ar->next_mode = AP_NETWORK; | ||
1122 | break; | ||
1123 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1124 | ar->next_mode = INFRA_NETWORK; | ||
1125 | break; | ||
1126 | case NL80211_IFTYPE_P2P_GO: | ||
1127 | ar->next_mode = AP_NETWORK; | ||
1128 | break; | ||
1186 | default: | 1129 | default: |
1187 | ath6kl_err("invalid interface type %u\n", type); | 1130 | ath6kl_err("invalid interface type %u\n", type); |
1188 | return -EOPNOTSUPP; | 1131 | return -EOPNOTSUPP; |
@@ -1246,13 +1189,13 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy, | |||
1246 | __func__, | 1189 | __func__, |
1247 | ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto, | 1190 | ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto, |
1248 | ar->prwise_crypto_len, ar->grp_crypto, | 1191 | ar->prwise_crypto_len, ar->grp_crypto, |
1249 | ar->grp_crpto_len, ar->ch_hint); | 1192 | ar->grp_crypto_len, ar->ch_hint); |
1250 | 1193 | ||
1251 | status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type, | 1194 | status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type, |
1252 | ar->dot11_auth_mode, ar->auth_mode, | 1195 | ar->dot11_auth_mode, ar->auth_mode, |
1253 | ar->prwise_crypto, | 1196 | ar->prwise_crypto, |
1254 | ar->prwise_crypto_len, | 1197 | ar->prwise_crypto_len, |
1255 | ar->grp_crypto, ar->grp_crpto_len, | 1198 | ar->grp_crypto, ar->grp_crypto_len, |
1256 | ar->ssid_len, ar->ssid, | 1199 | ar->ssid_len, ar->ssid, |
1257 | ar->req_bssid, ar->ch_hint, | 1200 | ar->req_bssid, ar->ch_hint, |
1258 | ar->connect_ctrl_flags); | 1201 | ar->connect_ctrl_flags); |
@@ -1422,12 +1365,23 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
1422 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 1365 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
1423 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | 1366 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; |
1424 | } else { | 1367 | } else { |
1425 | ath6kl_warn("invalid rate: %d\n", rate); | 1368 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1369 | "invalid rate from stats: %d\n", rate); | ||
1370 | ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE); | ||
1426 | return 0; | 1371 | return 0; |
1427 | } | 1372 | } |
1428 | 1373 | ||
1429 | sinfo->filled |= STATION_INFO_TX_BITRATE; | 1374 | sinfo->filled |= STATION_INFO_TX_BITRATE; |
1430 | 1375 | ||
1376 | if (test_bit(CONNECTED, &ar->flag) && | ||
1377 | test_bit(DTIM_PERIOD_AVAIL, &ar->flag) && | ||
1378 | ar->nw_type == INFRA_NETWORK) { | ||
1379 | sinfo->filled |= STATION_INFO_BSS_PARAM; | ||
1380 | sinfo->bss_param.flags = 0; | ||
1381 | sinfo->bss_param.dtim_period = ar->assoc_bss_dtim_period; | ||
1382 | sinfo->bss_param.beacon_interval = ar->assoc_bss_beacon_int; | ||
1383 | } | ||
1384 | |||
1431 | return 0; | 1385 | return 0; |
1432 | } | 1386 | } |
1433 | 1387 | ||
@@ -1455,6 +1409,402 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) | |||
1455 | return 0; | 1409 | return 0; |
1456 | } | 1410 | } |
1457 | 1411 | ||
1412 | #ifdef CONFIG_PM | ||
1413 | static int ar6k_cfg80211_suspend(struct wiphy *wiphy, | ||
1414 | struct cfg80211_wowlan *wow) | ||
1415 | { | ||
1416 | struct ath6kl *ar = wiphy_priv(wiphy); | ||
1417 | |||
1418 | return ath6kl_hif_suspend(ar); | ||
1419 | } | ||
1420 | #endif | ||
1421 | |||
1422 | static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, | ||
1423 | struct ieee80211_channel *chan, | ||
1424 | enum nl80211_channel_type channel_type) | ||
1425 | { | ||
1426 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1427 | |||
1428 | if (!ath6kl_cfg80211_ready(ar)) | ||
1429 | return -EIO; | ||
1430 | |||
1431 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", | ||
1432 | __func__, chan->center_freq, chan->hw_value); | ||
1433 | ar->next_chan = chan->center_freq; | ||
1434 | |||
1435 | return 0; | ||
1436 | } | ||
1437 | |||
1438 | static bool ath6kl_is_p2p_ie(const u8 *pos) | ||
1439 | { | ||
1440 | return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && | ||
1441 | pos[2] == 0x50 && pos[3] == 0x6f && | ||
1442 | pos[4] == 0x9a && pos[5] == 0x09; | ||
1443 | } | ||
1444 | |||
1445 | static int ath6kl_set_ap_probe_resp_ies(struct ath6kl *ar, const u8 *ies, | ||
1446 | size_t ies_len) | ||
1447 | { | ||
1448 | const u8 *pos; | ||
1449 | u8 *buf = NULL; | ||
1450 | size_t len = 0; | ||
1451 | int ret; | ||
1452 | |||
1453 | /* | ||
1454 | * Filter out P2P IE(s) since they will be included depending on | ||
1455 | * the Probe Request frame in ath6kl_send_go_probe_resp(). | ||
1456 | */ | ||
1457 | |||
1458 | if (ies && ies_len) { | ||
1459 | buf = kmalloc(ies_len, GFP_KERNEL); | ||
1460 | if (buf == NULL) | ||
1461 | return -ENOMEM; | ||
1462 | pos = ies; | ||
1463 | while (pos + 1 < ies + ies_len) { | ||
1464 | if (pos + 2 + pos[1] > ies + ies_len) | ||
1465 | break; | ||
1466 | if (!ath6kl_is_p2p_ie(pos)) { | ||
1467 | memcpy(buf + len, pos, 2 + pos[1]); | ||
1468 | len += 2 + pos[1]; | ||
1469 | } | ||
1470 | pos += 2 + pos[1]; | ||
1471 | } | ||
1472 | } | ||
1473 | |||
1474 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_RESP, | ||
1475 | buf, len); | ||
1476 | kfree(buf); | ||
1477 | return ret; | ||
1478 | } | ||
1479 | |||
1480 | static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, | ||
1481 | struct beacon_parameters *info, bool add) | ||
1482 | { | ||
1483 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1484 | struct ieee80211_mgmt *mgmt; | ||
1485 | u8 *ies; | ||
1486 | int ies_len; | ||
1487 | struct wmi_connect_cmd p; | ||
1488 | int res; | ||
1489 | int i; | ||
1490 | |||
1491 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add); | ||
1492 | |||
1493 | if (!ath6kl_cfg80211_ready(ar)) | ||
1494 | return -EIO; | ||
1495 | |||
1496 | if (ar->next_mode != AP_NETWORK) | ||
1497 | return -EOPNOTSUPP; | ||
1498 | |||
1499 | if (info->beacon_ies) { | ||
1500 | res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_BEACON, | ||
1501 | info->beacon_ies, | ||
1502 | info->beacon_ies_len); | ||
1503 | if (res) | ||
1504 | return res; | ||
1505 | } | ||
1506 | if (info->proberesp_ies) { | ||
1507 | res = ath6kl_set_ap_probe_resp_ies(ar, info->proberesp_ies, | ||
1508 | info->proberesp_ies_len); | ||
1509 | if (res) | ||
1510 | return res; | ||
1511 | } | ||
1512 | if (info->assocresp_ies) { | ||
1513 | res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_ASSOC_RESP, | ||
1514 | info->assocresp_ies, | ||
1515 | info->assocresp_ies_len); | ||
1516 | if (res) | ||
1517 | return res; | ||
1518 | } | ||
1519 | |||
1520 | if (!add) | ||
1521 | return 0; | ||
1522 | |||
1523 | ar->ap_mode_bkey.valid = false; | ||
1524 | |||
1525 | /* TODO: | ||
1526 | * info->interval | ||
1527 | * info->dtim_period | ||
1528 | */ | ||
1529 | |||
1530 | if (info->head == NULL) | ||
1531 | return -EINVAL; | ||
1532 | mgmt = (struct ieee80211_mgmt *) info->head; | ||
1533 | ies = mgmt->u.beacon.variable; | ||
1534 | if (ies > info->head + info->head_len) | ||
1535 | return -EINVAL; | ||
1536 | ies_len = info->head + info->head_len - ies; | ||
1537 | |||
1538 | if (info->ssid == NULL) | ||
1539 | return -EINVAL; | ||
1540 | memcpy(ar->ssid, info->ssid, info->ssid_len); | ||
1541 | ar->ssid_len = info->ssid_len; | ||
1542 | if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) | ||
1543 | return -EOPNOTSUPP; /* TODO */ | ||
1544 | |||
1545 | ar->dot11_auth_mode = OPEN_AUTH; | ||
1546 | |||
1547 | memset(&p, 0, sizeof(p)); | ||
1548 | |||
1549 | for (i = 0; i < info->crypto.n_akm_suites; i++) { | ||
1550 | switch (info->crypto.akm_suites[i]) { | ||
1551 | case WLAN_AKM_SUITE_8021X: | ||
1552 | if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1) | ||
1553 | p.auth_mode |= WPA_AUTH; | ||
1554 | if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2) | ||
1555 | p.auth_mode |= WPA2_AUTH; | ||
1556 | break; | ||
1557 | case WLAN_AKM_SUITE_PSK: | ||
1558 | if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1) | ||
1559 | p.auth_mode |= WPA_PSK_AUTH; | ||
1560 | if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2) | ||
1561 | p.auth_mode |= WPA2_PSK_AUTH; | ||
1562 | break; | ||
1563 | } | ||
1564 | } | ||
1565 | if (p.auth_mode == 0) | ||
1566 | p.auth_mode = NONE_AUTH; | ||
1567 | ar->auth_mode = p.auth_mode; | ||
1568 | |||
1569 | for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) { | ||
1570 | switch (info->crypto.ciphers_pairwise[i]) { | ||
1571 | case WLAN_CIPHER_SUITE_WEP40: | ||
1572 | case WLAN_CIPHER_SUITE_WEP104: | ||
1573 | p.prwise_crypto_type |= WEP_CRYPT; | ||
1574 | break; | ||
1575 | case WLAN_CIPHER_SUITE_TKIP: | ||
1576 | p.prwise_crypto_type |= TKIP_CRYPT; | ||
1577 | break; | ||
1578 | case WLAN_CIPHER_SUITE_CCMP: | ||
1579 | p.prwise_crypto_type |= AES_CRYPT; | ||
1580 | break; | ||
1581 | } | ||
1582 | } | ||
1583 | if (p.prwise_crypto_type == 0) { | ||
1584 | p.prwise_crypto_type = NONE_CRYPT; | ||
1585 | ath6kl_set_cipher(ar, 0, true); | ||
1586 | } else if (info->crypto.n_ciphers_pairwise == 1) | ||
1587 | ath6kl_set_cipher(ar, info->crypto.ciphers_pairwise[0], true); | ||
1588 | |||
1589 | switch (info->crypto.cipher_group) { | ||
1590 | case WLAN_CIPHER_SUITE_WEP40: | ||
1591 | case WLAN_CIPHER_SUITE_WEP104: | ||
1592 | p.grp_crypto_type = WEP_CRYPT; | ||
1593 | break; | ||
1594 | case WLAN_CIPHER_SUITE_TKIP: | ||
1595 | p.grp_crypto_type = TKIP_CRYPT; | ||
1596 | break; | ||
1597 | case WLAN_CIPHER_SUITE_CCMP: | ||
1598 | p.grp_crypto_type = AES_CRYPT; | ||
1599 | break; | ||
1600 | default: | ||
1601 | p.grp_crypto_type = NONE_CRYPT; | ||
1602 | break; | ||
1603 | } | ||
1604 | ath6kl_set_cipher(ar, info->crypto.cipher_group, false); | ||
1605 | |||
1606 | p.nw_type = AP_NETWORK; | ||
1607 | ar->nw_type = ar->next_mode; | ||
1608 | |||
1609 | p.ssid_len = ar->ssid_len; | ||
1610 | memcpy(p.ssid, ar->ssid, ar->ssid_len); | ||
1611 | p.dot11_auth_mode = ar->dot11_auth_mode; | ||
1612 | p.ch = cpu_to_le16(ar->next_chan); | ||
1613 | |||
1614 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, &p); | ||
1615 | if (res < 0) | ||
1616 | return res; | ||
1617 | |||
1618 | return 0; | ||
1619 | } | ||
1620 | |||
1621 | static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev, | ||
1622 | struct beacon_parameters *info) | ||
1623 | { | ||
1624 | return ath6kl_ap_beacon(wiphy, dev, info, true); | ||
1625 | } | ||
1626 | |||
1627 | static int ath6kl_set_beacon(struct wiphy *wiphy, struct net_device *dev, | ||
1628 | struct beacon_parameters *info) | ||
1629 | { | ||
1630 | return ath6kl_ap_beacon(wiphy, dev, info, false); | ||
1631 | } | ||
1632 | |||
1633 | static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev) | ||
1634 | { | ||
1635 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1636 | |||
1637 | if (ar->nw_type != AP_NETWORK) | ||
1638 | return -EOPNOTSUPP; | ||
1639 | if (!test_bit(CONNECTED, &ar->flag)) | ||
1640 | return -ENOTCONN; | ||
1641 | |||
1642 | ath6kl_wmi_disconnect_cmd(ar->wmi); | ||
1643 | clear_bit(CONNECTED, &ar->flag); | ||
1644 | |||
1645 | return 0; | ||
1646 | } | ||
1647 | |||
1648 | static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, | ||
1649 | u8 *mac, struct station_parameters *params) | ||
1650 | { | ||
1651 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1652 | |||
1653 | if (ar->nw_type != AP_NETWORK) | ||
1654 | return -EOPNOTSUPP; | ||
1655 | |||
1656 | /* Use this only for authorizing/unauthorizing a station */ | ||
1657 | if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) | ||
1658 | return -EOPNOTSUPP; | ||
1659 | |||
1660 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
1661 | return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_AUTHORIZE, | ||
1662 | mac, 0); | ||
1663 | return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_UNAUTHORIZE, mac, | ||
1664 | 0); | ||
1665 | } | ||
1666 | |||
1667 | static int ath6kl_remain_on_channel(struct wiphy *wiphy, | ||
1668 | struct net_device *dev, | ||
1669 | struct ieee80211_channel *chan, | ||
1670 | enum nl80211_channel_type channel_type, | ||
1671 | unsigned int duration, | ||
1672 | u64 *cookie) | ||
1673 | { | ||
1674 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1675 | |||
1676 | /* TODO: if already pending or ongoing remain-on-channel, | ||
1677 | * return -EBUSY */ | ||
1678 | *cookie = 1; /* only a single pending request is supported */ | ||
1679 | |||
1680 | return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, chan->center_freq, | ||
1681 | duration); | ||
1682 | } | ||
1683 | |||
1684 | static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy, | ||
1685 | struct net_device *dev, | ||
1686 | u64 cookie) | ||
1687 | { | ||
1688 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1689 | |||
1690 | if (cookie != 1) | ||
1691 | return -ENOENT; | ||
1692 | |||
1693 | return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi); | ||
1694 | } | ||
1695 | |||
1696 | static int ath6kl_send_go_probe_resp(struct ath6kl *ar, const u8 *buf, | ||
1697 | size_t len, unsigned int freq) | ||
1698 | { | ||
1699 | const u8 *pos; | ||
1700 | u8 *p2p; | ||
1701 | int p2p_len; | ||
1702 | int ret; | ||
1703 | const struct ieee80211_mgmt *mgmt; | ||
1704 | |||
1705 | mgmt = (const struct ieee80211_mgmt *) buf; | ||
1706 | |||
1707 | /* Include P2P IE(s) from the frame generated in user space. */ | ||
1708 | |||
1709 | p2p = kmalloc(len, GFP_KERNEL); | ||
1710 | if (p2p == NULL) | ||
1711 | return -ENOMEM; | ||
1712 | p2p_len = 0; | ||
1713 | |||
1714 | pos = mgmt->u.probe_resp.variable; | ||
1715 | while (pos + 1 < buf + len) { | ||
1716 | if (pos + 2 + pos[1] > buf + len) | ||
1717 | break; | ||
1718 | if (ath6kl_is_p2p_ie(pos)) { | ||
1719 | memcpy(p2p + p2p_len, pos, 2 + pos[1]); | ||
1720 | p2p_len += 2 + pos[1]; | ||
1721 | } | ||
1722 | pos += 2 + pos[1]; | ||
1723 | } | ||
1724 | |||
1725 | ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, freq, mgmt->da, | ||
1726 | p2p, p2p_len); | ||
1727 | kfree(p2p); | ||
1728 | return ret; | ||
1729 | } | ||
1730 | |||
1731 | static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | ||
1732 | struct ieee80211_channel *chan, bool offchan, | ||
1733 | enum nl80211_channel_type channel_type, | ||
1734 | bool channel_type_valid, unsigned int wait, | ||
1735 | const u8 *buf, size_t len, bool no_cck, u64 *cookie) | ||
1736 | { | ||
1737 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1738 | u32 id; | ||
1739 | const struct ieee80211_mgmt *mgmt; | ||
1740 | |||
1741 | mgmt = (const struct ieee80211_mgmt *) buf; | ||
1742 | if (buf + len >= mgmt->u.probe_resp.variable && | ||
1743 | ar->nw_type == AP_NETWORK && test_bit(CONNECTED, &ar->flag) && | ||
1744 | ieee80211_is_probe_resp(mgmt->frame_control)) { | ||
1745 | /* | ||
1746 | * Send Probe Response frame in AP mode using a separate WMI | ||
1747 | * command to allow the target to fill in the generic IEs. | ||
1748 | */ | ||
1749 | *cookie = 0; /* TX status not supported */ | ||
1750 | return ath6kl_send_go_probe_resp(ar, buf, len, | ||
1751 | chan->center_freq); | ||
1752 | } | ||
1753 | |||
1754 | id = ar->send_action_id++; | ||
1755 | if (id == 0) { | ||
1756 | /* | ||
1757 | * 0 is a reserved value in the WMI command and shall not be | ||
1758 | * used for the command. | ||
1759 | */ | ||
1760 | id = ar->send_action_id++; | ||
1761 | } | ||
1762 | |||
1763 | *cookie = id; | ||
1764 | return ath6kl_wmi_send_action_cmd(ar->wmi, id, chan->center_freq, wait, | ||
1765 | buf, len); | ||
1766 | } | ||
1767 | |||
1768 | static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, | ||
1769 | struct net_device *dev, | ||
1770 | u16 frame_type, bool reg) | ||
1771 | { | ||
1772 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1773 | |||
1774 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n", | ||
1775 | __func__, frame_type, reg); | ||
1776 | if (frame_type == IEEE80211_STYPE_PROBE_REQ) { | ||
1777 | /* | ||
1778 | * Note: This notification callback is not allowed to sleep, so | ||
1779 | * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we | ||
1780 | * hardcode target to report Probe Request frames all the time. | ||
1781 | */ | ||
1782 | ar->probe_req_report = reg; | ||
1783 | } | ||
1784 | } | ||
1785 | |||
1786 | static const struct ieee80211_txrx_stypes | ||
1787 | ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { | ||
1788 | [NL80211_IFTYPE_STATION] = { | ||
1789 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
1790 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
1791 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
1792 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
1793 | }, | ||
1794 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
1795 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
1796 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
1797 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
1798 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
1799 | }, | ||
1800 | [NL80211_IFTYPE_P2P_GO] = { | ||
1801 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
1802 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
1803 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
1804 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
1805 | }, | ||
1806 | }; | ||
1807 | |||
1458 | static struct cfg80211_ops ath6kl_cfg80211_ops = { | 1808 | static struct cfg80211_ops ath6kl_cfg80211_ops = { |
1459 | .change_virtual_intf = ath6kl_cfg80211_change_iface, | 1809 | .change_virtual_intf = ath6kl_cfg80211_change_iface, |
1460 | .scan = ath6kl_cfg80211_scan, | 1810 | .scan = ath6kl_cfg80211_scan, |
@@ -1474,12 +1824,26 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { | |||
1474 | .set_pmksa = ath6kl_set_pmksa, | 1824 | .set_pmksa = ath6kl_set_pmksa, |
1475 | .del_pmksa = ath6kl_del_pmksa, | 1825 | .del_pmksa = ath6kl_del_pmksa, |
1476 | .flush_pmksa = ath6kl_flush_pmksa, | 1826 | .flush_pmksa = ath6kl_flush_pmksa, |
1827 | CFG80211_TESTMODE_CMD(ath6kl_tm_cmd) | ||
1828 | #ifdef CONFIG_PM | ||
1829 | .suspend = ar6k_cfg80211_suspend, | ||
1830 | #endif | ||
1831 | .set_channel = ath6kl_set_channel, | ||
1832 | .add_beacon = ath6kl_add_beacon, | ||
1833 | .set_beacon = ath6kl_set_beacon, | ||
1834 | .del_beacon = ath6kl_del_beacon, | ||
1835 | .change_station = ath6kl_change_station, | ||
1836 | .remain_on_channel = ath6kl_remain_on_channel, | ||
1837 | .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, | ||
1838 | .mgmt_tx = ath6kl_mgmt_tx, | ||
1839 | .mgmt_frame_register = ath6kl_mgmt_frame_register, | ||
1477 | }; | 1840 | }; |
1478 | 1841 | ||
1479 | struct wireless_dev *ath6kl_cfg80211_init(struct device *dev) | 1842 | struct wireless_dev *ath6kl_cfg80211_init(struct device *dev) |
1480 | { | 1843 | { |
1481 | int ret = 0; | 1844 | int ret = 0; |
1482 | struct wireless_dev *wdev; | 1845 | struct wireless_dev *wdev; |
1846 | struct ath6kl *ar; | ||
1483 | 1847 | ||
1484 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 1848 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); |
1485 | if (!wdev) { | 1849 | if (!wdev) { |
@@ -1495,13 +1859,25 @@ struct wireless_dev *ath6kl_cfg80211_init(struct device *dev) | |||
1495 | return NULL; | 1859 | return NULL; |
1496 | } | 1860 | } |
1497 | 1861 | ||
1862 | ar = wiphy_priv(wdev->wiphy); | ||
1863 | ar->p2p = !!ath6kl_p2p; | ||
1864 | |||
1865 | wdev->wiphy->mgmt_stypes = ath6kl_mgmt_stypes; | ||
1866 | |||
1867 | wdev->wiphy->max_remain_on_channel_duration = 5000; | ||
1868 | |||
1498 | /* set device pointer for wiphy */ | 1869 | /* set device pointer for wiphy */ |
1499 | set_wiphy_dev(wdev->wiphy, dev); | 1870 | set_wiphy_dev(wdev->wiphy, dev); |
1500 | 1871 | ||
1501 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1872 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1502 | BIT(NL80211_IFTYPE_ADHOC); | 1873 | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); |
1874 | if (ar->p2p) { | ||
1875 | wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) | | ||
1876 | BIT(NL80211_IFTYPE_P2P_CLIENT); | ||
1877 | } | ||
1503 | /* max num of ssids that can be probed during scanning */ | 1878 | /* max num of ssids that can be probed during scanning */ |
1504 | wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; | 1879 | wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; |
1880 | wdev->wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ | ||
1505 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | 1881 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; |
1506 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; | 1882 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; |
1507 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 1883 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index 6b0d45642fe3..b92f0e5d2336 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h | |||
@@ -75,94 +75,11 @@ enum crypto_type { | |||
75 | AES_CRYPT = 0x08, | 75 | AES_CRYPT = 0x08, |
76 | }; | 76 | }; |
77 | 77 | ||
78 | #define ATH6KL_NODE_HASHSIZE 32 | ||
79 | /* simple hash is enough for variation of macaddr */ | ||
80 | #define ATH6KL_NODE_HASH(addr) \ | ||
81 | (((const u8 *)(addr))[ETH_ALEN - 1] % \ | ||
82 | ATH6KL_NODE_HASHSIZE) | ||
83 | |||
84 | /* | ||
85 | * Table of ath6kl_node instances. Each ieee80211com | ||
86 | * has at least one for holding the scan candidates. | ||
87 | * When operating as an access point or in ibss mode there | ||
88 | * is a second table for associated stations or neighbors. | ||
89 | */ | ||
90 | struct ath6kl_node_table { | ||
91 | spinlock_t nt_nodelock; /* on node table */ | ||
92 | struct bss *nt_node_first; /* information of all nodes */ | ||
93 | struct bss *nt_node_last; /* information of all nodes */ | ||
94 | struct bss *nt_hash[ATH6KL_NODE_HASHSIZE]; | ||
95 | const char *nt_name; /* for debugging */ | ||
96 | u32 nt_node_age; /* node aging time */ | ||
97 | }; | ||
98 | |||
99 | #define WLAN_NODE_INACT_TIMEOUT_MSEC 120000 | ||
100 | #define WLAN_NODE_INACT_CNT 4 | ||
101 | |||
102 | struct ath6kl_common_ie { | ||
103 | u16 ie_chan; | ||
104 | u8 *ie_tstamp; | ||
105 | u8 *ie_ssid; | ||
106 | u8 *ie_rates; | ||
107 | u8 *ie_xrates; | ||
108 | u8 *ie_country; | ||
109 | u8 *ie_wpa; | ||
110 | u8 *ie_rsn; | ||
111 | u8 *ie_wmm; | ||
112 | u8 *ie_ath; | ||
113 | u16 ie_capInfo; | ||
114 | u16 ie_beaconInt; | ||
115 | u8 *ie_tim; | ||
116 | u8 *ie_chswitch; | ||
117 | u8 ie_erp; | ||
118 | u8 *ie_wsc; | ||
119 | u8 *ie_htcap; | ||
120 | u8 *ie_htop; | ||
121 | }; | ||
122 | |||
123 | struct bss { | ||
124 | u8 ni_macaddr[ETH_ALEN]; | ||
125 | u8 ni_snr; | ||
126 | s16 ni_rssi; | ||
127 | struct bss *ni_list_next; | ||
128 | struct bss *ni_list_prev; | ||
129 | struct bss *ni_hash_next; | ||
130 | struct bss *ni_hash_prev; | ||
131 | struct ath6kl_common_ie ni_cie; | ||
132 | u8 *ni_buf; | ||
133 | u16 ni_framelen; | ||
134 | struct ath6kl_node_table *ni_table; | ||
135 | u32 ni_refcnt; | ||
136 | |||
137 | u32 ni_tstamp; | ||
138 | u32 ni_actcnt; | ||
139 | }; | ||
140 | |||
141 | struct htc_endpoint_credit_dist; | 78 | struct htc_endpoint_credit_dist; |
142 | struct ath6kl; | 79 | struct ath6kl; |
143 | enum htc_credit_dist_reason; | 80 | enum htc_credit_dist_reason; |
144 | struct htc_credit_state_info; | 81 | struct htc_credit_state_info; |
145 | 82 | ||
146 | struct bss *wlan_node_alloc(int wh_size); | ||
147 | void wlan_node_free(struct bss *ni); | ||
148 | void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni, | ||
149 | const u8 *mac_addr); | ||
150 | struct bss *wlan_find_node(struct ath6kl_node_table *nt, | ||
151 | const u8 *mac_addr); | ||
152 | void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni); | ||
153 | void wlan_free_allnodes(struct ath6kl_node_table *nt); | ||
154 | void wlan_iterate_nodes(struct ath6kl_node_table *nt, void *arg); | ||
155 | |||
156 | void wlan_node_table_init(struct ath6kl_node_table *nt); | ||
157 | void wlan_node_table_cleanup(struct ath6kl_node_table *nt); | ||
158 | |||
159 | void wlan_refresh_inactive_nodes(struct ath6kl *ar); | ||
160 | |||
161 | struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 *ssid, | ||
162 | u32 ssid_len, bool is_wpa2, bool match_ssid); | ||
163 | |||
164 | void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni); | ||
165 | |||
166 | int ath6k_setup_credit_dist(void *htc_handle, | 83 | int ath6k_setup_credit_dist(void *htc_handle, |
167 | struct htc_credit_state_info *cred_info); | 84 | struct htc_credit_state_info *cred_info); |
168 | void ath6k_credit_distribute(struct htc_credit_state_info *cred_inf, | 85 | void ath6k_credit_distribute(struct htc_credit_state_info *cred_inf, |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 74170229523f..6d8a4845baaf 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -21,10 +21,12 @@ | |||
21 | #include <linux/rtnetlink.h> | 21 | #include <linux/rtnetlink.h> |
22 | #include <linux/firmware.h> | 22 | #include <linux/firmware.h> |
23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | #include <linux/circ_buf.h> | ||
24 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
25 | #include "htc.h" | 26 | #include "htc.h" |
26 | #include "wmi.h" | 27 | #include "wmi.h" |
27 | #include "bmi.h" | 28 | #include "bmi.h" |
29 | #include "target.h" | ||
28 | 30 | ||
29 | #define MAX_ATH6KL 1 | 31 | #define MAX_ATH6KL 1 |
30 | #define ATH6KL_MAX_RX_BUFFERS 16 | 32 | #define ATH6KL_MAX_RX_BUFFERS 16 |
@@ -42,6 +44,9 @@ | |||
42 | #define ATH6KL_MAX_ENDPOINTS 4 | 44 | #define ATH6KL_MAX_ENDPOINTS 4 |
43 | #define MAX_NODE_NUM 15 | 45 | #define MAX_NODE_NUM 15 |
44 | 46 | ||
47 | /* Extra bytes for htc header alignment */ | ||
48 | #define ATH6KL_HTC_ALIGN_BYTES 3 | ||
49 | |||
45 | /* MAX_HI_COOKIE_NUM are reserved for high priority traffic */ | 50 | /* MAX_HI_COOKIE_NUM are reserved for high priority traffic */ |
46 | #define MAX_DEF_COOKIE_NUM 180 | 51 | #define MAX_DEF_COOKIE_NUM 180 |
47 | #define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */ | 52 | #define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */ |
@@ -53,6 +58,35 @@ | |||
53 | #define A_DEFAULT_LISTEN_INTERVAL 100 | 58 | #define A_DEFAULT_LISTEN_INTERVAL 100 |
54 | #define A_MAX_WOW_LISTEN_INTERVAL 1000 | 59 | #define A_MAX_WOW_LISTEN_INTERVAL 1000 |
55 | 60 | ||
61 | /* includes also the null byte */ | ||
62 | #define ATH6KL_FIRMWARE_MAGIC "QCA-ATH6KL" | ||
63 | |||
64 | enum ath6kl_fw_ie_type { | ||
65 | ATH6KL_FW_IE_FW_VERSION = 0, | ||
66 | ATH6KL_FW_IE_TIMESTAMP = 1, | ||
67 | ATH6KL_FW_IE_OTP_IMAGE = 2, | ||
68 | ATH6KL_FW_IE_FW_IMAGE = 3, | ||
69 | ATH6KL_FW_IE_PATCH_IMAGE = 4, | ||
70 | ATH6KL_FW_IE_RESERVED_RAM_SIZE = 5, | ||
71 | ATH6KL_FW_IE_CAPABILITIES = 6, | ||
72 | ATH6KL_FW_IE_PATCH_ADDR = 7, | ||
73 | }; | ||
74 | |||
75 | enum ath6kl_fw_capability { | ||
76 | ATH6KL_FW_CAPABILITY_HOST_P2P = 0, | ||
77 | |||
78 | /* this needs to be last */ | ||
79 | ATH6KL_FW_CAPABILITY_MAX, | ||
80 | }; | ||
81 | |||
82 | #define ATH6KL_CAPABILITY_LEN (ALIGN(ATH6KL_FW_CAPABILITY_MAX, 32) / 32) | ||
83 | |||
84 | struct ath6kl_fw_ie { | ||
85 | __le32 id; | ||
86 | __le32 len; | ||
87 | u8 data[0]; | ||
88 | }; | ||
89 | |||
56 | /* AR6003 1.0 definitions */ | 90 | /* AR6003 1.0 definitions */ |
57 | #define AR6003_REV1_VERSION 0x300002ba | 91 | #define AR6003_REV1_VERSION 0x300002ba |
58 | 92 | ||
@@ -61,7 +95,9 @@ | |||
61 | #define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910 | 95 | #define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910 |
62 | #define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" | 96 | #define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" |
63 | #define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" | 97 | #define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" |
98 | #define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" | ||
64 | #define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" | 99 | #define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" |
100 | #define AR6003_REV2_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin" | ||
65 | #define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" | 101 | #define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" |
66 | #define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin" | 102 | #define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin" |
67 | 103 | ||
@@ -69,11 +105,21 @@ | |||
69 | #define AR6003_REV3_VERSION 0x30000582 | 105 | #define AR6003_REV3_VERSION 0x30000582 |
70 | #define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" | 106 | #define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" |
71 | #define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" | 107 | #define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" |
108 | #define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" | ||
72 | #define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" | 109 | #define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" |
110 | #define AR6003_REV3_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin" | ||
73 | #define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" | 111 | #define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" |
74 | #define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \ | 112 | #define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \ |
75 | "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" | 113 | "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" |
76 | 114 | ||
115 | /* AR6004 1.0 definitions */ | ||
116 | #define AR6004_REV1_VERSION 0x30000623 | ||
117 | #define AR6004_REV1_FIRMWARE_FILE "ath6k/AR6004/hw6.1/fw.ram.bin" | ||
118 | #define AR6004_REV1_FIRMWARE_2_FILE "ath6k/AR6004/hw6.1/fw-2.bin" | ||
119 | #define AR6004_REV1_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.bin" | ||
120 | #define AR6004_REV1_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.DB132.bin" | ||
121 | #define AR6004_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6004/hw6.1/endpointping.bin" | ||
122 | |||
77 | /* Per STA data, used in AP mode */ | 123 | /* Per STA data, used in AP mode */ |
78 | #define STA_PS_AWAKE BIT(0) | 124 | #define STA_PS_AWAKE BIT(0) |
79 | #define STA_PS_SLEEP BIT(1) | 125 | #define STA_PS_SLEEP BIT(1) |
@@ -325,26 +371,13 @@ struct ath6kl_mbox_info { | |||
325 | #define ATH6KL_KEY_RECV 0x02 | 371 | #define ATH6KL_KEY_RECV 0x02 |
326 | #define ATH6KL_KEY_DEFAULT 0x80 /* default xmit key */ | 372 | #define ATH6KL_KEY_DEFAULT 0x80 /* default xmit key */ |
327 | 373 | ||
328 | /* | 374 | /* Initial group key for AP mode */ |
329 | * WPA/RSN get/set key request. Specify the key/cipher | ||
330 | * type and whether the key is to be used for sending and/or | ||
331 | * receiving. The key index should be set only when working | ||
332 | * with global keys (use IEEE80211_KEYIX_NONE for ``no index''). | ||
333 | * Otherwise a unicast/pairwise key is specified by the bssid | ||
334 | * (on a station) or mac address (on an ap). They key length | ||
335 | * must include any MIC key data; otherwise it should be no | ||
336 | * more than ATH6KL_KEYBUF_SIZE. | ||
337 | */ | ||
338 | struct ath6kl_req_key { | 375 | struct ath6kl_req_key { |
339 | u8 ik_type; /* key/cipher type */ | 376 | bool valid; |
340 | u8 ik_pad; | 377 | u8 key_index; |
341 | u16 ik_keyix; /* key index */ | 378 | int key_type; |
342 | u8 ik_keylen; /* key length in bytes */ | 379 | u8 key[WLAN_MAX_KEY_LEN]; |
343 | u8 ik_flags; | 380 | u8 key_len; |
344 | u8 ik_macaddr[ETH_ALEN]; | ||
345 | u64 ik_keyrsc; /* key receive sequence counter */ | ||
346 | u64 ik_keytsc; /* key transmit sequence counter */ | ||
347 | u8 ik_keydata[ATH6KL_KEYBUF_SIZE + ATH6KL_MICBUF_SIZE]; | ||
348 | }; | 381 | }; |
349 | 382 | ||
350 | /* Flag info */ | 383 | /* Flag info */ |
@@ -361,6 +394,9 @@ struct ath6kl_req_key { | |||
361 | #define NETDEV_REGISTERED 10 | 394 | #define NETDEV_REGISTERED 10 |
362 | #define SKIP_SCAN 11 | 395 | #define SKIP_SCAN 11 |
363 | #define WLAN_ENABLED 12 | 396 | #define WLAN_ENABLED 12 |
397 | #define TESTMODE 13 | ||
398 | #define CLEAR_BSSFILTER_ON_BEACON 14 | ||
399 | #define DTIM_PERIOD_AVAIL 15 | ||
364 | 400 | ||
365 | struct ath6kl { | 401 | struct ath6kl { |
366 | struct device *dev; | 402 | struct device *dev; |
@@ -383,7 +419,7 @@ struct ath6kl { | |||
383 | u8 prwise_crypto; | 419 | u8 prwise_crypto; |
384 | u8 prwise_crypto_len; | 420 | u8 prwise_crypto_len; |
385 | u8 grp_crypto; | 421 | u8 grp_crypto; |
386 | u8 grp_crpto_len; | 422 | u8 grp_crypto_len; |
387 | u8 def_txkey_index; | 423 | u8 def_txkey_index; |
388 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; | 424 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; |
389 | u8 bssid[ETH_ALEN]; | 425 | u8 bssid[ETH_ALEN]; |
@@ -392,6 +428,7 @@ struct ath6kl { | |||
392 | u16 bss_ch; | 428 | u16 bss_ch; |
393 | u16 listen_intvl_b; | 429 | u16 listen_intvl_b; |
394 | u16 listen_intvl_t; | 430 | u16 listen_intvl_t; |
431 | u8 lrssi_roam_threshold; | ||
395 | struct ath6kl_version version; | 432 | struct ath6kl_version version; |
396 | u32 target_type; | 433 | u32 target_type; |
397 | u8 tx_pwr; | 434 | u8 tx_pwr; |
@@ -432,7 +469,18 @@ struct ath6kl { | |||
432 | enum wlan_low_pwr_state wlan_pwr_state; | 469 | enum wlan_low_pwr_state wlan_pwr_state; |
433 | struct wmi_scan_params_cmd sc_params; | 470 | struct wmi_scan_params_cmd sc_params; |
434 | #define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 | 471 | #define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 |
435 | u8 auto_auth_stage; | 472 | struct { |
473 | void *rx_report; | ||
474 | size_t rx_report_len; | ||
475 | } tm; | ||
476 | |||
477 | struct { | ||
478 | u32 dataset_patch_addr; | ||
479 | u32 app_load_addr; | ||
480 | u32 app_start_override_addr; | ||
481 | u32 board_ext_data_addr; | ||
482 | u32 reserved_ram_size; | ||
483 | } hw; | ||
436 | 484 | ||
437 | u16 conf_flags; | 485 | u16 conf_flags; |
438 | wait_queue_head_t event_wq; | 486 | wait_queue_head_t event_wq; |
@@ -454,9 +502,35 @@ struct ath6kl { | |||
454 | u8 *fw_patch; | 502 | u8 *fw_patch; |
455 | size_t fw_patch_len; | 503 | size_t fw_patch_len; |
456 | 504 | ||
505 | unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN]; | ||
506 | |||
457 | struct workqueue_struct *ath6kl_wq; | 507 | struct workqueue_struct *ath6kl_wq; |
458 | 508 | ||
459 | struct ath6kl_node_table scan_table; | 509 | struct dentry *debugfs_phy; |
510 | |||
511 | u32 send_action_id; | ||
512 | bool probe_req_report; | ||
513 | u16 next_chan; | ||
514 | |||
515 | bool p2p; | ||
516 | u16 assoc_bss_beacon_int; | ||
517 | u8 assoc_bss_dtim_period; | ||
518 | |||
519 | #ifdef CONFIG_ATH6KL_DEBUG | ||
520 | struct { | ||
521 | struct circ_buf fwlog_buf; | ||
522 | spinlock_t fwlog_lock; | ||
523 | void *fwlog_tmp; | ||
524 | u32 fwlog_mask; | ||
525 | unsigned int dbgfs_diag_reg; | ||
526 | u32 diag_reg_addr_wr; | ||
527 | u32 diag_reg_val_wr; | ||
528 | |||
529 | struct { | ||
530 | unsigned int invalid_rate; | ||
531 | } war_stats; | ||
532 | } debug; | ||
533 | #endif /* CONFIG_ATH6KL_DEBUG */ | ||
460 | }; | 534 | }; |
461 | 535 | ||
462 | static inline void *ath6kl_priv(struct net_device *dev) | 536 | static inline void *ath6kl_priv(struct net_device *dev) |
@@ -474,6 +548,19 @@ static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info | |||
474 | cred_info->cur_free_credits -= credits; | 548 | cred_info->cur_free_credits -= credits; |
475 | } | 549 | } |
476 | 550 | ||
551 | static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar, | ||
552 | u32 item_offset) | ||
553 | { | ||
554 | u32 addr = 0; | ||
555 | |||
556 | if (ar->target_type == TARGET_TYPE_AR6003) | ||
557 | addr = ATH6KL_AR6003_HI_START_ADDR + item_offset; | ||
558 | else if (ar->target_type == TARGET_TYPE_AR6004) | ||
559 | addr = ATH6KL_AR6004_HI_START_ADDR + item_offset; | ||
560 | |||
561 | return addr; | ||
562 | } | ||
563 | |||
477 | void ath6kl_destroy(struct net_device *dev, unsigned int unregister); | 564 | void ath6kl_destroy(struct net_device *dev, unsigned int unregister); |
478 | int ath6kl_configure_target(struct ath6kl *ar); | 565 | int ath6kl_configure_target(struct ath6kl *ar); |
479 | void ath6kl_detect_error(unsigned long ptr); | 566 | void ath6kl_detect_error(unsigned long ptr); |
@@ -487,9 +574,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, | |||
487 | struct htc_packet *packet); | 574 | struct htc_packet *packet); |
488 | void ath6kl_stop_txrx(struct ath6kl *ar); | 575 | void ath6kl_stop_txrx(struct ath6kl *ar); |
489 | void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar); | 576 | void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar); |
490 | int ath6kl_access_datadiag(struct ath6kl *ar, u32 address, | 577 | int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value); |
491 | u8 *data, u32 length, bool read); | 578 | int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length); |
492 | int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data); | 579 | int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value); |
580 | int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length); | ||
581 | int ath6kl_read_fwlogs(struct ath6kl *ar); | ||
493 | void ath6kl_init_profile_info(struct ath6kl *ar); | 582 | void ath6kl_init_profile_info(struct ath6kl *ar); |
494 | void ath6kl_tx_data_cleanup(struct ath6kl *ar); | 583 | void ath6kl_tx_data_cleanup(struct ath6kl *ar); |
495 | void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile, | 584 | void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile, |
@@ -520,6 +609,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, | |||
520 | u16 beacon_int, enum network_type net_type, | 609 | u16 beacon_int, enum network_type net_type, |
521 | u8 beacon_ie_len, u8 assoc_req_len, | 610 | u8 beacon_ie_len, u8 assoc_req_len, |
522 | u8 assoc_resp_len, u8 *assoc_info); | 611 | u8 assoc_resp_len, u8 *assoc_info); |
612 | void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel); | ||
613 | void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr, | ||
614 | u8 keymgmt, u8 ucipher, u8 auth, | ||
615 | u8 assoc_req_len, u8 *assoc_info); | ||
523 | void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, | 616 | void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, |
524 | u8 *bssid, u8 assoc_resp_len, | 617 | u8 *bssid, u8 assoc_resp_len, |
525 | u8 *assoc_info, u16 prot_reason_status); | 618 | u8 *assoc_info, u16 prot_reason_status); |
@@ -534,11 +627,11 @@ void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid); | |||
534 | 627 | ||
535 | void ath6kl_dtimexpiry_event(struct ath6kl *ar); | 628 | void ath6kl_dtimexpiry_event(struct ath6kl *ar); |
536 | void ath6kl_disconnect(struct ath6kl *ar); | 629 | void ath6kl_disconnect(struct ath6kl *ar); |
630 | void ath6kl_deep_sleep_enable(struct ath6kl *ar); | ||
537 | void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid); | 631 | void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid); |
538 | void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, | 632 | void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, |
539 | u8 win_sz); | 633 | u8 win_sz); |
540 | void ath6kl_wakeup_event(void *dev); | 634 | void ath6kl_wakeup_event(void *dev); |
541 | void ath6kl_target_failure(struct ath6kl *ar); | 635 | void ath6kl_target_failure(struct ath6kl *ar); |
542 | 636 | ||
543 | void ath6kl_cfg80211_scan_node(struct wiphy *wiphy, struct bss *ni); | ||
544 | #endif /* CORE_H */ | 637 | #endif /* CORE_H */ |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 316136c8b903..ba3f23d71150 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -15,7 +15,26 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "core.h" | 17 | #include "core.h" |
18 | |||
19 | #include <linux/circ_buf.h> | ||
20 | #include <linux/fs.h> | ||
21 | #include <linux/vmalloc.h> | ||
22 | |||
18 | #include "debug.h" | 23 | #include "debug.h" |
24 | #include "target.h" | ||
25 | |||
26 | struct ath6kl_fwlog_slot { | ||
27 | __le32 timestamp; | ||
28 | __le32 length; | ||
29 | |||
30 | /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */ | ||
31 | u8 payload[0]; | ||
32 | }; | ||
33 | |||
34 | #define ATH6KL_FWLOG_SIZE 32768 | ||
35 | #define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \ | ||
36 | ATH6KL_FWLOG_PAYLOAD_SIZE) | ||
37 | #define ATH6KL_FWLOG_VALID_MASK 0x1ffff | ||
19 | 38 | ||
20 | int ath6kl_printk(const char *level, const char *fmt, ...) | 39 | int ath6kl_printk(const char *level, const char *fmt, ...) |
21 | { | 40 | { |
@@ -36,6 +55,27 @@ int ath6kl_printk(const char *level, const char *fmt, ...) | |||
36 | } | 55 | } |
37 | 56 | ||
38 | #ifdef CONFIG_ATH6KL_DEBUG | 57 | #ifdef CONFIG_ATH6KL_DEBUG |
58 | |||
59 | #define REG_OUTPUT_LEN_PER_LINE 25 | ||
60 | #define REGTYPE_STR_LEN 100 | ||
61 | |||
62 | struct ath6kl_diag_reg_info { | ||
63 | u32 reg_start; | ||
64 | u32 reg_end; | ||
65 | const char *reg_info; | ||
66 | }; | ||
67 | |||
68 | static const struct ath6kl_diag_reg_info diag_reg[] = { | ||
69 | { 0x20000, 0x200fc, "General DMA and Rx registers" }, | ||
70 | { 0x28000, 0x28900, "MAC PCU register & keycache" }, | ||
71 | { 0x20800, 0x20a40, "QCU" }, | ||
72 | { 0x21000, 0x212f0, "DCU" }, | ||
73 | { 0x4000, 0x42e4, "RTC" }, | ||
74 | { 0x540000, 0x540000 + (256 * 1024), "RAM" }, | ||
75 | { 0x29800, 0x2B210, "Base Band" }, | ||
76 | { 0x1C000, 0x1C748, "Analog" }, | ||
77 | }; | ||
78 | |||
39 | void ath6kl_dump_registers(struct ath6kl_device *dev, | 79 | void ath6kl_dump_registers(struct ath6kl_device *dev, |
40 | struct ath6kl_irq_proc_registers *irq_proc_reg, | 80 | struct ath6kl_irq_proc_registers *irq_proc_reg, |
41 | struct ath6kl_irq_enable_reg *irq_enable_reg) | 81 | struct ath6kl_irq_enable_reg *irq_enable_reg) |
@@ -147,4 +187,748 @@ void dump_cred_dist_stats(struct htc_target *target) | |||
147 | target->cred_dist_cntxt->cur_free_credits); | 187 | target->cred_dist_cntxt->cur_free_credits); |
148 | } | 188 | } |
149 | 189 | ||
190 | static int ath6kl_debugfs_open(struct inode *inode, struct file *file) | ||
191 | { | ||
192 | file->private_data = inode->i_private; | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) | ||
197 | { | ||
198 | switch (war) { | ||
199 | case ATH6KL_WAR_INVALID_RATE: | ||
200 | ar->debug.war_stats.invalid_rate++; | ||
201 | break; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static ssize_t read_file_war_stats(struct file *file, char __user *user_buf, | ||
206 | size_t count, loff_t *ppos) | ||
207 | { | ||
208 | struct ath6kl *ar = file->private_data; | ||
209 | char *buf; | ||
210 | unsigned int len = 0, buf_len = 1500; | ||
211 | ssize_t ret_cnt; | ||
212 | |||
213 | buf = kzalloc(buf_len, GFP_KERNEL); | ||
214 | if (!buf) | ||
215 | return -ENOMEM; | ||
216 | |||
217 | len += scnprintf(buf + len, buf_len - len, "\n"); | ||
218 | len += scnprintf(buf + len, buf_len - len, "%25s\n", | ||
219 | "Workaround stats"); | ||
220 | len += scnprintf(buf + len, buf_len - len, "%25s\n\n", | ||
221 | "================="); | ||
222 | len += scnprintf(buf + len, buf_len - len, "%20s %10u\n", | ||
223 | "Invalid rates", ar->debug.war_stats.invalid_rate); | ||
224 | |||
225 | if (WARN_ON(len > buf_len)) | ||
226 | len = buf_len; | ||
227 | |||
228 | ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
229 | |||
230 | kfree(buf); | ||
231 | return ret_cnt; | ||
232 | } | ||
233 | |||
234 | static const struct file_operations fops_war_stats = { | ||
235 | .read = read_file_war_stats, | ||
236 | .open = ath6kl_debugfs_open, | ||
237 | .owner = THIS_MODULE, | ||
238 | .llseek = default_llseek, | ||
239 | }; | ||
240 | |||
241 | static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf, | ||
242 | size_t buf_len) | ||
243 | { | ||
244 | struct circ_buf *fwlog = &ar->debug.fwlog_buf; | ||
245 | size_t space; | ||
246 | int i; | ||
247 | |||
248 | /* entries must all be equal size */ | ||
249 | if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE)) | ||
250 | return; | ||
251 | |||
252 | space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE); | ||
253 | if (space < buf_len) | ||
254 | /* discard oldest slot */ | ||
255 | fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) & | ||
256 | (ATH6KL_FWLOG_SIZE - 1); | ||
257 | |||
258 | for (i = 0; i < buf_len; i += space) { | ||
259 | space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail, | ||
260 | ATH6KL_FWLOG_SIZE); | ||
261 | |||
262 | if ((size_t) space > buf_len - i) | ||
263 | space = buf_len - i; | ||
264 | |||
265 | memcpy(&fwlog->buf[fwlog->head], buf, space); | ||
266 | fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1); | ||
267 | } | ||
268 | |||
269 | } | ||
270 | |||
271 | void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len) | ||
272 | { | ||
273 | struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp; | ||
274 | size_t slot_len; | ||
275 | |||
276 | if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) | ||
277 | return; | ||
278 | |||
279 | spin_lock_bh(&ar->debug.fwlog_lock); | ||
280 | |||
281 | slot->timestamp = cpu_to_le32(jiffies); | ||
282 | slot->length = cpu_to_le32(len); | ||
283 | memcpy(slot->payload, buf, len); | ||
284 | |||
285 | slot_len = sizeof(*slot) + len; | ||
286 | |||
287 | if (slot_len < ATH6KL_FWLOG_SLOT_SIZE) | ||
288 | memset(slot->payload + len, 0, | ||
289 | ATH6KL_FWLOG_SLOT_SIZE - slot_len); | ||
290 | |||
291 | ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE); | ||
292 | |||
293 | spin_unlock_bh(&ar->debug.fwlog_lock); | ||
294 | } | ||
295 | |||
296 | static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar) | ||
297 | { | ||
298 | return CIRC_CNT(ar->debug.fwlog_buf.head, | ||
299 | ar->debug.fwlog_buf.tail, | ||
300 | ATH6KL_FWLOG_SLOT_SIZE) == 0; | ||
301 | } | ||
302 | |||
303 | static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf, | ||
304 | size_t count, loff_t *ppos) | ||
305 | { | ||
306 | struct ath6kl *ar = file->private_data; | ||
307 | struct circ_buf *fwlog = &ar->debug.fwlog_buf; | ||
308 | size_t len = 0, buf_len = count; | ||
309 | ssize_t ret_cnt; | ||
310 | char *buf; | ||
311 | int ccnt; | ||
312 | |||
313 | buf = vmalloc(buf_len); | ||
314 | if (!buf) | ||
315 | return -ENOMEM; | ||
316 | |||
317 | /* read undelivered logs from firmware */ | ||
318 | ath6kl_read_fwlogs(ar); | ||
319 | |||
320 | spin_lock_bh(&ar->debug.fwlog_lock); | ||
321 | |||
322 | while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) { | ||
323 | ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail, | ||
324 | ATH6KL_FWLOG_SIZE); | ||
325 | |||
326 | if ((size_t) ccnt > buf_len - len) | ||
327 | ccnt = buf_len - len; | ||
328 | |||
329 | memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt); | ||
330 | len += ccnt; | ||
331 | |||
332 | fwlog->tail = (fwlog->tail + ccnt) & | ||
333 | (ATH6KL_FWLOG_SIZE - 1); | ||
334 | } | ||
335 | |||
336 | spin_unlock_bh(&ar->debug.fwlog_lock); | ||
337 | |||
338 | if (WARN_ON(len > buf_len)) | ||
339 | len = buf_len; | ||
340 | |||
341 | ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
342 | |||
343 | vfree(buf); | ||
344 | |||
345 | return ret_cnt; | ||
346 | } | ||
347 | |||
348 | static const struct file_operations fops_fwlog = { | ||
349 | .open = ath6kl_debugfs_open, | ||
350 | .read = ath6kl_fwlog_read, | ||
351 | .owner = THIS_MODULE, | ||
352 | .llseek = default_llseek, | ||
353 | }; | ||
354 | |||
355 | static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf, | ||
356 | size_t count, loff_t *ppos) | ||
357 | { | ||
358 | struct ath6kl *ar = file->private_data; | ||
359 | char buf[16]; | ||
360 | int len; | ||
361 | |||
362 | len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask); | ||
363 | |||
364 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
365 | } | ||
366 | |||
367 | static ssize_t ath6kl_fwlog_mask_write(struct file *file, | ||
368 | const char __user *user_buf, | ||
369 | size_t count, loff_t *ppos) | ||
370 | { | ||
371 | struct ath6kl *ar = file->private_data; | ||
372 | int ret; | ||
373 | |||
374 | ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask); | ||
375 | if (ret) | ||
376 | return ret; | ||
377 | |||
378 | ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi, | ||
379 | ATH6KL_FWLOG_VALID_MASK, | ||
380 | ar->debug.fwlog_mask); | ||
381 | if (ret) | ||
382 | return ret; | ||
383 | |||
384 | return count; | ||
385 | } | ||
386 | |||
387 | static const struct file_operations fops_fwlog_mask = { | ||
388 | .open = ath6kl_debugfs_open, | ||
389 | .read = ath6kl_fwlog_mask_read, | ||
390 | .write = ath6kl_fwlog_mask_write, | ||
391 | .owner = THIS_MODULE, | ||
392 | .llseek = default_llseek, | ||
393 | }; | ||
394 | |||
395 | static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, | ||
396 | size_t count, loff_t *ppos) | ||
397 | { | ||
398 | struct ath6kl *ar = file->private_data; | ||
399 | struct target_stats *tgt_stats = &ar->target_stats; | ||
400 | char *buf; | ||
401 | unsigned int len = 0, buf_len = 1500; | ||
402 | int i; | ||
403 | long left; | ||
404 | ssize_t ret_cnt; | ||
405 | |||
406 | buf = kzalloc(buf_len, GFP_KERNEL); | ||
407 | if (!buf) | ||
408 | return -ENOMEM; | ||
409 | |||
410 | if (down_interruptible(&ar->sem)) { | ||
411 | kfree(buf); | ||
412 | return -EBUSY; | ||
413 | } | ||
414 | |||
415 | set_bit(STATS_UPDATE_PEND, &ar->flag); | ||
416 | |||
417 | if (ath6kl_wmi_get_stats_cmd(ar->wmi)) { | ||
418 | up(&ar->sem); | ||
419 | kfree(buf); | ||
420 | return -EIO; | ||
421 | } | ||
422 | |||
423 | left = wait_event_interruptible_timeout(ar->event_wq, | ||
424 | !test_bit(STATS_UPDATE_PEND, | ||
425 | &ar->flag), WMI_TIMEOUT); | ||
426 | |||
427 | up(&ar->sem); | ||
428 | |||
429 | if (left <= 0) { | ||
430 | kfree(buf); | ||
431 | return -ETIMEDOUT; | ||
432 | } | ||
433 | |||
434 | len += scnprintf(buf + len, buf_len - len, "\n"); | ||
435 | len += scnprintf(buf + len, buf_len - len, "%25s\n", | ||
436 | "Target Tx stats"); | ||
437 | len += scnprintf(buf + len, buf_len - len, "%25s\n\n", | ||
438 | "================="); | ||
439 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
440 | "Ucast packets", tgt_stats->tx_ucast_pkt); | ||
441 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
442 | "Bcast packets", tgt_stats->tx_bcast_pkt); | ||
443 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
444 | "Ucast byte", tgt_stats->tx_ucast_byte); | ||
445 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
446 | "Bcast byte", tgt_stats->tx_bcast_byte); | ||
447 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
448 | "Rts success cnt", tgt_stats->tx_rts_success_cnt); | ||
449 | for (i = 0; i < 4; i++) | ||
450 | len += scnprintf(buf + len, buf_len - len, | ||
451 | "%18s %d %10llu\n", "PER on ac", | ||
452 | i, tgt_stats->tx_pkt_per_ac[i]); | ||
453 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
454 | "Error", tgt_stats->tx_err); | ||
455 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
456 | "Fail count", tgt_stats->tx_fail_cnt); | ||
457 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
458 | "Retry count", tgt_stats->tx_retry_cnt); | ||
459 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
460 | "Multi retry cnt", tgt_stats->tx_mult_retry_cnt); | ||
461 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
462 | "Rts fail cnt", tgt_stats->tx_rts_fail_cnt); | ||
463 | len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n", | ||
464 | "TKIP counter measure used", | ||
465 | tgt_stats->tkip_cnter_measures_invoked); | ||
466 | |||
467 | len += scnprintf(buf + len, buf_len - len, "%25s\n", | ||
468 | "Target Rx stats"); | ||
469 | len += scnprintf(buf + len, buf_len - len, "%25s\n", | ||
470 | "================="); | ||
471 | |||
472 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
473 | "Ucast packets", tgt_stats->rx_ucast_pkt); | ||
474 | len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", | ||
475 | "Ucast Rate", tgt_stats->rx_ucast_rate); | ||
476 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
477 | "Bcast packets", tgt_stats->rx_bcast_pkt); | ||
478 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
479 | "Ucast byte", tgt_stats->rx_ucast_byte); | ||
480 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
481 | "Bcast byte", tgt_stats->rx_bcast_byte); | ||
482 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
483 | "Fragmented pkt", tgt_stats->rx_frgment_pkt); | ||
484 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
485 | "Error", tgt_stats->rx_err); | ||
486 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
487 | "CRC Err", tgt_stats->rx_crc_err); | ||
488 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
489 | "Key chache miss", tgt_stats->rx_key_cache_miss); | ||
490 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
491 | "Decrypt Err", tgt_stats->rx_decrypt_err); | ||
492 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
493 | "Duplicate frame", tgt_stats->rx_dupl_frame); | ||
494 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
495 | "Tkip Mic failure", tgt_stats->tkip_local_mic_fail); | ||
496 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
497 | "TKIP format err", tgt_stats->tkip_fmt_err); | ||
498 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
499 | "CCMP format Err", tgt_stats->ccmp_fmt_err); | ||
500 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", | ||
501 | "CCMP Replay Err", tgt_stats->ccmp_replays); | ||
502 | |||
503 | len += scnprintf(buf + len, buf_len - len, "%25s\n", | ||
504 | "Misc Target stats"); | ||
505 | len += scnprintf(buf + len, buf_len - len, "%25s\n", | ||
506 | "================="); | ||
507 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
508 | "Beacon Miss count", tgt_stats->cs_bmiss_cnt); | ||
509 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
510 | "Num Connects", tgt_stats->cs_connect_cnt); | ||
511 | len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", | ||
512 | "Num disconnects", tgt_stats->cs_discon_cnt); | ||
513 | len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", | ||
514 | "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi); | ||
515 | |||
516 | if (len > buf_len) | ||
517 | len = buf_len; | ||
518 | |||
519 | ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
520 | |||
521 | kfree(buf); | ||
522 | return ret_cnt; | ||
523 | } | ||
524 | |||
525 | static const struct file_operations fops_tgt_stats = { | ||
526 | .read = read_file_tgt_stats, | ||
527 | .open = ath6kl_debugfs_open, | ||
528 | .owner = THIS_MODULE, | ||
529 | .llseek = default_llseek, | ||
530 | }; | ||
531 | |||
532 | #define print_credit_info(fmt_str, ep_list_field) \ | ||
533 | (len += scnprintf(buf + len, buf_len - len, fmt_str, \ | ||
534 | ep_list->ep_list_field)) | ||
535 | #define CREDIT_INFO_DISPLAY_STRING_LEN 200 | ||
536 | #define CREDIT_INFO_LEN 128 | ||
537 | |||
538 | static ssize_t read_file_credit_dist_stats(struct file *file, | ||
539 | char __user *user_buf, | ||
540 | size_t count, loff_t *ppos) | ||
541 | { | ||
542 | struct ath6kl *ar = file->private_data; | ||
543 | struct htc_target *target = ar->htc_target; | ||
544 | struct htc_endpoint_credit_dist *ep_list; | ||
545 | char *buf; | ||
546 | unsigned int buf_len, len = 0; | ||
547 | ssize_t ret_cnt; | ||
548 | |||
549 | buf_len = CREDIT_INFO_DISPLAY_STRING_LEN + | ||
550 | get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN; | ||
551 | buf = kzalloc(buf_len, GFP_KERNEL); | ||
552 | if (!buf) | ||
553 | return -ENOMEM; | ||
554 | |||
555 | len += scnprintf(buf + len, buf_len - len, "%25s%5d\n", | ||
556 | "Total Avail Credits: ", | ||
557 | target->cred_dist_cntxt->total_avail_credits); | ||
558 | len += scnprintf(buf + len, buf_len - len, "%25s%5d\n", | ||
559 | "Free credits :", | ||
560 | target->cred_dist_cntxt->cur_free_credits); | ||
561 | |||
562 | len += scnprintf(buf + len, buf_len - len, | ||
563 | " Epid Flags Cred_norm Cred_min Credits Cred_assngd" | ||
564 | " Seek_cred Cred_sz Cred_per_msg Cred_to_dist" | ||
565 | " qdepth\n"); | ||
566 | |||
567 | list_for_each_entry(ep_list, &target->cred_dist_list, list) { | ||
568 | print_credit_info(" %2d", endpoint); | ||
569 | print_credit_info("%10x", dist_flags); | ||
570 | print_credit_info("%8d", cred_norm); | ||
571 | print_credit_info("%9d", cred_min); | ||
572 | print_credit_info("%9d", credits); | ||
573 | print_credit_info("%10d", cred_assngd); | ||
574 | print_credit_info("%13d", seek_cred); | ||
575 | print_credit_info("%12d", cred_sz); | ||
576 | print_credit_info("%9d", cred_per_msg); | ||
577 | print_credit_info("%14d", cred_to_dist); | ||
578 | len += scnprintf(buf + len, buf_len - len, "%12d\n", | ||
579 | get_queue_depth(&((struct htc_endpoint *) | ||
580 | ep_list->htc_rsvd)->txq)); | ||
581 | } | ||
582 | |||
583 | if (len > buf_len) | ||
584 | len = buf_len; | ||
585 | |||
586 | ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
587 | kfree(buf); | ||
588 | return ret_cnt; | ||
589 | } | ||
590 | |||
591 | static const struct file_operations fops_credit_dist_stats = { | ||
592 | .read = read_file_credit_dist_stats, | ||
593 | .open = ath6kl_debugfs_open, | ||
594 | .owner = THIS_MODULE, | ||
595 | .llseek = default_llseek, | ||
596 | }; | ||
597 | |||
598 | static unsigned long ath6kl_get_num_reg(void) | ||
599 | { | ||
600 | int i; | ||
601 | unsigned long n_reg = 0; | ||
602 | |||
603 | for (i = 0; i < ARRAY_SIZE(diag_reg); i++) | ||
604 | n_reg = n_reg + | ||
605 | (diag_reg[i].reg_end - diag_reg[i].reg_start) / 4 + 1; | ||
606 | |||
607 | return n_reg; | ||
608 | } | ||
609 | |||
610 | static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr) | ||
611 | { | ||
612 | int i; | ||
613 | |||
614 | for (i = 0; i < ARRAY_SIZE(diag_reg); i++) { | ||
615 | if (reg_addr >= diag_reg[i].reg_start && | ||
616 | reg_addr <= diag_reg[i].reg_end) | ||
617 | return true; | ||
618 | } | ||
619 | |||
620 | return false; | ||
621 | } | ||
622 | |||
623 | static ssize_t ath6kl_regread_read(struct file *file, char __user *user_buf, | ||
624 | size_t count, loff_t *ppos) | ||
625 | { | ||
626 | struct ath6kl *ar = file->private_data; | ||
627 | u8 buf[50]; | ||
628 | unsigned int len = 0; | ||
629 | |||
630 | if (ar->debug.dbgfs_diag_reg) | ||
631 | len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", | ||
632 | ar->debug.dbgfs_diag_reg); | ||
633 | else | ||
634 | len += scnprintf(buf + len, sizeof(buf) - len, | ||
635 | "All diag registers\n"); | ||
636 | |||
637 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
638 | } | ||
639 | |||
640 | static ssize_t ath6kl_regread_write(struct file *file, | ||
641 | const char __user *user_buf, | ||
642 | size_t count, loff_t *ppos) | ||
643 | { | ||
644 | struct ath6kl *ar = file->private_data; | ||
645 | u8 buf[50]; | ||
646 | unsigned int len; | ||
647 | unsigned long reg_addr; | ||
648 | |||
649 | len = min(count, sizeof(buf) - 1); | ||
650 | if (copy_from_user(buf, user_buf, len)) | ||
651 | return -EFAULT; | ||
652 | |||
653 | buf[len] = '\0'; | ||
654 | |||
655 | if (strict_strtoul(buf, 0, ®_addr)) | ||
656 | return -EINVAL; | ||
657 | |||
658 | if ((reg_addr % 4) != 0) | ||
659 | return -EINVAL; | ||
660 | |||
661 | if (reg_addr && !ath6kl_dbg_is_diag_reg_valid(reg_addr)) | ||
662 | return -EINVAL; | ||
663 | |||
664 | ar->debug.dbgfs_diag_reg = reg_addr; | ||
665 | |||
666 | return count; | ||
667 | } | ||
668 | |||
669 | static const struct file_operations fops_diag_reg_read = { | ||
670 | .read = ath6kl_regread_read, | ||
671 | .write = ath6kl_regread_write, | ||
672 | .open = ath6kl_debugfs_open, | ||
673 | .owner = THIS_MODULE, | ||
674 | .llseek = default_llseek, | ||
675 | }; | ||
676 | |||
677 | static int ath6kl_regdump_open(struct inode *inode, struct file *file) | ||
678 | { | ||
679 | struct ath6kl *ar = inode->i_private; | ||
680 | u8 *buf; | ||
681 | unsigned long int reg_len; | ||
682 | unsigned int len = 0, n_reg; | ||
683 | u32 addr; | ||
684 | __le32 reg_val; | ||
685 | int i, status; | ||
686 | |||
687 | /* Dump all the registers if no register is specified */ | ||
688 | if (!ar->debug.dbgfs_diag_reg) | ||
689 | n_reg = ath6kl_get_num_reg(); | ||
690 | else | ||
691 | n_reg = 1; | ||
692 | |||
693 | reg_len = n_reg * REG_OUTPUT_LEN_PER_LINE; | ||
694 | if (n_reg > 1) | ||
695 | reg_len += REGTYPE_STR_LEN; | ||
696 | |||
697 | buf = vmalloc(reg_len); | ||
698 | if (!buf) | ||
699 | return -ENOMEM; | ||
700 | |||
701 | if (n_reg == 1) { | ||
702 | addr = ar->debug.dbgfs_diag_reg; | ||
703 | |||
704 | status = ath6kl_diag_read32(ar, | ||
705 | TARG_VTOP(ar->target_type, addr), | ||
706 | (u32 *)®_val); | ||
707 | if (status) | ||
708 | goto fail_reg_read; | ||
709 | |||
710 | len += scnprintf(buf + len, reg_len - len, | ||
711 | "0x%06x 0x%08x\n", addr, le32_to_cpu(reg_val)); | ||
712 | goto done; | ||
713 | } | ||
714 | |||
715 | for (i = 0; i < ARRAY_SIZE(diag_reg); i++) { | ||
716 | len += scnprintf(buf + len, reg_len - len, | ||
717 | "%s\n", diag_reg[i].reg_info); | ||
718 | for (addr = diag_reg[i].reg_start; | ||
719 | addr <= diag_reg[i].reg_end; addr += 4) { | ||
720 | status = ath6kl_diag_read32(ar, | ||
721 | TARG_VTOP(ar->target_type, addr), | ||
722 | (u32 *)®_val); | ||
723 | if (status) | ||
724 | goto fail_reg_read; | ||
725 | |||
726 | len += scnprintf(buf + len, reg_len - len, | ||
727 | "0x%06x 0x%08x\n", | ||
728 | addr, le32_to_cpu(reg_val)); | ||
729 | } | ||
730 | } | ||
731 | |||
732 | done: | ||
733 | file->private_data = buf; | ||
734 | return 0; | ||
735 | |||
736 | fail_reg_read: | ||
737 | ath6kl_warn("Unable to read memory:%u\n", addr); | ||
738 | vfree(buf); | ||
739 | return -EIO; | ||
740 | } | ||
741 | |||
742 | static ssize_t ath6kl_regdump_read(struct file *file, char __user *user_buf, | ||
743 | size_t count, loff_t *ppos) | ||
744 | { | ||
745 | u8 *buf = file->private_data; | ||
746 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | ||
747 | } | ||
748 | |||
749 | static int ath6kl_regdump_release(struct inode *inode, struct file *file) | ||
750 | { | ||
751 | vfree(file->private_data); | ||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static const struct file_operations fops_reg_dump = { | ||
756 | .open = ath6kl_regdump_open, | ||
757 | .read = ath6kl_regdump_read, | ||
758 | .release = ath6kl_regdump_release, | ||
759 | .owner = THIS_MODULE, | ||
760 | .llseek = default_llseek, | ||
761 | }; | ||
762 | |||
763 | static ssize_t ath6kl_lrssi_roam_write(struct file *file, | ||
764 | const char __user *user_buf, | ||
765 | size_t count, loff_t *ppos) | ||
766 | { | ||
767 | struct ath6kl *ar = file->private_data; | ||
768 | unsigned long lrssi_roam_threshold; | ||
769 | char buf[32]; | ||
770 | ssize_t len; | ||
771 | |||
772 | len = min(count, sizeof(buf) - 1); | ||
773 | if (copy_from_user(buf, user_buf, len)) | ||
774 | return -EFAULT; | ||
775 | |||
776 | buf[len] = '\0'; | ||
777 | if (strict_strtoul(buf, 0, &lrssi_roam_threshold)) | ||
778 | return -EINVAL; | ||
779 | |||
780 | ar->lrssi_roam_threshold = lrssi_roam_threshold; | ||
781 | |||
782 | ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold); | ||
783 | |||
784 | return count; | ||
785 | } | ||
786 | |||
787 | static ssize_t ath6kl_lrssi_roam_read(struct file *file, | ||
788 | char __user *user_buf, | ||
789 | size_t count, loff_t *ppos) | ||
790 | { | ||
791 | struct ath6kl *ar = file->private_data; | ||
792 | char buf[32]; | ||
793 | unsigned int len; | ||
794 | |||
795 | len = snprintf(buf, sizeof(buf), "%u\n", ar->lrssi_roam_threshold); | ||
796 | |||
797 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
798 | } | ||
799 | |||
800 | static const struct file_operations fops_lrssi_roam_threshold = { | ||
801 | .read = ath6kl_lrssi_roam_read, | ||
802 | .write = ath6kl_lrssi_roam_write, | ||
803 | .open = ath6kl_debugfs_open, | ||
804 | .owner = THIS_MODULE, | ||
805 | .llseek = default_llseek, | ||
806 | }; | ||
807 | |||
808 | static ssize_t ath6kl_regwrite_read(struct file *file, | ||
809 | char __user *user_buf, | ||
810 | size_t count, loff_t *ppos) | ||
811 | { | ||
812 | struct ath6kl *ar = file->private_data; | ||
813 | u8 buf[32]; | ||
814 | unsigned int len = 0; | ||
815 | |||
816 | len = scnprintf(buf, sizeof(buf), "Addr: 0x%x Val: 0x%x\n", | ||
817 | ar->debug.diag_reg_addr_wr, ar->debug.diag_reg_val_wr); | ||
818 | |||
819 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
820 | } | ||
821 | |||
822 | static ssize_t ath6kl_regwrite_write(struct file *file, | ||
823 | const char __user *user_buf, | ||
824 | size_t count, loff_t *ppos) | ||
825 | { | ||
826 | struct ath6kl *ar = file->private_data; | ||
827 | char buf[32]; | ||
828 | char *sptr, *token; | ||
829 | unsigned int len = 0; | ||
830 | u32 reg_addr, reg_val; | ||
831 | |||
832 | len = min(count, sizeof(buf) - 1); | ||
833 | if (copy_from_user(buf, user_buf, len)) | ||
834 | return -EFAULT; | ||
835 | |||
836 | buf[len] = '\0'; | ||
837 | sptr = buf; | ||
838 | |||
839 | token = strsep(&sptr, "="); | ||
840 | if (!token) | ||
841 | return -EINVAL; | ||
842 | |||
843 | if (kstrtou32(token, 0, ®_addr)) | ||
844 | return -EINVAL; | ||
845 | |||
846 | if (!ath6kl_dbg_is_diag_reg_valid(reg_addr)) | ||
847 | return -EINVAL; | ||
848 | |||
849 | if (kstrtou32(sptr, 0, ®_val)) | ||
850 | return -EINVAL; | ||
851 | |||
852 | ar->debug.diag_reg_addr_wr = reg_addr; | ||
853 | ar->debug.diag_reg_val_wr = reg_val; | ||
854 | |||
855 | if (ath6kl_diag_write32(ar, ar->debug.diag_reg_addr_wr, | ||
856 | cpu_to_le32(ar->debug.diag_reg_val_wr))) | ||
857 | return -EIO; | ||
858 | |||
859 | return count; | ||
860 | } | ||
861 | |||
862 | static const struct file_operations fops_diag_reg_write = { | ||
863 | .read = ath6kl_regwrite_read, | ||
864 | .write = ath6kl_regwrite_write, | ||
865 | .open = ath6kl_debugfs_open, | ||
866 | .owner = THIS_MODULE, | ||
867 | .llseek = default_llseek, | ||
868 | }; | ||
869 | |||
870 | int ath6kl_debug_init(struct ath6kl *ar) | ||
871 | { | ||
872 | ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE); | ||
873 | if (ar->debug.fwlog_buf.buf == NULL) | ||
874 | return -ENOMEM; | ||
875 | |||
876 | ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL); | ||
877 | if (ar->debug.fwlog_tmp == NULL) { | ||
878 | vfree(ar->debug.fwlog_buf.buf); | ||
879 | return -ENOMEM; | ||
880 | } | ||
881 | |||
882 | spin_lock_init(&ar->debug.fwlog_lock); | ||
883 | |||
884 | /* | ||
885 | * Actually we are lying here but don't know how to read the mask | ||
886 | * value from the firmware. | ||
887 | */ | ||
888 | ar->debug.fwlog_mask = 0; | ||
889 | |||
890 | ar->debugfs_phy = debugfs_create_dir("ath6kl", | ||
891 | ar->wdev->wiphy->debugfsdir); | ||
892 | if (!ar->debugfs_phy) { | ||
893 | vfree(ar->debug.fwlog_buf.buf); | ||
894 | kfree(ar->debug.fwlog_tmp); | ||
895 | return -ENOMEM; | ||
896 | } | ||
897 | |||
898 | debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, | ||
899 | &fops_tgt_stats); | ||
900 | |||
901 | debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar, | ||
902 | &fops_credit_dist_stats); | ||
903 | |||
904 | debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar, | ||
905 | &fops_fwlog); | ||
906 | |||
907 | debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy, | ||
908 | ar, &fops_fwlog_mask); | ||
909 | |||
910 | debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar, | ||
911 | &fops_diag_reg_read); | ||
912 | |||
913 | debugfs_create_file("reg_dump", S_IRUSR, ar->debugfs_phy, ar, | ||
914 | &fops_reg_dump); | ||
915 | |||
916 | debugfs_create_file("lrssi_roam_threshold", S_IRUSR | S_IWUSR, | ||
917 | ar->debugfs_phy, ar, &fops_lrssi_roam_threshold); | ||
918 | |||
919 | debugfs_create_file("reg_write", S_IRUSR | S_IWUSR, | ||
920 | ar->debugfs_phy, ar, &fops_diag_reg_write); | ||
921 | |||
922 | debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar, | ||
923 | &fops_war_stats); | ||
924 | |||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | void ath6kl_debug_cleanup(struct ath6kl *ar) | ||
929 | { | ||
930 | vfree(ar->debug.fwlog_buf.buf); | ||
931 | kfree(ar->debug.fwlog_tmp); | ||
932 | } | ||
933 | |||
150 | #endif | 934 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 66b399962f01..9288a3ce1e39 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -34,8 +34,12 @@ enum ATH6K_DEBUG_MASK { | |||
34 | ATH6KL_DBG_TRC = BIT(11), /* generic func tracing */ | 34 | ATH6KL_DBG_TRC = BIT(11), /* generic func tracing */ |
35 | ATH6KL_DBG_SCATTER = BIT(12), /* hif scatter tracing */ | 35 | ATH6KL_DBG_SCATTER = BIT(12), /* hif scatter tracing */ |
36 | ATH6KL_DBG_WLAN_CFG = BIT(13), /* cfg80211 i/f file tracing */ | 36 | ATH6KL_DBG_WLAN_CFG = BIT(13), /* cfg80211 i/f file tracing */ |
37 | ATH6KL_DBG_RAW_BYTES = BIT(14), /* dump tx/rx and wmi frames */ | 37 | ATH6KL_DBG_RAW_BYTES = BIT(14), /* dump tx/rx frames */ |
38 | ATH6KL_DBG_AGGR = BIT(15), /* aggregation */ | 38 | ATH6KL_DBG_AGGR = BIT(15), /* aggregation */ |
39 | ATH6KL_DBG_SDIO = BIT(16), | ||
40 | ATH6KL_DBG_SDIO_DUMP = BIT(17), | ||
41 | ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ | ||
42 | ATH6KL_DBG_WMI_DUMP = BIT(19), | ||
39 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ | 43 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ |
40 | }; | 44 | }; |
41 | 45 | ||
@@ -52,6 +56,10 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...) | |||
52 | 56 | ||
53 | #define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) | 57 | #define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) |
54 | 58 | ||
59 | enum ath6kl_war { | ||
60 | ATH6KL_WAR_INVALID_RATE, | ||
61 | }; | ||
62 | |||
55 | #ifdef CONFIG_ATH6KL_DEBUG | 63 | #ifdef CONFIG_ATH6KL_DEBUG |
56 | #define ath6kl_dbg(mask, fmt, ...) \ | 64 | #define ath6kl_dbg(mask, fmt, ...) \ |
57 | ({ \ | 65 | ({ \ |
@@ -65,12 +73,14 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...) | |||
65 | }) | 73 | }) |
66 | 74 | ||
67 | static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, | 75 | static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, |
68 | const char *msg, const void *buf, | 76 | const char *msg, const char *prefix, |
69 | size_t len) | 77 | const void *buf, size_t len) |
70 | { | 78 | { |
71 | if (debug_mask & mask) { | 79 | if (debug_mask & mask) { |
72 | ath6kl_dbg(mask, "%s\n", msg); | 80 | if (msg) |
73 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); | 81 | ath6kl_dbg(mask, "%s\n", msg); |
82 | |||
83 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); | ||
74 | } | 84 | } |
75 | } | 85 | } |
76 | 86 | ||
@@ -78,6 +88,11 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, | |||
78 | struct ath6kl_irq_proc_registers *irq_proc_reg, | 88 | struct ath6kl_irq_proc_registers *irq_proc_reg, |
79 | struct ath6kl_irq_enable_reg *irq_en_reg); | 89 | struct ath6kl_irq_enable_reg *irq_en_reg); |
80 | void dump_cred_dist_stats(struct htc_target *target); | 90 | void dump_cred_dist_stats(struct htc_target *target); |
91 | void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len); | ||
92 | void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war); | ||
93 | int ath6kl_debug_init(struct ath6kl *ar); | ||
94 | void ath6kl_debug_cleanup(struct ath6kl *ar); | ||
95 | |||
81 | #else | 96 | #else |
82 | static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, | 97 | static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, |
83 | const char *fmt, ...) | 98 | const char *fmt, ...) |
@@ -86,8 +101,8 @@ static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, | |||
86 | } | 101 | } |
87 | 102 | ||
88 | static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, | 103 | static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, |
89 | const char *msg, const void *buf, | 104 | const char *msg, const char *prefix, |
90 | size_t len) | 105 | const void *buf, size_t len) |
91 | { | 106 | { |
92 | } | 107 | } |
93 | 108 | ||
@@ -100,6 +115,24 @@ static inline void ath6kl_dump_registers(struct ath6kl_device *dev, | |||
100 | static inline void dump_cred_dist_stats(struct htc_target *target) | 115 | static inline void dump_cred_dist_stats(struct htc_target *target) |
101 | { | 116 | { |
102 | } | 117 | } |
103 | #endif | ||
104 | 118 | ||
119 | static inline void ath6kl_debug_fwlog_event(struct ath6kl *ar, | ||
120 | const void *buf, size_t len) | ||
121 | { | ||
122 | } | ||
123 | |||
124 | static inline void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) | ||
125 | { | ||
126 | } | ||
127 | |||
128 | static inline int ath6kl_debug_init(struct ath6kl *ar) | ||
129 | { | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static inline void ath6kl_debug_cleanup(struct ath6kl *ar) | ||
134 | { | ||
135 | } | ||
136 | |||
137 | #endif | ||
105 | #endif | 138 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h index c923979776a0..d6c898f3d0b3 100644 --- a/drivers/net/wireless/ath/ath6kl/hif-ops.h +++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h | |||
@@ -69,4 +69,9 @@ static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar) | |||
69 | return ar->hif_ops->cleanup_scatter(ar); | 69 | return ar->hif_ops->cleanup_scatter(ar); |
70 | } | 70 | } |
71 | 71 | ||
72 | static inline int ath6kl_hif_suspend(struct ath6kl *ar) | ||
73 | { | ||
74 | return ar->hif_ops->suspend(ar); | ||
75 | } | ||
76 | |||
72 | #endif | 77 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h index 5ceff54775a1..797e2d1d9bf9 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.h +++ b/drivers/net/wireless/ath/ath6kl/hif.h | |||
@@ -202,6 +202,7 @@ struct ath6kl_hif_ops { | |||
202 | int (*scat_req_rw) (struct ath6kl *ar, | 202 | int (*scat_req_rw) (struct ath6kl *ar, |
203 | struct hif_scatter_req *scat_req); | 203 | struct hif_scatter_req *scat_req); |
204 | void (*cleanup_scatter)(struct ath6kl *ar); | 204 | void (*cleanup_scatter)(struct ath6kl *ar); |
205 | int (*suspend)(struct ath6kl *ar); | ||
205 | }; | 206 | }; |
206 | 207 | ||
207 | #endif | 208 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index a8dc5c3ea567..f88a7c9e4148 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c | |||
@@ -22,8 +22,19 @@ | |||
22 | 22 | ||
23 | #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) | 23 | #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) |
24 | 24 | ||
25 | static void htc_prep_send_pkt(struct htc_packet *packet, u8 flags, int ctrl0, | 25 | static void ath6kl_htc_tx_buf_align(u8 **buf, unsigned long len) |
26 | int ctrl1) | 26 | { |
27 | u8 *align_addr; | ||
28 | |||
29 | if (!IS_ALIGNED((unsigned long) *buf, 4)) { | ||
30 | align_addr = PTR_ALIGN(*buf - 4, 4); | ||
31 | memmove(align_addr, *buf, len); | ||
32 | *buf = align_addr; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | static void ath6kl_htc_tx_prep_pkt(struct htc_packet *packet, u8 flags, | ||
37 | int ctrl0, int ctrl1) | ||
27 | { | 38 | { |
28 | struct htc_frame_hdr *hdr; | 39 | struct htc_frame_hdr *hdr; |
29 | 40 | ||
@@ -167,7 +178,8 @@ static void htc_async_tx_scat_complete(struct htc_target *target, | |||
167 | htc_tx_complete(endpoint, &tx_compq); | 178 | htc_tx_complete(endpoint, &tx_compq); |
168 | } | 179 | } |
169 | 180 | ||
170 | static int htc_issue_send(struct htc_target *target, struct htc_packet *packet) | 181 | static int ath6kl_htc_tx_issue(struct htc_target *target, |
182 | struct htc_packet *packet) | ||
171 | { | 183 | { |
172 | int status; | 184 | int status; |
173 | bool sync = false; | 185 | bool sync = false; |
@@ -196,7 +208,7 @@ static int htc_issue_send(struct htc_target *target, struct htc_packet *packet) | |||
196 | HIF_WR_SYNC_BLOCK_INC); | 208 | HIF_WR_SYNC_BLOCK_INC); |
197 | 209 | ||
198 | packet->status = status; | 210 | packet->status = status; |
199 | packet->buf += HTC_HDR_LENGTH; | 211 | packet->buf += HTC_HDR_LENGTH; |
200 | } else | 212 | } else |
201 | status = hif_write_async(target->dev->ar, | 213 | status = hif_write_async(target->dev->ar, |
202 | target->dev->ar->mbox_info.htc_addr, | 214 | target->dev->ar->mbox_info.htc_addr, |
@@ -265,9 +277,9 @@ static int htc_check_credits(struct htc_target *target, | |||
265 | return 0; | 277 | return 0; |
266 | } | 278 | } |
267 | 279 | ||
268 | static void htc_tx_pkts_get(struct htc_target *target, | 280 | static void ath6kl_htc_tx_pkts_get(struct htc_target *target, |
269 | struct htc_endpoint *endpoint, | 281 | struct htc_endpoint *endpoint, |
270 | struct list_head *queue) | 282 | struct list_head *queue) |
271 | { | 283 | { |
272 | int req_cred; | 284 | int req_cred; |
273 | u8 flags; | 285 | u8 flags; |
@@ -346,11 +358,11 @@ static int htc_get_credit_padding(unsigned int cred_sz, int *len, | |||
346 | return cred_pad; | 358 | return cred_pad; |
347 | } | 359 | } |
348 | 360 | ||
349 | static int htc_setup_send_scat_list(struct htc_target *target, | 361 | static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target, |
350 | struct htc_endpoint *endpoint, | 362 | struct htc_endpoint *endpoint, |
351 | struct hif_scatter_req *scat_req, | 363 | struct hif_scatter_req *scat_req, |
352 | int n_scat, | 364 | int n_scat, |
353 | struct list_head *queue) | 365 | struct list_head *queue) |
354 | { | 366 | { |
355 | struct htc_packet *packet; | 367 | struct htc_packet *packet; |
356 | int i, len, rem_scat, cred_pad; | 368 | int i, len, rem_scat, cred_pad; |
@@ -370,27 +382,23 @@ static int htc_setup_send_scat_list(struct htc_target *target, | |||
370 | 382 | ||
371 | cred_pad = htc_get_credit_padding(target->tgt_cred_sz, | 383 | cred_pad = htc_get_credit_padding(target->tgt_cred_sz, |
372 | &len, endpoint); | 384 | &len, endpoint); |
373 | if (cred_pad < 0) { | 385 | if (cred_pad < 0 || rem_scat < len) { |
374 | status = -EINVAL; | ||
375 | break; | ||
376 | } | ||
377 | |||
378 | if (rem_scat < len) { | ||
379 | /* exceeds what we can transfer */ | ||
380 | status = -ENOSPC; | 386 | status = -ENOSPC; |
381 | break; | 387 | break; |
382 | } | 388 | } |
383 | 389 | ||
384 | rem_scat -= len; | 390 | rem_scat -= len; |
385 | /* now remove it from the queue */ | 391 | /* now remove it from the queue */ |
386 | packet = list_first_entry(queue, struct htc_packet, list); | ||
387 | list_del(&packet->list); | 392 | list_del(&packet->list); |
388 | 393 | ||
389 | scat_req->scat_list[i].packet = packet; | 394 | scat_req->scat_list[i].packet = packet; |
390 | /* prepare packet and flag message as part of a send bundle */ | 395 | /* prepare packet and flag message as part of a send bundle */ |
391 | htc_prep_send_pkt(packet, | 396 | ath6kl_htc_tx_prep_pkt(packet, |
392 | packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE, | 397 | packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE, |
393 | cred_pad, packet->info.tx.seqno); | 398 | cred_pad, packet->info.tx.seqno); |
399 | /* Make sure the buffer is 4-byte aligned */ | ||
400 | ath6kl_htc_tx_buf_align(&packet->buf, | ||
401 | packet->act_len + HTC_HDR_LENGTH); | ||
394 | scat_req->scat_list[i].buf = packet->buf; | 402 | scat_req->scat_list[i].buf = packet->buf; |
395 | scat_req->scat_list[i].len = len; | 403 | scat_req->scat_list[i].len = len; |
396 | 404 | ||
@@ -402,7 +410,7 @@ static int htc_setup_send_scat_list(struct htc_target *target, | |||
402 | } | 410 | } |
403 | 411 | ||
404 | /* Roll back scatter setup in case of any failure */ | 412 | /* Roll back scatter setup in case of any failure */ |
405 | if (status || (scat_req->scat_entries < HTC_MIN_HTC_MSGS_TO_BUNDLE)) { | 413 | if (scat_req->scat_entries < HTC_MIN_HTC_MSGS_TO_BUNDLE) { |
406 | for (i = scat_req->scat_entries - 1; i >= 0; i--) { | 414 | for (i = scat_req->scat_entries - 1; i >= 0; i--) { |
407 | packet = scat_req->scat_list[i].packet; | 415 | packet = scat_req->scat_list[i].packet; |
408 | if (packet) { | 416 | if (packet) { |
@@ -410,31 +418,32 @@ static int htc_setup_send_scat_list(struct htc_target *target, | |||
410 | list_add(&packet->list, queue); | 418 | list_add(&packet->list, queue); |
411 | } | 419 | } |
412 | } | 420 | } |
413 | return -EINVAL; | 421 | return -EAGAIN; |
414 | } | 422 | } |
415 | 423 | ||
416 | return 0; | 424 | return status; |
417 | } | 425 | } |
418 | 426 | ||
419 | /* | 427 | /* |
420 | * htc_issue_send_bundle: drain a queue and send as bundles | 428 | * Drain a queue and send as bundles this function may return without fully |
421 | * this function may return without fully draining the queue | 429 | * draining the queue when |
422 | * when | ||
423 | * | 430 | * |
424 | * 1. scatter resources are exhausted | 431 | * 1. scatter resources are exhausted |
425 | * 2. a message that will consume a partial credit will stop the | 432 | * 2. a message that will consume a partial credit will stop the |
426 | * bundling process early | 433 | * bundling process early |
427 | * 3. we drop below the minimum number of messages for a bundle | 434 | * 3. we drop below the minimum number of messages for a bundle |
428 | */ | 435 | */ |
429 | static void htc_issue_send_bundle(struct htc_endpoint *endpoint, | 436 | static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, |
430 | struct list_head *queue, | 437 | struct list_head *queue, |
431 | int *sent_bundle, int *n_bundle_pkts) | 438 | int *sent_bundle, int *n_bundle_pkts) |
432 | { | 439 | { |
433 | struct htc_target *target = endpoint->target; | 440 | struct htc_target *target = endpoint->target; |
434 | struct hif_scatter_req *scat_req = NULL; | 441 | struct hif_scatter_req *scat_req = NULL; |
435 | int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; | 442 | int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; |
443 | int status; | ||
436 | 444 | ||
437 | while (true) { | 445 | while (true) { |
446 | status = 0; | ||
438 | n_scat = get_queue_depth(queue); | 447 | n_scat = get_queue_depth(queue); |
439 | n_scat = min(n_scat, target->msg_per_bndl_max); | 448 | n_scat = min(n_scat, target->msg_per_bndl_max); |
440 | 449 | ||
@@ -457,8 +466,10 @@ static void htc_issue_send_bundle(struct htc_endpoint *endpoint, | |||
457 | scat_req->len = 0; | 466 | scat_req->len = 0; |
458 | scat_req->scat_entries = 0; | 467 | scat_req->scat_entries = 0; |
459 | 468 | ||
460 | if (htc_setup_send_scat_list(target, endpoint, scat_req, | 469 | status = ath6kl_htc_tx_setup_scat_list(target, endpoint, |
461 | n_scat, queue)) { | 470 | scat_req, n_scat, |
471 | queue); | ||
472 | if (status == -EAGAIN) { | ||
462 | hif_scatter_req_add(target->dev->ar, scat_req); | 473 | hif_scatter_req_add(target->dev->ar, scat_req); |
463 | break; | 474 | break; |
464 | } | 475 | } |
@@ -472,18 +483,21 @@ static void htc_issue_send_bundle(struct htc_endpoint *endpoint, | |||
472 | "send scatter total bytes: %d , entries: %d\n", | 483 | "send scatter total bytes: %d , entries: %d\n", |
473 | scat_req->len, scat_req->scat_entries); | 484 | scat_req->len, scat_req->scat_entries); |
474 | ath6kldev_submit_scat_req(target->dev, scat_req, false); | 485 | ath6kldev_submit_scat_req(target->dev, scat_req, false); |
486 | |||
487 | if (status) | ||
488 | break; | ||
475 | } | 489 | } |
476 | 490 | ||
477 | *sent_bundle = n_sent_bundle; | 491 | *sent_bundle = n_sent_bundle; |
478 | *n_bundle_pkts = tot_pkts_bundle; | 492 | *n_bundle_pkts = tot_pkts_bundle; |
479 | ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "htc_issue_send_bundle (sent:%d)\n", | 493 | ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "%s (sent:%d)\n", |
480 | n_sent_bundle); | 494 | __func__, n_sent_bundle); |
481 | 495 | ||
482 | return; | 496 | return; |
483 | } | 497 | } |
484 | 498 | ||
485 | static void htc_tx_from_ep_txq(struct htc_target *target, | 499 | static void ath6kl_htc_tx_from_queue(struct htc_target *target, |
486 | struct htc_endpoint *endpoint) | 500 | struct htc_endpoint *endpoint) |
487 | { | 501 | { |
488 | struct list_head txq; | 502 | struct list_head txq; |
489 | struct htc_packet *packet; | 503 | struct htc_packet *packet; |
@@ -511,7 +525,7 @@ static void htc_tx_from_ep_txq(struct htc_target *target, | |||
511 | if (list_empty(&endpoint->txq)) | 525 | if (list_empty(&endpoint->txq)) |
512 | break; | 526 | break; |
513 | 527 | ||
514 | htc_tx_pkts_get(target, endpoint, &txq); | 528 | ath6kl_htc_tx_pkts_get(target, endpoint, &txq); |
515 | 529 | ||
516 | if (list_empty(&txq)) | 530 | if (list_empty(&txq)) |
517 | break; | 531 | break; |
@@ -528,8 +542,8 @@ static void htc_tx_from_ep_txq(struct htc_target *target, | |||
528 | HTC_MIN_HTC_MSGS_TO_BUNDLE)) { | 542 | HTC_MIN_HTC_MSGS_TO_BUNDLE)) { |
529 | int temp1 = 0, temp2 = 0; | 543 | int temp1 = 0, temp2 = 0; |
530 | 544 | ||
531 | htc_issue_send_bundle(endpoint, &txq, | 545 | ath6kl_htc_tx_bundle(endpoint, &txq, |
532 | &temp1, &temp2); | 546 | &temp1, &temp2); |
533 | bundle_sent += temp1; | 547 | bundle_sent += temp1; |
534 | n_pkts_bundle += temp2; | 548 | n_pkts_bundle += temp2; |
535 | } | 549 | } |
@@ -541,9 +555,9 @@ static void htc_tx_from_ep_txq(struct htc_target *target, | |||
541 | list); | 555 | list); |
542 | list_del(&packet->list); | 556 | list_del(&packet->list); |
543 | 557 | ||
544 | htc_prep_send_pkt(packet, packet->info.tx.flags, | 558 | ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags, |
545 | 0, packet->info.tx.seqno); | 559 | 0, packet->info.tx.seqno); |
546 | htc_issue_send(target, packet); | 560 | ath6kl_htc_tx_issue(target, packet); |
547 | } | 561 | } |
548 | 562 | ||
549 | spin_lock_bh(&target->tx_lock); | 563 | spin_lock_bh(&target->tx_lock); |
@@ -556,9 +570,9 @@ static void htc_tx_from_ep_txq(struct htc_target *target, | |||
556 | spin_unlock_bh(&target->tx_lock); | 570 | spin_unlock_bh(&target->tx_lock); |
557 | } | 571 | } |
558 | 572 | ||
559 | static bool htc_try_send(struct htc_target *target, | 573 | static bool ath6kl_htc_tx_try(struct htc_target *target, |
560 | struct htc_endpoint *endpoint, | 574 | struct htc_endpoint *endpoint, |
561 | struct htc_packet *tx_pkt) | 575 | struct htc_packet *tx_pkt) |
562 | { | 576 | { |
563 | struct htc_ep_callbacks ep_cb; | 577 | struct htc_ep_callbacks ep_cb; |
564 | int txq_depth; | 578 | int txq_depth; |
@@ -594,7 +608,7 @@ static bool htc_try_send(struct htc_target *target, | |||
594 | list_add_tail(&tx_pkt->list, &endpoint->txq); | 608 | list_add_tail(&tx_pkt->list, &endpoint->txq); |
595 | spin_unlock_bh(&target->tx_lock); | 609 | spin_unlock_bh(&target->tx_lock); |
596 | 610 | ||
597 | htc_tx_from_ep_txq(target, endpoint); | 611 | ath6kl_htc_tx_from_queue(target, endpoint); |
598 | 612 | ||
599 | return true; | 613 | return true; |
600 | } | 614 | } |
@@ -628,7 +642,7 @@ static void htc_chk_ep_txq(struct htc_target *target) | |||
628 | * chance to reclaim credits from lower priority | 642 | * chance to reclaim credits from lower priority |
629 | * ones. | 643 | * ones. |
630 | */ | 644 | */ |
631 | htc_tx_from_ep_txq(target, endpoint); | 645 | ath6kl_htc_tx_from_queue(target, endpoint); |
632 | spin_lock_bh(&target->tx_lock); | 646 | spin_lock_bh(&target->tx_lock); |
633 | } | 647 | } |
634 | spin_unlock_bh(&target->tx_lock); | 648 | spin_unlock_bh(&target->tx_lock); |
@@ -680,8 +694,8 @@ static int htc_setup_tx_complete(struct htc_target *target) | |||
680 | 694 | ||
681 | /* we want synchronous operation */ | 695 | /* we want synchronous operation */ |
682 | send_pkt->completion = NULL; | 696 | send_pkt->completion = NULL; |
683 | htc_prep_send_pkt(send_pkt, 0, 0, 0); | 697 | ath6kl_htc_tx_prep_pkt(send_pkt, 0, 0, 0); |
684 | status = htc_issue_send(target, send_pkt); | 698 | status = ath6kl_htc_tx_issue(target, send_pkt); |
685 | 699 | ||
686 | if (send_pkt != NULL) | 700 | if (send_pkt != NULL) |
687 | htc_reclaim_txctrl_buf(target, send_pkt); | 701 | htc_reclaim_txctrl_buf(target, send_pkt); |
@@ -733,7 +747,7 @@ int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet) | |||
733 | 747 | ||
734 | endpoint = &target->endpoint[packet->endpoint]; | 748 | endpoint = &target->endpoint[packet->endpoint]; |
735 | 749 | ||
736 | if (!htc_try_send(target, endpoint, packet)) { | 750 | if (!ath6kl_htc_tx_try(target, endpoint, packet)) { |
737 | packet->status = (target->htc_flags & HTC_OP_STATE_STOPPING) ? | 751 | packet->status = (target->htc_flags & HTC_OP_STATE_STOPPING) ? |
738 | -ECANCELED : -ENOSPC; | 752 | -ECANCELED : -ENOSPC; |
739 | INIT_LIST_HEAD(&queue); | 753 | INIT_LIST_HEAD(&queue); |
@@ -846,8 +860,8 @@ void ath6kl_htc_indicate_activity_change(struct htc_target *target, | |||
846 | 860 | ||
847 | /* HTC Rx */ | 861 | /* HTC Rx */ |
848 | 862 | ||
849 | static inline void htc_update_rx_stats(struct htc_endpoint *endpoint, | 863 | static inline void ath6kl_htc_rx_update_stats(struct htc_endpoint *endpoint, |
850 | int n_look_ahds) | 864 | int n_look_ahds) |
851 | { | 865 | { |
852 | endpoint->ep_st.rx_pkts++; | 866 | endpoint->ep_st.rx_pkts++; |
853 | if (n_look_ahds == 1) | 867 | if (n_look_ahds == 1) |
@@ -894,8 +908,9 @@ static void reclaim_rx_ctrl_buf(struct htc_target *target, | |||
894 | spin_unlock_bh(&target->htc_lock); | 908 | spin_unlock_bh(&target->htc_lock); |
895 | } | 909 | } |
896 | 910 | ||
897 | static int dev_rx_pkt(struct htc_target *target, struct htc_packet *packet, | 911 | static int ath6kl_htc_rx_packet(struct htc_target *target, |
898 | u32 rx_len) | 912 | struct htc_packet *packet, |
913 | u32 rx_len) | ||
899 | { | 914 | { |
900 | struct ath6kl_device *dev = target->dev; | 915 | struct ath6kl_device *dev = target->dev; |
901 | u32 padded_len; | 916 | u32 padded_len; |
@@ -929,9 +944,9 @@ static int dev_rx_pkt(struct htc_target *target, struct htc_packet *packet, | |||
929 | * "hint" that there are more single-packets to fetch | 944 | * "hint" that there are more single-packets to fetch |
930 | * on this endpoint. | 945 | * on this endpoint. |
931 | */ | 946 | */ |
932 | static void set_rxpkt_indication_flag(u32 lk_ahd, | 947 | static void ath6kl_htc_rx_set_indicate(u32 lk_ahd, |
933 | struct htc_endpoint *endpoint, | 948 | struct htc_endpoint *endpoint, |
934 | struct htc_packet *packet) | 949 | struct htc_packet *packet) |
935 | { | 950 | { |
936 | struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)&lk_ahd; | 951 | struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)&lk_ahd; |
937 | 952 | ||
@@ -942,7 +957,7 @@ static void set_rxpkt_indication_flag(u32 lk_ahd, | |||
942 | } | 957 | } |
943 | } | 958 | } |
944 | 959 | ||
945 | static void chk_rx_water_mark(struct htc_endpoint *endpoint) | 960 | static void ath6kl_htc_rx_chk_water_mark(struct htc_endpoint *endpoint) |
946 | { | 961 | { |
947 | struct htc_ep_callbacks ep_cb = endpoint->ep_cb; | 962 | struct htc_ep_callbacks ep_cb = endpoint->ep_cb; |
948 | 963 | ||
@@ -959,8 +974,9 @@ static void chk_rx_water_mark(struct htc_endpoint *endpoint) | |||
959 | } | 974 | } |
960 | 975 | ||
961 | /* This function is called with rx_lock held */ | 976 | /* This function is called with rx_lock held */ |
962 | static int htc_setup_rxpkts(struct htc_target *target, struct htc_endpoint *ep, | 977 | static int ath6kl_htc_rx_setup(struct htc_target *target, |
963 | u32 *lk_ahds, struct list_head *queue, int n_msg) | 978 | struct htc_endpoint *ep, |
979 | u32 *lk_ahds, struct list_head *queue, int n_msg) | ||
964 | { | 980 | { |
965 | struct htc_packet *packet; | 981 | struct htc_packet *packet; |
966 | /* FIXME: type of lk_ahds can't be right */ | 982 | /* FIXME: type of lk_ahds can't be right */ |
@@ -1060,10 +1076,10 @@ static int htc_setup_rxpkts(struct htc_target *target, struct htc_endpoint *ep, | |||
1060 | return status; | 1076 | return status; |
1061 | } | 1077 | } |
1062 | 1078 | ||
1063 | static int alloc_and_prep_rxpkts(struct htc_target *target, | 1079 | static int ath6kl_htc_rx_alloc(struct htc_target *target, |
1064 | u32 lk_ahds[], int msg, | 1080 | u32 lk_ahds[], int msg, |
1065 | struct htc_endpoint *endpoint, | 1081 | struct htc_endpoint *endpoint, |
1066 | struct list_head *queue) | 1082 | struct list_head *queue) |
1067 | { | 1083 | { |
1068 | int status = 0; | 1084 | int status = 0; |
1069 | struct htc_packet *packet, *tmp_pkt; | 1085 | struct htc_packet *packet, *tmp_pkt; |
@@ -1129,8 +1145,8 @@ static int alloc_and_prep_rxpkts(struct htc_target *target, | |||
1129 | n_msg = 1; | 1145 | n_msg = 1; |
1130 | 1146 | ||
1131 | /* Setup packet buffers for each message */ | 1147 | /* Setup packet buffers for each message */ |
1132 | status = htc_setup_rxpkts(target, endpoint, &lk_ahds[i], queue, | 1148 | status = ath6kl_htc_rx_setup(target, endpoint, &lk_ahds[i], |
1133 | n_msg); | 1149 | queue, n_msg); |
1134 | 1150 | ||
1135 | /* | 1151 | /* |
1136 | * This is due to unavailabilty of buffers to rx entire data. | 1152 | * This is due to unavailabilty of buffers to rx entire data. |
@@ -1176,9 +1192,9 @@ static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets) | |||
1176 | packets->act_len + HTC_HDR_LENGTH); | 1192 | packets->act_len + HTC_HDR_LENGTH); |
1177 | 1193 | ||
1178 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, | 1194 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, |
1179 | "Unexpected ENDPOINT 0 Message", | 1195 | "Unexpected ENDPOINT 0 Message", "", |
1180 | packets->buf - HTC_HDR_LENGTH, | 1196 | packets->buf - HTC_HDR_LENGTH, |
1181 | packets->act_len + HTC_HDR_LENGTH); | 1197 | packets->act_len + HTC_HDR_LENGTH); |
1182 | } | 1198 | } |
1183 | 1199 | ||
1184 | htc_reclaim_rxbuf(context, packets, &context->endpoint[0]); | 1200 | htc_reclaim_rxbuf(context, packets, &context->endpoint[0]); |
@@ -1312,7 +1328,7 @@ static int htc_parse_trailer(struct htc_target *target, | |||
1312 | memcpy((u8 *)&next_lk_ahds[0], lk_ahd->lk_ahd, 4); | 1328 | memcpy((u8 *)&next_lk_ahds[0], lk_ahd->lk_ahd, 4); |
1313 | 1329 | ||
1314 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Next Look Ahead", | 1330 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Next Look Ahead", |
1315 | next_lk_ahds, 4); | 1331 | "", next_lk_ahds, 4); |
1316 | 1332 | ||
1317 | *n_lk_ahds = 1; | 1333 | *n_lk_ahds = 1; |
1318 | } | 1334 | } |
@@ -1331,7 +1347,7 @@ static int htc_parse_trailer(struct htc_target *target, | |||
1331 | (struct htc_bundle_lkahd_rpt *) record_buf; | 1347 | (struct htc_bundle_lkahd_rpt *) record_buf; |
1332 | 1348 | ||
1333 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Bundle lk_ahd", | 1349 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Bundle lk_ahd", |
1334 | record_buf, record->len); | 1350 | "", record_buf, record->len); |
1335 | 1351 | ||
1336 | for (i = 0; i < len; i++) { | 1352 | for (i = 0; i < len; i++) { |
1337 | memcpy((u8 *)&next_lk_ahds[i], | 1353 | memcpy((u8 *)&next_lk_ahds[i], |
@@ -1364,7 +1380,8 @@ static int htc_proc_trailer(struct htc_target *target, | |||
1364 | 1380 | ||
1365 | ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "+htc_proc_trailer (len:%d)\n", len); | 1381 | ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "+htc_proc_trailer (len:%d)\n", len); |
1366 | 1382 | ||
1367 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", buf, len); | 1383 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", "", |
1384 | buf, len); | ||
1368 | 1385 | ||
1369 | orig_buf = buf; | 1386 | orig_buf = buf; |
1370 | orig_len = len; | 1387 | orig_len = len; |
@@ -1402,14 +1419,14 @@ static int htc_proc_trailer(struct htc_target *target, | |||
1402 | 1419 | ||
1403 | if (status) | 1420 | if (status) |
1404 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD Recv Trailer", | 1421 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD Recv Trailer", |
1405 | orig_buf, orig_len); | 1422 | "", orig_buf, orig_len); |
1406 | 1423 | ||
1407 | return status; | 1424 | return status; |
1408 | } | 1425 | } |
1409 | 1426 | ||
1410 | static int htc_proc_rxhdr(struct htc_target *target, | 1427 | static int ath6kl_htc_rx_process_hdr(struct htc_target *target, |
1411 | struct htc_packet *packet, | 1428 | struct htc_packet *packet, |
1412 | u32 *next_lkahds, int *n_lkahds) | 1429 | u32 *next_lkahds, int *n_lkahds) |
1413 | { | 1430 | { |
1414 | int status = 0; | 1431 | int status = 0; |
1415 | u16 payload_len; | 1432 | u16 payload_len; |
@@ -1419,8 +1436,8 @@ static int htc_proc_rxhdr(struct htc_target *target, | |||
1419 | if (n_lkahds != NULL) | 1436 | if (n_lkahds != NULL) |
1420 | *n_lkahds = 0; | 1437 | *n_lkahds = 0; |
1421 | 1438 | ||
1422 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", packet->buf, | 1439 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", "htc ", |
1423 | packet->act_len); | 1440 | packet->buf, packet->act_len); |
1424 | 1441 | ||
1425 | /* | 1442 | /* |
1426 | * NOTE: we cannot assume the alignment of buf, so we use the safe | 1443 | * NOTE: we cannot assume the alignment of buf, so we use the safe |
@@ -1461,12 +1478,12 @@ static int htc_proc_rxhdr(struct htc_target *target, | |||
1461 | } | 1478 | } |
1462 | 1479 | ||
1463 | if (lk_ahd != packet->info.rx.exp_hdr) { | 1480 | if (lk_ahd != packet->info.rx.exp_hdr) { |
1464 | ath6kl_err("htc_proc_rxhdr, lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n", | 1481 | ath6kl_err("%s(): lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n", |
1465 | packet, packet->info.rx.rx_flags); | 1482 | __func__, packet, packet->info.rx.rx_flags); |
1466 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Expected Message lk_ahd", | 1483 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Expected Message lk_ahd", |
1467 | &packet->info.rx.exp_hdr, 4); | 1484 | "", &packet->info.rx.exp_hdr, 4); |
1468 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Current Frame Header", | 1485 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Current Frame Header", |
1469 | (u8 *)&lk_ahd, sizeof(lk_ahd)); | 1486 | "", (u8 *)&lk_ahd, sizeof(lk_ahd)); |
1470 | status = -ENOMEM; | 1487 | status = -ENOMEM; |
1471 | goto fail_rx; | 1488 | goto fail_rx; |
1472 | } | 1489 | } |
@@ -1474,8 +1491,8 @@ static int htc_proc_rxhdr(struct htc_target *target, | |||
1474 | if (htc_hdr->flags & HTC_FLG_RX_TRAILER) { | 1491 | if (htc_hdr->flags & HTC_FLG_RX_TRAILER) { |
1475 | if (htc_hdr->ctrl[0] < sizeof(struct htc_record_hdr) || | 1492 | if (htc_hdr->ctrl[0] < sizeof(struct htc_record_hdr) || |
1476 | htc_hdr->ctrl[0] > payload_len) { | 1493 | htc_hdr->ctrl[0] > payload_len) { |
1477 | ath6kl_err("htc_proc_rxhdr, invalid hdr (payload len should be :%d, CB[0] is:%d)\n", | 1494 | ath6kl_err("%s(): invalid hdr (payload len should be :%d, CB[0] is:%d)\n", |
1478 | payload_len, htc_hdr->ctrl[0]); | 1495 | __func__, payload_len, htc_hdr->ctrl[0]); |
1479 | status = -ENOMEM; | 1496 | status = -ENOMEM; |
1480 | goto fail_rx; | 1497 | goto fail_rx; |
1481 | } | 1498 | } |
@@ -1502,20 +1519,20 @@ static int htc_proc_rxhdr(struct htc_target *target, | |||
1502 | fail_rx: | 1519 | fail_rx: |
1503 | if (status) | 1520 | if (status) |
1504 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD HTC Recv PKT", | 1521 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD HTC Recv PKT", |
1505 | packet->buf, | 1522 | "", packet->buf, |
1506 | packet->act_len < 256 ? packet->act_len : 256); | 1523 | packet->act_len < 256 ? packet->act_len : 256); |
1507 | else { | 1524 | else { |
1508 | if (packet->act_len > 0) | 1525 | if (packet->act_len > 0) |
1509 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, | 1526 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, |
1510 | "HTC - Application Msg", | 1527 | "HTC - Application Msg", "", |
1511 | packet->buf, packet->act_len); | 1528 | packet->buf, packet->act_len); |
1512 | } | 1529 | } |
1513 | 1530 | ||
1514 | return status; | 1531 | return status; |
1515 | } | 1532 | } |
1516 | 1533 | ||
1517 | static void do_rx_completion(struct htc_endpoint *endpoint, | 1534 | static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint, |
1518 | struct htc_packet *packet) | 1535 | struct htc_packet *packet) |
1519 | { | 1536 | { |
1520 | ath6kl_dbg(ATH6KL_DBG_HTC_RECV, | 1537 | ath6kl_dbg(ATH6KL_DBG_HTC_RECV, |
1521 | "htc calling ep %d recv callback on packet 0x%p\n", | 1538 | "htc calling ep %d recv callback on packet 0x%p\n", |
@@ -1523,10 +1540,10 @@ static void do_rx_completion(struct htc_endpoint *endpoint, | |||
1523 | endpoint->ep_cb.rx(endpoint->target, packet); | 1540 | endpoint->ep_cb.rx(endpoint->target, packet); |
1524 | } | 1541 | } |
1525 | 1542 | ||
1526 | static int htc_issue_rxpkt_bundle(struct htc_target *target, | 1543 | static int ath6kl_htc_rx_bundle(struct htc_target *target, |
1527 | struct list_head *rxq, | 1544 | struct list_head *rxq, |
1528 | struct list_head *sync_compq, | 1545 | struct list_head *sync_compq, |
1529 | int *n_pkt_fetched, bool part_bundle) | 1546 | int *n_pkt_fetched, bool part_bundle) |
1530 | { | 1547 | { |
1531 | struct hif_scatter_req *scat_req; | 1548 | struct hif_scatter_req *scat_req; |
1532 | struct htc_packet *packet; | 1549 | struct htc_packet *packet; |
@@ -1548,15 +1565,15 @@ static int htc_issue_rxpkt_bundle(struct htc_target *target, | |||
1548 | * This would only happen if the target ignored our max | 1565 | * This would only happen if the target ignored our max |
1549 | * bundle limit. | 1566 | * bundle limit. |
1550 | */ | 1567 | */ |
1551 | ath6kl_warn("htc_issue_rxpkt_bundle : partial bundle detected num:%d , %d\n", | 1568 | ath6kl_warn("%s(): partial bundle detected num:%d , %d\n", |
1552 | get_queue_depth(rxq), n_scat_pkt); | 1569 | __func__, get_queue_depth(rxq), n_scat_pkt); |
1553 | } | 1570 | } |
1554 | 1571 | ||
1555 | len = 0; | 1572 | len = 0; |
1556 | 1573 | ||
1557 | ath6kl_dbg(ATH6KL_DBG_HTC_RECV, | 1574 | ath6kl_dbg(ATH6KL_DBG_HTC_RECV, |
1558 | "htc_issue_rxpkt_bundle (numpackets: %d , actual : %d)\n", | 1575 | "%s(): (numpackets: %d , actual : %d)\n", |
1559 | get_queue_depth(rxq), n_scat_pkt); | 1576 | __func__, get_queue_depth(rxq), n_scat_pkt); |
1560 | 1577 | ||
1561 | scat_req = hif_scatter_req_get(target->dev->ar); | 1578 | scat_req = hif_scatter_req_get(target->dev->ar); |
1562 | 1579 | ||
@@ -1616,9 +1633,10 @@ fail_rx_pkt: | |||
1616 | return status; | 1633 | return status; |
1617 | } | 1634 | } |
1618 | 1635 | ||
1619 | static int htc_proc_fetched_rxpkts(struct htc_target *target, | 1636 | static int ath6kl_htc_rx_process_packets(struct htc_target *target, |
1620 | struct list_head *comp_pktq, u32 lk_ahds[], | 1637 | struct list_head *comp_pktq, |
1621 | int *n_lk_ahd) | 1638 | u32 lk_ahds[], |
1639 | int *n_lk_ahd) | ||
1622 | { | 1640 | { |
1623 | struct htc_packet *packet, *tmp_pkt; | 1641 | struct htc_packet *packet, *tmp_pkt; |
1624 | struct htc_endpoint *ep; | 1642 | struct htc_endpoint *ep; |
@@ -1629,7 +1647,8 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target, | |||
1629 | ep = &target->endpoint[packet->endpoint]; | 1647 | ep = &target->endpoint[packet->endpoint]; |
1630 | 1648 | ||
1631 | /* process header for each of the recv packet */ | 1649 | /* process header for each of the recv packet */ |
1632 | status = htc_proc_rxhdr(target, packet, lk_ahds, n_lk_ahd); | 1650 | status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds, |
1651 | n_lk_ahd); | ||
1633 | if (status) | 1652 | if (status) |
1634 | return status; | 1653 | return status; |
1635 | 1654 | ||
@@ -1639,8 +1658,8 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target, | |||
1639 | * based on the lookahead. | 1658 | * based on the lookahead. |
1640 | */ | 1659 | */ |
1641 | if (*n_lk_ahd > 0) | 1660 | if (*n_lk_ahd > 0) |
1642 | set_rxpkt_indication_flag(lk_ahds[0], | 1661 | ath6kl_htc_rx_set_indicate(lk_ahds[0], |
1643 | ep, packet); | 1662 | ep, packet); |
1644 | } else | 1663 | } else |
1645 | /* | 1664 | /* |
1646 | * Packets in a bundle automatically have | 1665 | * Packets in a bundle automatically have |
@@ -1649,20 +1668,20 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target, | |||
1649 | packet->info.rx.indicat_flags |= | 1668 | packet->info.rx.indicat_flags |= |
1650 | HTC_RX_FLAGS_INDICATE_MORE_PKTS; | 1669 | HTC_RX_FLAGS_INDICATE_MORE_PKTS; |
1651 | 1670 | ||
1652 | htc_update_rx_stats(ep, *n_lk_ahd); | 1671 | ath6kl_htc_rx_update_stats(ep, *n_lk_ahd); |
1653 | 1672 | ||
1654 | if (packet->info.rx.rx_flags & HTC_RX_PKT_PART_OF_BUNDLE) | 1673 | if (packet->info.rx.rx_flags & HTC_RX_PKT_PART_OF_BUNDLE) |
1655 | ep->ep_st.rx_bundl += 1; | 1674 | ep->ep_st.rx_bundl += 1; |
1656 | 1675 | ||
1657 | do_rx_completion(ep, packet); | 1676 | ath6kl_htc_rx_complete(ep, packet); |
1658 | } | 1677 | } |
1659 | 1678 | ||
1660 | return status; | 1679 | return status; |
1661 | } | 1680 | } |
1662 | 1681 | ||
1663 | static int htc_fetch_rxpkts(struct htc_target *target, | 1682 | static int ath6kl_htc_rx_fetch(struct htc_target *target, |
1664 | struct list_head *rx_pktq, | 1683 | struct list_head *rx_pktq, |
1665 | struct list_head *comp_pktq) | 1684 | struct list_head *comp_pktq) |
1666 | { | 1685 | { |
1667 | int fetched_pkts; | 1686 | int fetched_pkts; |
1668 | bool part_bundle = false; | 1687 | bool part_bundle = false; |
@@ -1678,10 +1697,10 @@ static int htc_fetch_rxpkts(struct htc_target *target, | |||
1678 | * bundle transfer and recv bundling is | 1697 | * bundle transfer and recv bundling is |
1679 | * allowed. | 1698 | * allowed. |
1680 | */ | 1699 | */ |
1681 | status = htc_issue_rxpkt_bundle(target, rx_pktq, | 1700 | status = ath6kl_htc_rx_bundle(target, rx_pktq, |
1682 | comp_pktq, | 1701 | comp_pktq, |
1683 | &fetched_pkts, | 1702 | &fetched_pkts, |
1684 | part_bundle); | 1703 | part_bundle); |
1685 | if (status) | 1704 | if (status) |
1686 | return status; | 1705 | return status; |
1687 | 1706 | ||
@@ -1710,7 +1729,8 @@ static int htc_fetch_rxpkts(struct htc_target *target, | |||
1710 | HTC_RX_PKT_IGNORE_LOOKAHEAD; | 1729 | HTC_RX_PKT_IGNORE_LOOKAHEAD; |
1711 | 1730 | ||
1712 | /* go fetch the packet */ | 1731 | /* go fetch the packet */ |
1713 | status = dev_rx_pkt(target, packet, packet->act_len); | 1732 | status = ath6kl_htc_rx_packet(target, packet, |
1733 | packet->act_len); | ||
1714 | if (status) | 1734 | if (status) |
1715 | return status; | 1735 | return status; |
1716 | 1736 | ||
@@ -1764,9 +1784,9 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, | |||
1764 | * Try to allocate as many HTC RX packets indicated by the | 1784 | * Try to allocate as many HTC RX packets indicated by the |
1765 | * look_aheads. | 1785 | * look_aheads. |
1766 | */ | 1786 | */ |
1767 | status = alloc_and_prep_rxpkts(target, look_aheads, | 1787 | status = ath6kl_htc_rx_alloc(target, look_aheads, |
1768 | num_look_ahead, endpoint, | 1788 | num_look_ahead, endpoint, |
1769 | &rx_pktq); | 1789 | &rx_pktq); |
1770 | if (status) | 1790 | if (status) |
1771 | break; | 1791 | break; |
1772 | 1792 | ||
@@ -1781,14 +1801,15 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, | |||
1781 | 1801 | ||
1782 | num_look_ahead = 0; | 1802 | num_look_ahead = 0; |
1783 | 1803 | ||
1784 | status = htc_fetch_rxpkts(target, &rx_pktq, &comp_pktq); | 1804 | status = ath6kl_htc_rx_fetch(target, &rx_pktq, &comp_pktq); |
1785 | 1805 | ||
1786 | if (!status) | 1806 | if (!status) |
1787 | chk_rx_water_mark(endpoint); | 1807 | ath6kl_htc_rx_chk_water_mark(endpoint); |
1788 | 1808 | ||
1789 | /* Process fetched packets */ | 1809 | /* Process fetched packets */ |
1790 | status = htc_proc_fetched_rxpkts(target, &comp_pktq, | 1810 | status = ath6kl_htc_rx_process_packets(target, &comp_pktq, |
1791 | look_aheads, &num_look_ahead); | 1811 | look_aheads, |
1812 | &num_look_ahead); | ||
1792 | 1813 | ||
1793 | if (!num_look_ahead || status) | 1814 | if (!num_look_ahead || status) |
1794 | break; | 1815 | break; |
@@ -1881,14 +1902,14 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target) | |||
1881 | packet->completion = NULL; | 1902 | packet->completion = NULL; |
1882 | 1903 | ||
1883 | /* get the message from the device, this will block */ | 1904 | /* get the message from the device, this will block */ |
1884 | if (dev_rx_pkt(target, packet, packet->act_len)) | 1905 | if (ath6kl_htc_rx_packet(target, packet, packet->act_len)) |
1885 | goto fail_ctrl_rx; | 1906 | goto fail_ctrl_rx; |
1886 | 1907 | ||
1887 | /* process receive header */ | 1908 | /* process receive header */ |
1888 | packet->status = htc_proc_rxhdr(target, packet, NULL, NULL); | 1909 | packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL); |
1889 | 1910 | ||
1890 | if (packet->status) { | 1911 | if (packet->status) { |
1891 | ath6kl_err("htc_wait_for_ctrl_msg, htc_proc_rxhdr failed (status = %d)\n", | 1912 | ath6kl_err("htc_wait_for_ctrl_msg, ath6kl_htc_rx_process_hdr failed (status = %d)\n", |
1892 | packet->status); | 1913 | packet->status); |
1893 | goto fail_ctrl_rx; | 1914 | goto fail_ctrl_rx; |
1894 | } | 1915 | } |
@@ -1935,7 +1956,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, | |||
1935 | list_for_each_entry_safe(packet, tmp_pkt, pkt_queue, list) { | 1956 | list_for_each_entry_safe(packet, tmp_pkt, pkt_queue, list) { |
1936 | packet->status = -ECANCELED; | 1957 | packet->status = -ECANCELED; |
1937 | list_del(&packet->list); | 1958 | list_del(&packet->list); |
1938 | do_rx_completion(endpoint, packet); | 1959 | ath6kl_htc_rx_complete(endpoint, packet); |
1939 | } | 1960 | } |
1940 | 1961 | ||
1941 | return status; | 1962 | return status; |
@@ -2034,8 +2055,8 @@ int ath6kl_htc_conn_service(struct htc_target *target, | |||
2034 | 2055 | ||
2035 | /* we want synchronous operation */ | 2056 | /* we want synchronous operation */ |
2036 | tx_pkt->completion = NULL; | 2057 | tx_pkt->completion = NULL; |
2037 | htc_prep_send_pkt(tx_pkt, 0, 0, 0); | 2058 | ath6kl_htc_tx_prep_pkt(tx_pkt, 0, 0, 0); |
2038 | status = htc_issue_send(target, tx_pkt); | 2059 | status = ath6kl_htc_tx_issue(target, tx_pkt); |
2039 | 2060 | ||
2040 | if (status) | 2061 | if (status) |
2041 | goto fail_tx; | 2062 | goto fail_tx; |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 9d10322eac41..c1d2366704b5 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -15,6 +15,8 @@ | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/moduleparam.h> | ||
19 | #include <linux/of.h> | ||
18 | #include <linux/mmc/sdio_func.h> | 20 | #include <linux/mmc/sdio_func.h> |
19 | #include "core.h" | 21 | #include "core.h" |
20 | #include "cfg80211.h" | 22 | #include "cfg80211.h" |
@@ -23,8 +25,10 @@ | |||
23 | #include "hif-ops.h" | 25 | #include "hif-ops.h" |
24 | 26 | ||
25 | unsigned int debug_mask; | 27 | unsigned int debug_mask; |
28 | static unsigned int testmode; | ||
26 | 29 | ||
27 | module_param(debug_mask, uint, 0644); | 30 | module_param(debug_mask, uint, 0644); |
31 | module_param(testmode, uint, 0644); | ||
28 | 32 | ||
29 | /* | 33 | /* |
30 | * Include definitions here that can be used to tune the WLAN module | 34 | * Include definitions here that can be used to tune the WLAN module |
@@ -53,12 +57,6 @@ module_param(debug_mask, uint, 0644); | |||
53 | 57 | ||
54 | #define CONFIG_AR600x_DEBUG_UART_TX_PIN 8 | 58 | #define CONFIG_AR600x_DEBUG_UART_TX_PIN 8 |
55 | 59 | ||
56 | enum addr_type { | ||
57 | DATASET_PATCH_ADDR, | ||
58 | APP_LOAD_ADDR, | ||
59 | APP_START_OVERRIDE_ADDR, | ||
60 | }; | ||
61 | |||
62 | #define ATH6KL_DATA_OFFSET 64 | 60 | #define ATH6KL_DATA_OFFSET 64 |
63 | struct sk_buff *ath6kl_buf_alloc(int size) | 61 | struct sk_buff *ath6kl_buf_alloc(int size) |
64 | { | 62 | { |
@@ -67,7 +65,7 @@ struct sk_buff *ath6kl_buf_alloc(int size) | |||
67 | 65 | ||
68 | /* Add chacheline space at front and back of buffer */ | 66 | /* Add chacheline space at front and back of buffer */ |
69 | reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + | 67 | reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + |
70 | sizeof(struct htc_packet); | 68 | sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES; |
71 | skb = dev_alloc_skb(size + reserved); | 69 | skb = dev_alloc_skb(size + reserved); |
72 | 70 | ||
73 | if (skb) | 71 | if (skb) |
@@ -85,7 +83,7 @@ void ath6kl_init_profile_info(struct ath6kl *ar) | |||
85 | ar->prwise_crypto = NONE_CRYPT; | 83 | ar->prwise_crypto = NONE_CRYPT; |
86 | ar->prwise_crypto_len = 0; | 84 | ar->prwise_crypto_len = 0; |
87 | ar->grp_crypto = NONE_CRYPT; | 85 | ar->grp_crypto = NONE_CRYPT; |
88 | ar->grp_crpto_len = 0; | 86 | ar->grp_crypto_len = 0; |
89 | memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list)); | 87 | memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list)); |
90 | memset(ar->req_bssid, 0, sizeof(ar->req_bssid)); | 88 | memset(ar->req_bssid, 0, sizeof(ar->req_bssid)); |
91 | memset(ar->bssid, 0, sizeof(ar->bssid)); | 89 | memset(ar->bssid, 0, sizeof(ar->bssid)); |
@@ -108,17 +106,6 @@ static u8 ath6kl_get_fw_iftype(struct ath6kl *ar) | |||
108 | } | 106 | } |
109 | } | 107 | } |
110 | 108 | ||
111 | static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar, | ||
112 | u32 item_offset) | ||
113 | { | ||
114 | u32 addr = 0; | ||
115 | |||
116 | if (ar->target_type == TARGET_TYPE_AR6003) | ||
117 | addr = ATH6KL_HI_START_ADDR + item_offset; | ||
118 | |||
119 | return addr; | ||
120 | } | ||
121 | |||
122 | static int ath6kl_set_host_app_area(struct ath6kl *ar) | 109 | static int ath6kl_set_host_app_area(struct ath6kl *ar) |
123 | { | 110 | { |
124 | u32 address, data; | 111 | u32 address, data; |
@@ -127,16 +114,15 @@ static int ath6kl_set_host_app_area(struct ath6kl *ar) | |||
127 | /* Fetch the address of the host_app_area_s | 114 | /* Fetch the address of the host_app_area_s |
128 | * instance in the host interest area */ | 115 | * instance in the host interest area */ |
129 | address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest)); | 116 | address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest)); |
130 | address = TARG_VTOP(address); | 117 | address = TARG_VTOP(ar->target_type, address); |
131 | 118 | ||
132 | if (ath6kl_read_reg_diag(ar, &address, &data)) | 119 | if (ath6kl_diag_read32(ar, address, &data)) |
133 | return -EIO; | 120 | return -EIO; |
134 | 121 | ||
135 | address = TARG_VTOP(data); | 122 | address = TARG_VTOP(ar->target_type, data); |
136 | host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION; | 123 | host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION; |
137 | if (ath6kl_access_datadiag(ar, address, | 124 | if (ath6kl_diag_write(ar, address, (u8 *) &host_app_area, |
138 | (u8 *)&host_app_area, | 125 | sizeof(struct host_app_area))) |
139 | sizeof(struct host_app_area), false)) | ||
140 | return -EIO; | 126 | return -EIO; |
141 | 127 | ||
142 | return 0; | 128 | return 0; |
@@ -290,6 +276,7 @@ static void ath6kl_init_control_info(struct ath6kl *ar) | |||
290 | memset(&ar->sc_params, 0, sizeof(ar->sc_params)); | 276 | memset(&ar->sc_params, 0, sizeof(ar->sc_params)); |
291 | ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT; | 277 | ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT; |
292 | ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS; | 278 | ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS; |
279 | ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; | ||
293 | 280 | ||
294 | memset((u8 *)ar->sta_list, 0, | 281 | memset((u8 *)ar->sta_list, 0, |
295 | AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); | 282 | AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); |
@@ -370,10 +357,10 @@ static void ath6kl_dump_target_assert_info(struct ath6kl *ar) | |||
370 | 357 | ||
371 | /* the reg dump pointer is copied to the host interest area */ | 358 | /* the reg dump pointer is copied to the host interest area */ |
372 | address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state)); | 359 | address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state)); |
373 | address = TARG_VTOP(address); | 360 | address = TARG_VTOP(ar->target_type, address); |
374 | 361 | ||
375 | /* read RAM location through diagnostic window */ | 362 | /* read RAM location through diagnostic window */ |
376 | status = ath6kl_read_reg_diag(ar, &address, ®dump_loc); | 363 | status = ath6kl_diag_read32(ar, address, ®dump_loc); |
377 | 364 | ||
378 | if (status || !regdump_loc) { | 365 | if (status || !regdump_loc) { |
379 | ath6kl_err("failed to get ptr to register dump area\n"); | 366 | ath6kl_err("failed to get ptr to register dump area\n"); |
@@ -382,15 +369,11 @@ static void ath6kl_dump_target_assert_info(struct ath6kl *ar) | |||
382 | 369 | ||
383 | ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n", | 370 | ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n", |
384 | regdump_loc); | 371 | regdump_loc); |
385 | 372 | regdump_loc = TARG_VTOP(ar->target_type, regdump_loc); | |
386 | regdump_loc = TARG_VTOP(regdump_loc); | ||
387 | 373 | ||
388 | /* fetch register dump data */ | 374 | /* fetch register dump data */ |
389 | status = ath6kl_access_datadiag(ar, | 375 | status = ath6kl_diag_read(ar, regdump_loc, (u8 *)®dump_val[0], |
390 | regdump_loc, | 376 | REG_DUMP_COUNT_AR6003 * (sizeof(u32))); |
391 | (u8 *)®dump_val[0], | ||
392 | REG_DUMP_COUNT_AR6003 * (sizeof(u32)), | ||
393 | true); | ||
394 | 377 | ||
395 | if (status) { | 378 | if (status) { |
396 | ath6kl_err("failed to get register dump\n"); | 379 | ath6kl_err("failed to get register dump\n"); |
@@ -416,6 +399,7 @@ void ath6kl_target_failure(struct ath6kl *ar) | |||
416 | static int ath6kl_target_config_wlan_params(struct ath6kl *ar) | 399 | static int ath6kl_target_config_wlan_params(struct ath6kl *ar) |
417 | { | 400 | { |
418 | int status = 0; | 401 | int status = 0; |
402 | int ret; | ||
419 | 403 | ||
420 | /* | 404 | /* |
421 | * Configure the device for rx dot11 header rules. "0,0" are the | 405 | * Configure the device for rx dot11 header rules. "0,0" are the |
@@ -460,6 +444,28 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar) | |||
460 | status = -EIO; | 444 | status = -EIO; |
461 | } | 445 | } |
462 | 446 | ||
447 | if (ar->p2p) { | ||
448 | ret = ath6kl_wmi_info_req_cmd(ar->wmi, | ||
449 | P2P_FLAG_CAPABILITIES_REQ | | ||
450 | P2P_FLAG_MACADDR_REQ | | ||
451 | P2P_FLAG_HMODEL_REQ); | ||
452 | if (ret) { | ||
453 | ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P " | ||
454 | "capabilities (%d) - assuming P2P not " | ||
455 | "supported\n", ret); | ||
456 | ar->p2p = 0; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | if (ar->p2p) { | ||
461 | /* Enable Probe Request reporting for P2P */ | ||
462 | ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, true); | ||
463 | if (ret) { | ||
464 | ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe " | ||
465 | "Request reporting (%d)\n", ret); | ||
466 | } | ||
467 | } | ||
468 | |||
463 | return status; | 469 | return status; |
464 | } | 470 | } |
465 | 471 | ||
@@ -495,6 +501,10 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
495 | 501 | ||
496 | param |= (1 << HI_OPTION_NUM_DEV_SHIFT); | 502 | param |= (1 << HI_OPTION_NUM_DEV_SHIFT); |
497 | param |= (fw_iftype << HI_OPTION_FW_MODE_SHIFT); | 503 | param |= (fw_iftype << HI_OPTION_FW_MODE_SHIFT); |
504 | if (ar->p2p && fw_iftype == HI_OPTION_FW_MODE_BSS_STA) { | ||
505 | param |= HI_OPTION_FW_SUBMODE_P2PDEV << | ||
506 | HI_OPTION_FW_SUBMODE_SHIFT; | ||
507 | } | ||
498 | param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT); | 508 | param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT); |
499 | param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT); | 509 | param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT); |
500 | 510 | ||
@@ -518,29 +528,21 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
518 | * but possible in theory. | 528 | * but possible in theory. |
519 | */ | 529 | */ |
520 | 530 | ||
521 | if (ar->target_type == TARGET_TYPE_AR6003) { | 531 | param = ar->hw.board_ext_data_addr; |
522 | if (ar->version.target_ver == AR6003_REV2_VERSION) { | 532 | ram_reserved_size = ar->hw.reserved_ram_size; |
523 | param = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; | ||
524 | ram_reserved_size = AR6003_REV2_RAM_RESERVE_SIZE; | ||
525 | } else { | ||
526 | param = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; | ||
527 | ram_reserved_size = AR6003_REV3_RAM_RESERVE_SIZE; | ||
528 | } | ||
529 | 533 | ||
530 | if (ath6kl_bmi_write(ar, | 534 | if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, |
531 | ath6kl_get_hi_item_addr(ar, | 535 | HI_ITEM(hi_board_ext_data)), |
532 | HI_ITEM(hi_board_ext_data)), | 536 | (u8 *)¶m, 4) != 0) { |
533 | (u8 *)¶m, 4) != 0) { | 537 | ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n"); |
534 | ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n"); | 538 | return -EIO; |
535 | return -EIO; | 539 | } |
536 | } | 540 | |
537 | if (ath6kl_bmi_write(ar, | 541 | if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, |
538 | ath6kl_get_hi_item_addr(ar, | 542 | HI_ITEM(hi_end_ram_reserve_sz)), |
539 | HI_ITEM(hi_end_ram_reserve_sz)), | 543 | (u8 *)&ram_reserved_size, 4) != 0) { |
540 | (u8 *)&ram_reserved_size, 4) != 0) { | 544 | ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n"); |
541 | ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n"); | 545 | return -EIO; |
542 | return -EIO; | ||
543 | } | ||
544 | } | 546 | } |
545 | 547 | ||
546 | /* set the block size for the target */ | 548 | /* set the block size for the target */ |
@@ -568,6 +570,12 @@ struct ath6kl *ath6kl_core_alloc(struct device *sdev) | |||
568 | ar->wdev = wdev; | 570 | ar->wdev = wdev; |
569 | wdev->iftype = NL80211_IFTYPE_STATION; | 571 | wdev->iftype = NL80211_IFTYPE_STATION; |
570 | 572 | ||
573 | if (ath6kl_debug_init(ar)) { | ||
574 | ath6kl_err("Failed to initialize debugfs\n"); | ||
575 | ath6kl_cfg80211_deinit(ar); | ||
576 | return NULL; | ||
577 | } | ||
578 | |||
571 | dev = alloc_netdev(0, "wlan%d", ether_setup); | 579 | dev = alloc_netdev(0, "wlan%d", ether_setup); |
572 | if (!dev) { | 580 | if (!dev) { |
573 | ath6kl_err("no memory for network device instance\n"); | 581 | ath6kl_err("no memory for network device instance\n"); |
@@ -579,7 +587,6 @@ struct ath6kl *ath6kl_core_alloc(struct device *sdev) | |||
579 | SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); | 587 | SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); |
580 | wdev->netdev = dev; | 588 | wdev->netdev = dev; |
581 | ar->sme_state = SME_DISCONNECTED; | 589 | ar->sme_state = SME_DISCONNECTED; |
582 | ar->auto_auth_stage = AUTH_IDLE; | ||
583 | 590 | ||
584 | init_netdev(dev); | 591 | init_netdev(dev); |
585 | 592 | ||
@@ -611,29 +618,6 @@ int ath6kl_unavail_ev(struct ath6kl *ar) | |||
611 | } | 618 | } |
612 | 619 | ||
613 | /* firmware upload */ | 620 | /* firmware upload */ |
614 | static u32 ath6kl_get_load_address(u32 target_ver, enum addr_type type) | ||
615 | { | ||
616 | WARN_ON(target_ver != AR6003_REV2_VERSION && | ||
617 | target_ver != AR6003_REV3_VERSION); | ||
618 | |||
619 | switch (type) { | ||
620 | case DATASET_PATCH_ADDR: | ||
621 | return (target_ver == AR6003_REV2_VERSION) ? | ||
622 | AR6003_REV2_DATASET_PATCH_ADDRESS : | ||
623 | AR6003_REV3_DATASET_PATCH_ADDRESS; | ||
624 | case APP_LOAD_ADDR: | ||
625 | return (target_ver == AR6003_REV2_VERSION) ? | ||
626 | AR6003_REV2_APP_LOAD_ADDRESS : | ||
627 | 0x1234; | ||
628 | case APP_START_OVERRIDE_ADDR: | ||
629 | return (target_ver == AR6003_REV2_VERSION) ? | ||
630 | AR6003_REV2_APP_START_OVERRIDE : | ||
631 | AR6003_REV3_APP_START_OVERRIDE; | ||
632 | default: | ||
633 | return 0; | ||
634 | } | ||
635 | } | ||
636 | |||
637 | static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, | 621 | static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, |
638 | u8 **fw, size_t *fw_len) | 622 | u8 **fw, size_t *fw_len) |
639 | { | 623 | { |
@@ -655,15 +639,79 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, | |||
655 | return ret; | 639 | return ret; |
656 | } | 640 | } |
657 | 641 | ||
642 | #ifdef CONFIG_OF | ||
643 | static const char *get_target_ver_dir(const struct ath6kl *ar) | ||
644 | { | ||
645 | switch (ar->version.target_ver) { | ||
646 | case AR6003_REV1_VERSION: | ||
647 | return "ath6k/AR6003/hw1.0"; | ||
648 | case AR6003_REV2_VERSION: | ||
649 | return "ath6k/AR6003/hw2.0"; | ||
650 | case AR6003_REV3_VERSION: | ||
651 | return "ath6k/AR6003/hw2.1.1"; | ||
652 | } | ||
653 | ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__, | ||
654 | ar->version.target_ver); | ||
655 | return NULL; | ||
656 | } | ||
657 | |||
658 | /* | ||
659 | * Check the device tree for a board-id and use it to construct | ||
660 | * the pathname to the firmware file. Used (for now) to find a | ||
661 | * fallback to the "bdata.bin" file--typically a symlink to the | ||
662 | * appropriate board-specific file. | ||
663 | */ | ||
664 | static bool check_device_tree(struct ath6kl *ar) | ||
665 | { | ||
666 | static const char *board_id_prop = "atheros,board-id"; | ||
667 | struct device_node *node; | ||
668 | char board_filename[64]; | ||
669 | const char *board_id; | ||
670 | int ret; | ||
671 | |||
672 | for_each_compatible_node(node, NULL, "atheros,ath6kl") { | ||
673 | board_id = of_get_property(node, board_id_prop, NULL); | ||
674 | if (board_id == NULL) { | ||
675 | ath6kl_warn("No \"%s\" property on %s node.\n", | ||
676 | board_id_prop, node->name); | ||
677 | continue; | ||
678 | } | ||
679 | snprintf(board_filename, sizeof(board_filename), | ||
680 | "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id); | ||
681 | |||
682 | ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board, | ||
683 | &ar->fw_board_len); | ||
684 | if (ret) { | ||
685 | ath6kl_err("Failed to get DT board file %s: %d\n", | ||
686 | board_filename, ret); | ||
687 | continue; | ||
688 | } | ||
689 | return true; | ||
690 | } | ||
691 | return false; | ||
692 | } | ||
693 | #else | ||
694 | static bool check_device_tree(struct ath6kl *ar) | ||
695 | { | ||
696 | return false; | ||
697 | } | ||
698 | #endif /* CONFIG_OF */ | ||
699 | |||
658 | static int ath6kl_fetch_board_file(struct ath6kl *ar) | 700 | static int ath6kl_fetch_board_file(struct ath6kl *ar) |
659 | { | 701 | { |
660 | const char *filename; | 702 | const char *filename; |
661 | int ret; | 703 | int ret; |
662 | 704 | ||
705 | if (ar->fw_board != NULL) | ||
706 | return 0; | ||
707 | |||
663 | switch (ar->version.target_ver) { | 708 | switch (ar->version.target_ver) { |
664 | case AR6003_REV2_VERSION: | 709 | case AR6003_REV2_VERSION: |
665 | filename = AR6003_REV2_BOARD_DATA_FILE; | 710 | filename = AR6003_REV2_BOARD_DATA_FILE; |
666 | break; | 711 | break; |
712 | case AR6004_REV1_VERSION: | ||
713 | filename = AR6004_REV1_BOARD_DATA_FILE; | ||
714 | break; | ||
667 | default: | 715 | default: |
668 | filename = AR6003_REV3_BOARD_DATA_FILE; | 716 | filename = AR6003_REV3_BOARD_DATA_FILE; |
669 | break; | 717 | break; |
@@ -676,6 +724,11 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) | |||
676 | return 0; | 724 | return 0; |
677 | } | 725 | } |
678 | 726 | ||
727 | if (check_device_tree(ar)) { | ||
728 | /* got board file from device tree */ | ||
729 | return 0; | ||
730 | } | ||
731 | |||
679 | /* there was no proper board file, try to use default instead */ | 732 | /* there was no proper board file, try to use default instead */ |
680 | ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", | 733 | ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", |
681 | filename, ret); | 734 | filename, ret); |
@@ -684,6 +737,9 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) | |||
684 | case AR6003_REV2_VERSION: | 737 | case AR6003_REV2_VERSION: |
685 | filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE; | 738 | filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE; |
686 | break; | 739 | break; |
740 | case AR6004_REV1_VERSION: | ||
741 | filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE; | ||
742 | break; | ||
687 | default: | 743 | default: |
688 | filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE; | 744 | filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE; |
689 | break; | 745 | break; |
@@ -703,25 +759,346 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) | |||
703 | return 0; | 759 | return 0; |
704 | } | 760 | } |
705 | 761 | ||
762 | static int ath6kl_fetch_otp_file(struct ath6kl *ar) | ||
763 | { | ||
764 | const char *filename; | ||
765 | int ret; | ||
706 | 766 | ||
707 | static int ath6kl_upload_board_file(struct ath6kl *ar) | 767 | if (ar->fw_otp != NULL) |
768 | return 0; | ||
769 | |||
770 | switch (ar->version.target_ver) { | ||
771 | case AR6003_REV2_VERSION: | ||
772 | filename = AR6003_REV2_OTP_FILE; | ||
773 | break; | ||
774 | case AR6004_REV1_VERSION: | ||
775 | ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n"); | ||
776 | return 0; | ||
777 | break; | ||
778 | default: | ||
779 | filename = AR6003_REV3_OTP_FILE; | ||
780 | break; | ||
781 | } | ||
782 | |||
783 | ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, | ||
784 | &ar->fw_otp_len); | ||
785 | if (ret) { | ||
786 | ath6kl_err("Failed to get OTP file %s: %d\n", | ||
787 | filename, ret); | ||
788 | return ret; | ||
789 | } | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | static int ath6kl_fetch_fw_file(struct ath6kl *ar) | ||
708 | { | 795 | { |
709 | u32 board_address, board_ext_address, param; | 796 | const char *filename; |
797 | int ret; | ||
798 | |||
799 | if (ar->fw != NULL) | ||
800 | return 0; | ||
801 | |||
802 | if (testmode) { | ||
803 | switch (ar->version.target_ver) { | ||
804 | case AR6003_REV2_VERSION: | ||
805 | filename = AR6003_REV2_TCMD_FIRMWARE_FILE; | ||
806 | break; | ||
807 | case AR6003_REV3_VERSION: | ||
808 | filename = AR6003_REV3_TCMD_FIRMWARE_FILE; | ||
809 | break; | ||
810 | case AR6004_REV1_VERSION: | ||
811 | ath6kl_warn("testmode not supported with ar6004\n"); | ||
812 | return -EOPNOTSUPP; | ||
813 | default: | ||
814 | ath6kl_warn("unknown target version: 0x%x\n", | ||
815 | ar->version.target_ver); | ||
816 | return -EINVAL; | ||
817 | } | ||
818 | |||
819 | set_bit(TESTMODE, &ar->flag); | ||
820 | |||
821 | goto get_fw; | ||
822 | } | ||
823 | |||
824 | switch (ar->version.target_ver) { | ||
825 | case AR6003_REV2_VERSION: | ||
826 | filename = AR6003_REV2_FIRMWARE_FILE; | ||
827 | break; | ||
828 | case AR6004_REV1_VERSION: | ||
829 | filename = AR6004_REV1_FIRMWARE_FILE; | ||
830 | break; | ||
831 | default: | ||
832 | filename = AR6003_REV3_FIRMWARE_FILE; | ||
833 | break; | ||
834 | } | ||
835 | |||
836 | get_fw: | ||
837 | ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); | ||
838 | if (ret) { | ||
839 | ath6kl_err("Failed to get firmware file %s: %d\n", | ||
840 | filename, ret); | ||
841 | return ret; | ||
842 | } | ||
843 | |||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | static int ath6kl_fetch_patch_file(struct ath6kl *ar) | ||
848 | { | ||
849 | const char *filename; | ||
710 | int ret; | 850 | int ret; |
711 | 851 | ||
712 | if (ar->fw_board == NULL) { | 852 | switch (ar->version.target_ver) { |
713 | ret = ath6kl_fetch_board_file(ar); | 853 | case AR6003_REV2_VERSION: |
714 | if (ret) | 854 | filename = AR6003_REV2_PATCH_FILE; |
855 | break; | ||
856 | case AR6004_REV1_VERSION: | ||
857 | /* FIXME: implement for AR6004 */ | ||
858 | return 0; | ||
859 | break; | ||
860 | default: | ||
861 | filename = AR6003_REV3_PATCH_FILE; | ||
862 | break; | ||
863 | } | ||
864 | |||
865 | if (ar->fw_patch == NULL) { | ||
866 | ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, | ||
867 | &ar->fw_patch_len); | ||
868 | if (ret) { | ||
869 | ath6kl_err("Failed to get patch file %s: %d\n", | ||
870 | filename, ret); | ||
715 | return ret; | 871 | return ret; |
872 | } | ||
716 | } | 873 | } |
717 | 874 | ||
718 | /* Determine where in Target RAM to write Board Data */ | 875 | return 0; |
719 | ath6kl_bmi_read(ar, | 876 | } |
720 | ath6kl_get_hi_item_addr(ar, | 877 | |
721 | HI_ITEM(hi_board_data)), | 878 | static int ath6kl_fetch_fw_api1(struct ath6kl *ar) |
722 | (u8 *) &board_address, 4); | 879 | { |
723 | ath6kl_dbg(ATH6KL_DBG_TRC, "board data download addr: 0x%x\n", | 880 | int ret; |
724 | board_address); | 881 | |
882 | ret = ath6kl_fetch_otp_file(ar); | ||
883 | if (ret) | ||
884 | return ret; | ||
885 | |||
886 | ret = ath6kl_fetch_fw_file(ar); | ||
887 | if (ret) | ||
888 | return ret; | ||
889 | |||
890 | ret = ath6kl_fetch_patch_file(ar); | ||
891 | if (ret) | ||
892 | return ret; | ||
893 | |||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | static int ath6kl_fetch_fw_api2(struct ath6kl *ar) | ||
898 | { | ||
899 | size_t magic_len, len, ie_len; | ||
900 | const struct firmware *fw; | ||
901 | struct ath6kl_fw_ie *hdr; | ||
902 | const char *filename; | ||
903 | const u8 *data; | ||
904 | int ret, ie_id, i, index, bit; | ||
905 | __le32 *val; | ||
906 | |||
907 | switch (ar->version.target_ver) { | ||
908 | case AR6003_REV2_VERSION: | ||
909 | filename = AR6003_REV2_FIRMWARE_2_FILE; | ||
910 | break; | ||
911 | case AR6003_REV3_VERSION: | ||
912 | filename = AR6003_REV3_FIRMWARE_2_FILE; | ||
913 | break; | ||
914 | case AR6004_REV1_VERSION: | ||
915 | filename = AR6004_REV1_FIRMWARE_2_FILE; | ||
916 | break; | ||
917 | default: | ||
918 | return -EOPNOTSUPP; | ||
919 | } | ||
920 | |||
921 | ret = request_firmware(&fw, filename, ar->dev); | ||
922 | if (ret) | ||
923 | return ret; | ||
924 | |||
925 | data = fw->data; | ||
926 | len = fw->size; | ||
927 | |||
928 | /* magic also includes the null byte, check that as well */ | ||
929 | magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1; | ||
930 | |||
931 | if (len < magic_len) { | ||
932 | ret = -EINVAL; | ||
933 | goto out; | ||
934 | } | ||
935 | |||
936 | if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) { | ||
937 | ret = -EINVAL; | ||
938 | goto out; | ||
939 | } | ||
940 | |||
941 | len -= magic_len; | ||
942 | data += magic_len; | ||
943 | |||
944 | /* loop elements */ | ||
945 | while (len > sizeof(struct ath6kl_fw_ie)) { | ||
946 | /* hdr is unaligned! */ | ||
947 | hdr = (struct ath6kl_fw_ie *) data; | ||
948 | |||
949 | ie_id = le32_to_cpup(&hdr->id); | ||
950 | ie_len = le32_to_cpup(&hdr->len); | ||
951 | |||
952 | len -= sizeof(*hdr); | ||
953 | data += sizeof(*hdr); | ||
954 | |||
955 | if (len < ie_len) { | ||
956 | ret = -EINVAL; | ||
957 | goto out; | ||
958 | } | ||
959 | |||
960 | switch (ie_id) { | ||
961 | case ATH6KL_FW_IE_OTP_IMAGE: | ||
962 | ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n", | ||
963 | ie_len); | ||
964 | |||
965 | ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL); | ||
966 | |||
967 | if (ar->fw_otp == NULL) { | ||
968 | ret = -ENOMEM; | ||
969 | goto out; | ||
970 | } | ||
971 | |||
972 | ar->fw_otp_len = ie_len; | ||
973 | break; | ||
974 | case ATH6KL_FW_IE_FW_IMAGE: | ||
975 | ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n", | ||
976 | ie_len); | ||
977 | |||
978 | ar->fw = kmemdup(data, ie_len, GFP_KERNEL); | ||
979 | |||
980 | if (ar->fw == NULL) { | ||
981 | ret = -ENOMEM; | ||
982 | goto out; | ||
983 | } | ||
984 | |||
985 | ar->fw_len = ie_len; | ||
986 | break; | ||
987 | case ATH6KL_FW_IE_PATCH_IMAGE: | ||
988 | ath6kl_dbg(ATH6KL_DBG_BOOT, "found patch image ie (%zd B)\n", | ||
989 | ie_len); | ||
990 | |||
991 | ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL); | ||
992 | |||
993 | if (ar->fw_patch == NULL) { | ||
994 | ret = -ENOMEM; | ||
995 | goto out; | ||
996 | } | ||
997 | |||
998 | ar->fw_patch_len = ie_len; | ||
999 | break; | ||
1000 | case ATH6KL_FW_IE_RESERVED_RAM_SIZE: | ||
1001 | val = (__le32 *) data; | ||
1002 | ar->hw.reserved_ram_size = le32_to_cpup(val); | ||
1003 | |||
1004 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
1005 | "found reserved ram size ie 0x%d\n", | ||
1006 | ar->hw.reserved_ram_size); | ||
1007 | break; | ||
1008 | case ATH6KL_FW_IE_CAPABILITIES: | ||
1009 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
1010 | "found firmware capabilities ie (%zd B)\n", | ||
1011 | ie_len); | ||
1012 | |||
1013 | for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) { | ||
1014 | index = ALIGN(i, 8) / 8; | ||
1015 | bit = i % 8; | ||
1016 | |||
1017 | if (data[index] & (1 << bit)) | ||
1018 | __set_bit(i, ar->fw_capabilities); | ||
1019 | } | ||
1020 | |||
1021 | ath6kl_dbg_dump(ATH6KL_DBG_BOOT, "capabilities", "", | ||
1022 | ar->fw_capabilities, | ||
1023 | sizeof(ar->fw_capabilities)); | ||
1024 | break; | ||
1025 | case ATH6KL_FW_IE_PATCH_ADDR: | ||
1026 | if (ie_len != sizeof(*val)) | ||
1027 | break; | ||
1028 | |||
1029 | val = (__le32 *) data; | ||
1030 | ar->hw.dataset_patch_addr = le32_to_cpup(val); | ||
1031 | |||
1032 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
1033 | "found patch address ie 0x%d\n", | ||
1034 | ar->hw.dataset_patch_addr); | ||
1035 | break; | ||
1036 | default: | ||
1037 | ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n", | ||
1038 | le32_to_cpup(&hdr->id)); | ||
1039 | break; | ||
1040 | } | ||
1041 | |||
1042 | len -= ie_len; | ||
1043 | data += ie_len; | ||
1044 | }; | ||
1045 | |||
1046 | ret = 0; | ||
1047 | out: | ||
1048 | release_firmware(fw); | ||
1049 | |||
1050 | return ret; | ||
1051 | } | ||
1052 | |||
1053 | static int ath6kl_fetch_firmwares(struct ath6kl *ar) | ||
1054 | { | ||
1055 | int ret; | ||
1056 | |||
1057 | ret = ath6kl_fetch_board_file(ar); | ||
1058 | if (ret) | ||
1059 | return ret; | ||
1060 | |||
1061 | ret = ath6kl_fetch_fw_api2(ar); | ||
1062 | if (ret == 0) { | ||
1063 | ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 2\n"); | ||
1064 | return 0; | ||
1065 | } | ||
1066 | |||
1067 | ret = ath6kl_fetch_fw_api1(ar); | ||
1068 | if (ret) | ||
1069 | return ret; | ||
1070 | |||
1071 | ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 1\n"); | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | static int ath6kl_upload_board_file(struct ath6kl *ar) | ||
1077 | { | ||
1078 | u32 board_address, board_ext_address, param; | ||
1079 | u32 board_data_size, board_ext_data_size; | ||
1080 | int ret; | ||
1081 | |||
1082 | if (WARN_ON(ar->fw_board == NULL)) | ||
1083 | return -ENOENT; | ||
1084 | |||
1085 | /* | ||
1086 | * Determine where in Target RAM to write Board Data. | ||
1087 | * For AR6004, host determine Target RAM address for | ||
1088 | * writing board data. | ||
1089 | */ | ||
1090 | if (ar->target_type == TARGET_TYPE_AR6004) { | ||
1091 | board_address = AR6004_REV1_BOARD_DATA_ADDRESS; | ||
1092 | ath6kl_bmi_write(ar, | ||
1093 | ath6kl_get_hi_item_addr(ar, | ||
1094 | HI_ITEM(hi_board_data)), | ||
1095 | (u8 *) &board_address, 4); | ||
1096 | } else { | ||
1097 | ath6kl_bmi_read(ar, | ||
1098 | ath6kl_get_hi_item_addr(ar, | ||
1099 | HI_ITEM(hi_board_data)), | ||
1100 | (u8 *) &board_address, 4); | ||
1101 | } | ||
725 | 1102 | ||
726 | /* determine where in target ram to write extended board data */ | 1103 | /* determine where in target ram to write extended board data */ |
727 | ath6kl_bmi_read(ar, | 1104 | ath6kl_bmi_read(ar, |
@@ -729,21 +1106,37 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
729 | HI_ITEM(hi_board_ext_data)), | 1106 | HI_ITEM(hi_board_ext_data)), |
730 | (u8 *) &board_ext_address, 4); | 1107 | (u8 *) &board_ext_address, 4); |
731 | 1108 | ||
732 | ath6kl_dbg(ATH6KL_DBG_TRC, "board file download addr: 0x%x\n", | ||
733 | board_ext_address); | ||
734 | |||
735 | if (board_ext_address == 0) { | 1109 | if (board_ext_address == 0) { |
736 | ath6kl_err("Failed to get board file target address.\n"); | 1110 | ath6kl_err("Failed to get board file target address.\n"); |
737 | return -EINVAL; | 1111 | return -EINVAL; |
738 | } | 1112 | } |
739 | 1113 | ||
740 | if (ar->fw_board_len == (AR6003_BOARD_DATA_SZ + | 1114 | switch (ar->target_type) { |
741 | AR6003_BOARD_EXT_DATA_SZ)) { | 1115 | case TARGET_TYPE_AR6003: |
1116 | board_data_size = AR6003_BOARD_DATA_SZ; | ||
1117 | board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ; | ||
1118 | break; | ||
1119 | case TARGET_TYPE_AR6004: | ||
1120 | board_data_size = AR6004_BOARD_DATA_SZ; | ||
1121 | board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ; | ||
1122 | break; | ||
1123 | default: | ||
1124 | WARN_ON(1); | ||
1125 | return -EINVAL; | ||
1126 | break; | ||
1127 | } | ||
1128 | |||
1129 | if (ar->fw_board_len == (board_data_size + | ||
1130 | board_ext_data_size)) { | ||
1131 | |||
742 | /* write extended board data */ | 1132 | /* write extended board data */ |
743 | ret = ath6kl_bmi_write(ar, board_ext_address, | 1133 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
744 | ar->fw_board + AR6003_BOARD_DATA_SZ, | 1134 | "writing extended board data to 0x%x (%d B)\n", |
745 | AR6003_BOARD_EXT_DATA_SZ); | 1135 | board_ext_address, board_ext_data_size); |
746 | 1136 | ||
1137 | ret = ath6kl_bmi_write(ar, board_ext_address, | ||
1138 | ar->fw_board + board_data_size, | ||
1139 | board_ext_data_size); | ||
747 | if (ret) { | 1140 | if (ret) { |
748 | ath6kl_err("Failed to write extended board data: %d\n", | 1141 | ath6kl_err("Failed to write extended board data: %d\n", |
749 | ret); | 1142 | ret); |
@@ -751,21 +1144,25 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
751 | } | 1144 | } |
752 | 1145 | ||
753 | /* record that extended board data is initialized */ | 1146 | /* record that extended board data is initialized */ |
754 | param = (AR6003_BOARD_EXT_DATA_SZ << 16) | 1; | 1147 | param = (board_ext_data_size << 16) | 1; |
1148 | |||
755 | ath6kl_bmi_write(ar, | 1149 | ath6kl_bmi_write(ar, |
756 | ath6kl_get_hi_item_addr(ar, | 1150 | ath6kl_get_hi_item_addr(ar, |
757 | HI_ITEM(hi_board_ext_data_config)), | 1151 | HI_ITEM(hi_board_ext_data_config)), |
758 | (unsigned char *) ¶m, 4); | 1152 | (unsigned char *) ¶m, 4); |
759 | } | 1153 | } |
760 | 1154 | ||
761 | if (ar->fw_board_len < AR6003_BOARD_DATA_SZ) { | 1155 | if (ar->fw_board_len < board_data_size) { |
762 | ath6kl_err("Too small board file: %zu\n", ar->fw_board_len); | 1156 | ath6kl_err("Too small board file: %zu\n", ar->fw_board_len); |
763 | ret = -EINVAL; | 1157 | ret = -EINVAL; |
764 | return ret; | 1158 | return ret; |
765 | } | 1159 | } |
766 | 1160 | ||
1161 | ath6kl_dbg(ATH6KL_DBG_BOOT, "writing board file to 0x%x (%d B)\n", | ||
1162 | board_address, board_data_size); | ||
1163 | |||
767 | ret = ath6kl_bmi_write(ar, board_address, ar->fw_board, | 1164 | ret = ath6kl_bmi_write(ar, board_address, ar->fw_board, |
768 | AR6003_BOARD_DATA_SZ); | 1165 | board_data_size); |
769 | 1166 | ||
770 | if (ret) { | 1167 | if (ret) { |
771 | ath6kl_err("Board file bmi write failed: %d\n", ret); | 1168 | ath6kl_err("Board file bmi write failed: %d\n", ret); |
@@ -784,31 +1181,16 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
784 | 1181 | ||
785 | static int ath6kl_upload_otp(struct ath6kl *ar) | 1182 | static int ath6kl_upload_otp(struct ath6kl *ar) |
786 | { | 1183 | { |
787 | const char *filename; | ||
788 | u32 address, param; | 1184 | u32 address, param; |
789 | int ret; | 1185 | int ret; |
790 | 1186 | ||
791 | switch (ar->version.target_ver) { | 1187 | if (WARN_ON(ar->fw_otp == NULL)) |
792 | case AR6003_REV2_VERSION: | 1188 | return -ENOENT; |
793 | filename = AR6003_REV2_OTP_FILE; | ||
794 | break; | ||
795 | default: | ||
796 | filename = AR6003_REV3_OTP_FILE; | ||
797 | break; | ||
798 | } | ||
799 | 1189 | ||
800 | if (ar->fw_otp == NULL) { | 1190 | address = ar->hw.app_load_addr; |
801 | ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, | ||
802 | &ar->fw_otp_len); | ||
803 | if (ret) { | ||
804 | ath6kl_err("Failed to get OTP file %s: %d\n", | ||
805 | filename, ret); | ||
806 | return ret; | ||
807 | } | ||
808 | } | ||
809 | 1191 | ||
810 | address = ath6kl_get_load_address(ar->version.target_ver, | 1192 | ath6kl_dbg(ATH6KL_DBG_BOOT, "writing otp to 0x%x (%zd B)\n", address, |
811 | APP_LOAD_ADDR); | 1193 | ar->fw_otp_len); |
812 | 1194 | ||
813 | ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp, | 1195 | ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp, |
814 | ar->fw_otp_len); | 1196 | ar->fw_otp_len); |
@@ -817,10 +1199,25 @@ static int ath6kl_upload_otp(struct ath6kl *ar) | |||
817 | return ret; | 1199 | return ret; |
818 | } | 1200 | } |
819 | 1201 | ||
1202 | /* read firmware start address */ | ||
1203 | ret = ath6kl_bmi_read(ar, | ||
1204 | ath6kl_get_hi_item_addr(ar, | ||
1205 | HI_ITEM(hi_app_start)), | ||
1206 | (u8 *) &address, sizeof(address)); | ||
1207 | |||
1208 | if (ret) { | ||
1209 | ath6kl_err("Failed to read hi_app_start: %d\n", ret); | ||
1210 | return ret; | ||
1211 | } | ||
1212 | |||
1213 | ar->hw.app_start_override_addr = address; | ||
1214 | |||
1215 | ath6kl_dbg(ATH6KL_DBG_BOOT, "app_start_override_addr 0x%x\n", | ||
1216 | ar->hw.app_start_override_addr); | ||
1217 | |||
820 | /* execute the OTP code */ | 1218 | /* execute the OTP code */ |
1219 | ath6kl_dbg(ATH6KL_DBG_BOOT, "executing OTP at 0x%x\n", address); | ||
821 | param = 0; | 1220 | param = 0; |
822 | address = ath6kl_get_load_address(ar->version.target_ver, | ||
823 | APP_START_OVERRIDE_ADDR); | ||
824 | ath6kl_bmi_execute(ar, address, ¶m); | 1221 | ath6kl_bmi_execute(ar, address, ¶m); |
825 | 1222 | ||
826 | return ret; | 1223 | return ret; |
@@ -828,30 +1225,16 @@ static int ath6kl_upload_otp(struct ath6kl *ar) | |||
828 | 1225 | ||
829 | static int ath6kl_upload_firmware(struct ath6kl *ar) | 1226 | static int ath6kl_upload_firmware(struct ath6kl *ar) |
830 | { | 1227 | { |
831 | const char *filename; | ||
832 | u32 address; | 1228 | u32 address; |
833 | int ret; | 1229 | int ret; |
834 | 1230 | ||
835 | switch (ar->version.target_ver) { | 1231 | if (WARN_ON(ar->fw == NULL)) |
836 | case AR6003_REV2_VERSION: | 1232 | return -ENOENT; |
837 | filename = AR6003_REV2_FIRMWARE_FILE; | ||
838 | break; | ||
839 | default: | ||
840 | filename = AR6003_REV3_FIRMWARE_FILE; | ||
841 | break; | ||
842 | } | ||
843 | 1233 | ||
844 | if (ar->fw == NULL) { | 1234 | address = ar->hw.app_load_addr; |
845 | ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); | ||
846 | if (ret) { | ||
847 | ath6kl_err("Failed to get firmware file %s: %d\n", | ||
848 | filename, ret); | ||
849 | return ret; | ||
850 | } | ||
851 | } | ||
852 | 1235 | ||
853 | address = ath6kl_get_load_address(ar->version.target_ver, | 1236 | ath6kl_dbg(ATH6KL_DBG_BOOT, "writing firmware to 0x%x (%zd B)\n", |
854 | APP_LOAD_ADDR); | 1237 | address, ar->fw_len); |
855 | 1238 | ||
856 | ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len); | 1239 | ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len); |
857 | 1240 | ||
@@ -860,41 +1243,29 @@ static int ath6kl_upload_firmware(struct ath6kl *ar) | |||
860 | return ret; | 1243 | return ret; |
861 | } | 1244 | } |
862 | 1245 | ||
863 | /* Set starting address for firmware */ | 1246 | /* |
864 | address = ath6kl_get_load_address(ar->version.target_ver, | 1247 | * Set starting address for firmware |
865 | APP_START_OVERRIDE_ADDR); | 1248 | * Don't need to setup app_start override addr on AR6004 |
866 | ath6kl_bmi_set_app_start(ar, address); | 1249 | */ |
867 | 1250 | if (ar->target_type != TARGET_TYPE_AR6004) { | |
1251 | address = ar->hw.app_start_override_addr; | ||
1252 | ath6kl_bmi_set_app_start(ar, address); | ||
1253 | } | ||
868 | return ret; | 1254 | return ret; |
869 | } | 1255 | } |
870 | 1256 | ||
871 | static int ath6kl_upload_patch(struct ath6kl *ar) | 1257 | static int ath6kl_upload_patch(struct ath6kl *ar) |
872 | { | 1258 | { |
873 | const char *filename; | ||
874 | u32 address, param; | 1259 | u32 address, param; |
875 | int ret; | 1260 | int ret; |
876 | 1261 | ||
877 | switch (ar->version.target_ver) { | 1262 | if (WARN_ON(ar->fw_patch == NULL)) |
878 | case AR6003_REV2_VERSION: | 1263 | return -ENOENT; |
879 | filename = AR6003_REV2_PATCH_FILE; | ||
880 | break; | ||
881 | default: | ||
882 | filename = AR6003_REV3_PATCH_FILE; | ||
883 | break; | ||
884 | } | ||
885 | 1264 | ||
886 | if (ar->fw_patch == NULL) { | 1265 | address = ar->hw.dataset_patch_addr; |
887 | ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, | ||
888 | &ar->fw_patch_len); | ||
889 | if (ret) { | ||
890 | ath6kl_err("Failed to get patch file %s: %d\n", | ||
891 | filename, ret); | ||
892 | return ret; | ||
893 | } | ||
894 | } | ||
895 | 1266 | ||
896 | address = ath6kl_get_load_address(ar->version.target_ver, | 1267 | ath6kl_dbg(ATH6KL_DBG_BOOT, "writing patch to 0x%x (%zd B)\n", |
897 | DATASET_PATCH_ADDR); | 1268 | address, ar->fw_patch_len); |
898 | 1269 | ||
899 | ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len); | 1270 | ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len); |
900 | if (ret) { | 1271 | if (ret) { |
@@ -916,7 +1287,8 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
916 | u32 param, options, sleep, address; | 1287 | u32 param, options, sleep, address; |
917 | int status = 0; | 1288 | int status = 0; |
918 | 1289 | ||
919 | if (ar->target_type != TARGET_TYPE_AR6003) | 1290 | if (ar->target_type != TARGET_TYPE_AR6003 && |
1291 | ar->target_type != TARGET_TYPE_AR6004) | ||
920 | return -EINVAL; | 1292 | return -EINVAL; |
921 | 1293 | ||
922 | /* temporarily disable system sleep */ | 1294 | /* temporarily disable system sleep */ |
@@ -948,18 +1320,22 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
948 | options, sleep); | 1320 | options, sleep); |
949 | 1321 | ||
950 | /* program analog PLL register */ | 1322 | /* program analog PLL register */ |
951 | status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER, | 1323 | /* no need to control 40/44MHz clock on AR6004 */ |
952 | 0xF9104001); | 1324 | if (ar->target_type != TARGET_TYPE_AR6004) { |
953 | if (status) | 1325 | status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER, |
954 | return status; | 1326 | 0xF9104001); |
955 | 1327 | ||
956 | /* Run at 80/88MHz by default */ | 1328 | if (status) |
957 | param = SM(CPU_CLOCK_STANDARD, 1); | 1329 | return status; |
958 | 1330 | ||
959 | address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS; | 1331 | /* Run at 80/88MHz by default */ |
960 | status = ath6kl_bmi_reg_write(ar, address, param); | 1332 | param = SM(CPU_CLOCK_STANDARD, 1); |
961 | if (status) | 1333 | |
962 | return status; | 1334 | address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS; |
1335 | status = ath6kl_bmi_reg_write(ar, address, param); | ||
1336 | if (status) | ||
1337 | return status; | ||
1338 | } | ||
963 | 1339 | ||
964 | param = 0; | 1340 | param = 0; |
965 | address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS; | 1341 | address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS; |
@@ -1036,6 +1412,45 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
1036 | return status; | 1412 | return status; |
1037 | } | 1413 | } |
1038 | 1414 | ||
1415 | static int ath6kl_init_hw_params(struct ath6kl *ar) | ||
1416 | { | ||
1417 | switch (ar->version.target_ver) { | ||
1418 | case AR6003_REV2_VERSION: | ||
1419 | ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS; | ||
1420 | ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS; | ||
1421 | ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; | ||
1422 | ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE; | ||
1423 | break; | ||
1424 | case AR6003_REV3_VERSION: | ||
1425 | ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS; | ||
1426 | ar->hw.app_load_addr = 0x1234; | ||
1427 | ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; | ||
1428 | ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE; | ||
1429 | break; | ||
1430 | case AR6004_REV1_VERSION: | ||
1431 | ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS; | ||
1432 | ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS; | ||
1433 | ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS; | ||
1434 | ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE; | ||
1435 | break; | ||
1436 | default: | ||
1437 | ath6kl_err("Unsupported hardware version: 0x%x\n", | ||
1438 | ar->version.target_ver); | ||
1439 | return -EINVAL; | ||
1440 | } | ||
1441 | |||
1442 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
1443 | "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n", | ||
1444 | ar->version.target_ver, ar->target_type, | ||
1445 | ar->hw.dataset_patch_addr, ar->hw.app_load_addr); | ||
1446 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
1447 | "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x", | ||
1448 | ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr, | ||
1449 | ar->hw.reserved_ram_size); | ||
1450 | |||
1451 | return 0; | ||
1452 | } | ||
1453 | |||
1039 | static int ath6kl_init(struct net_device *dev) | 1454 | static int ath6kl_init(struct net_device *dev) |
1040 | { | 1455 | { |
1041 | struct ath6kl *ar = ath6kl_priv(dev); | 1456 | struct ath6kl *ar = ath6kl_priv(dev); |
@@ -1062,8 +1477,6 @@ static int ath6kl_init(struct net_device *dev) | |||
1062 | 1477 | ||
1063 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); | 1478 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); |
1064 | 1479 | ||
1065 | wlan_node_table_init(&ar->scan_table); | ||
1066 | |||
1067 | /* | 1480 | /* |
1068 | * The reason we have to wait for the target here is that the | 1481 | * The reason we have to wait for the target here is that the |
1069 | * driver layer has to init BMI in order to set the host block | 1482 | * driver layer has to init BMI in order to set the host block |
@@ -1111,6 +1524,8 @@ static int ath6kl_init(struct net_device *dev) | |||
1111 | &ar->flag), | 1524 | &ar->flag), |
1112 | WMI_TIMEOUT); | 1525 | WMI_TIMEOUT); |
1113 | 1526 | ||
1527 | ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n"); | ||
1528 | |||
1114 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { | 1529 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { |
1115 | ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n", | 1530 | ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n", |
1116 | ATH6KL_ABI_VERSION, ar->version.abi_ver); | 1531 | ATH6KL_ABI_VERSION, ar->version.abi_ver); |
@@ -1133,6 +1548,8 @@ static int ath6kl_init(struct net_device *dev) | |||
1133 | ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | | 1548 | ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | |
1134 | ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; | 1549 | ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; |
1135 | 1550 | ||
1551 | ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; | ||
1552 | |||
1136 | status = ath6kl_target_config_wlan_params(ar); | 1553 | status = ath6kl_target_config_wlan_params(ar); |
1137 | if (!status) | 1554 | if (!status) |
1138 | goto ath6kl_init_done; | 1555 | goto ath6kl_init_done; |
@@ -1145,7 +1562,6 @@ err_rxbuf_cleanup: | |||
1145 | err_cleanup_scatter: | 1562 | err_cleanup_scatter: |
1146 | ath6kl_hif_cleanup_scatter(ar); | 1563 | ath6kl_hif_cleanup_scatter(ar); |
1147 | err_node_cleanup: | 1564 | err_node_cleanup: |
1148 | wlan_node_table_cleanup(&ar->scan_table); | ||
1149 | ath6kl_wmi_shutdown(ar->wmi); | 1565 | ath6kl_wmi_shutdown(ar->wmi); |
1150 | clear_bit(WMI_ENABLED, &ar->flag); | 1566 | clear_bit(WMI_ENABLED, &ar->flag); |
1151 | ar->wmi = NULL; | 1567 | ar->wmi = NULL; |
@@ -1175,6 +1591,10 @@ int ath6kl_core_init(struct ath6kl *ar) | |||
1175 | ar->target_type = le32_to_cpu(targ_info.type); | 1591 | ar->target_type = le32_to_cpu(targ_info.type); |
1176 | ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version); | 1592 | ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version); |
1177 | 1593 | ||
1594 | ret = ath6kl_init_hw_params(ar); | ||
1595 | if (ret) | ||
1596 | goto err_bmi_cleanup; | ||
1597 | |||
1178 | ret = ath6kl_configure_target(ar); | 1598 | ret = ath6kl_configure_target(ar); |
1179 | if (ret) | 1599 | if (ret) |
1180 | goto err_bmi_cleanup; | 1600 | goto err_bmi_cleanup; |
@@ -1193,6 +1613,10 @@ int ath6kl_core_init(struct ath6kl *ar) | |||
1193 | goto err_htc_cleanup; | 1613 | goto err_htc_cleanup; |
1194 | } | 1614 | } |
1195 | 1615 | ||
1616 | ret = ath6kl_fetch_firmwares(ar); | ||
1617 | if (ret) | ||
1618 | goto err_htc_cleanup; | ||
1619 | |||
1196 | ret = ath6kl_init_upload(ar); | 1620 | ret = ath6kl_init_upload(ar); |
1197 | if (ret) | 1621 | if (ret) |
1198 | goto err_htc_cleanup; | 1622 | goto err_htc_cleanup; |
@@ -1285,6 +1709,8 @@ void ath6kl_destroy(struct net_device *dev, unsigned int unregister) | |||
1285 | 1709 | ||
1286 | ath6kl_bmi_cleanup(ar); | 1710 | ath6kl_bmi_cleanup(ar); |
1287 | 1711 | ||
1712 | ath6kl_debug_cleanup(ar); | ||
1713 | |||
1288 | if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) { | 1714 | if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) { |
1289 | unregister_netdev(dev); | 1715 | unregister_netdev(dev); |
1290 | clear_bit(NETDEV_REGISTERED, &ar->flag); | 1716 | clear_bit(NETDEV_REGISTERED, &ar->flag); |
@@ -1292,8 +1718,6 @@ void ath6kl_destroy(struct net_device *dev, unsigned int unregister) | |||
1292 | 1718 | ||
1293 | free_netdev(dev); | 1719 | free_netdev(dev); |
1294 | 1720 | ||
1295 | wlan_node_table_cleanup(&ar->scan_table); | ||
1296 | |||
1297 | kfree(ar->fw_board); | 1721 | kfree(ar->fw_board); |
1298 | kfree(ar->fw_otp); | 1722 | kfree(ar->fw_otp); |
1299 | kfree(ar->fw); | 1723 | kfree(ar->fw); |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index c336eae0cf48..30b5a53db9ed 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -61,7 +61,8 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, | |||
61 | 61 | ||
62 | sta = &ar->sta_list[free_slot]; | 62 | sta = &ar->sta_list[free_slot]; |
63 | memcpy(sta->mac, mac, ETH_ALEN); | 63 | memcpy(sta->mac, mac, ETH_ALEN); |
64 | memcpy(sta->wpa_ie, wpaie, ielen); | 64 | if (ielen <= ATH6KL_MAX_IE) |
65 | memcpy(sta->wpa_ie, wpaie, ielen); | ||
65 | sta->aid = aid; | 66 | sta->aid = aid; |
66 | sta->keymgmt = keymgmt; | 67 | sta->keymgmt = keymgmt; |
67 | sta->ucipher = ucipher; | 68 | sta->ucipher = ucipher; |
@@ -177,8 +178,8 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie) | |||
177 | static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | 178 | static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) |
178 | { | 179 | { |
179 | int status; | 180 | int status; |
180 | u8 addr_val[4]; | ||
181 | s32 i; | 181 | s32 i; |
182 | __le32 addr_val; | ||
182 | 183 | ||
183 | /* | 184 | /* |
184 | * Write bytes 1,2,3 of the register to set the upper address bytes, | 185 | * Write bytes 1,2,3 of the register to set the upper address bytes, |
@@ -188,16 +189,18 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | |||
188 | for (i = 1; i <= 3; i++) { | 189 | for (i = 1; i <= 3; i++) { |
189 | /* | 190 | /* |
190 | * Fill the buffer with the address byte value we want to | 191 | * Fill the buffer with the address byte value we want to |
191 | * hit 4 times. | 192 | * hit 4 times. No need to worry about endianness as the |
193 | * same byte is copied to all four bytes of addr_val at | ||
194 | * any time. | ||
192 | */ | 195 | */ |
193 | memset(addr_val, ((u8 *)&addr)[i], 4); | 196 | memset((u8 *)&addr_val, ((u8 *)&addr)[i], 4); |
194 | 197 | ||
195 | /* | 198 | /* |
196 | * Hit each byte of the register address with a 4-byte | 199 | * Hit each byte of the register address with a 4-byte |
197 | * write operation to the same address, this is a harmless | 200 | * write operation to the same address, this is a harmless |
198 | * operation. | 201 | * operation. |
199 | */ | 202 | */ |
200 | status = hif_read_write_sync(ar, reg_addr + i, addr_val, | 203 | status = hif_read_write_sync(ar, reg_addr + i, (u8 *)&addr_val, |
201 | 4, HIF_WR_SYNC_BYTE_FIX); | 204 | 4, HIF_WR_SYNC_BYTE_FIX); |
202 | if (status) | 205 | if (status) |
203 | break; | 206 | break; |
@@ -215,7 +218,9 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | |||
215 | * cycle to start, the extra 3 byte write to bytes 1,2,3 has no | 218 | * cycle to start, the extra 3 byte write to bytes 1,2,3 has no |
216 | * effect since we are writing the same values again | 219 | * effect since we are writing the same values again |
217 | */ | 220 | */ |
218 | status = hif_read_write_sync(ar, reg_addr, (u8 *)(&addr), | 221 | addr_val = cpu_to_le32(addr); |
222 | status = hif_read_write_sync(ar, reg_addr, | ||
223 | (u8 *)&(addr_val), | ||
219 | 4, HIF_WR_SYNC_BYTE_INC); | 224 | 4, HIF_WR_SYNC_BYTE_INC); |
220 | 225 | ||
221 | if (status) { | 226 | if (status) { |
@@ -228,90 +233,193 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | |||
228 | } | 233 | } |
229 | 234 | ||
230 | /* | 235 | /* |
231 | * Read from the ATH6KL through its diagnostic window. No cooperation from | 236 | * Read from the hardware through its diagnostic window. No cooperation |
232 | * the Target is required for this. | 237 | * from the firmware is required for this. |
233 | */ | 238 | */ |
234 | int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data) | 239 | int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value) |
235 | { | 240 | { |
236 | int status; | 241 | int ret; |
237 | 242 | ||
238 | /* set window register to start read cycle */ | 243 | /* set window register to start read cycle */ |
239 | status = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, | 244 | ret = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, address); |
240 | *address); | 245 | if (ret) |
241 | 246 | return ret; | |
242 | if (status) | ||
243 | return status; | ||
244 | 247 | ||
245 | /* read the data */ | 248 | /* read the data */ |
246 | status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data, | 249 | ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) value, |
247 | sizeof(u32), HIF_RD_SYNC_BYTE_INC); | 250 | sizeof(*value), HIF_RD_SYNC_BYTE_INC); |
248 | if (status) { | 251 | if (ret) { |
249 | ath6kl_err("failed to read from window data addr\n"); | 252 | ath6kl_warn("failed to read32 through diagnose window: %d\n", |
250 | return status; | 253 | ret); |
254 | return ret; | ||
251 | } | 255 | } |
252 | 256 | ||
253 | return status; | 257 | return 0; |
254 | } | 258 | } |
255 | 259 | ||
256 | |||
257 | /* | 260 | /* |
258 | * Write to the ATH6KL through its diagnostic window. No cooperation from | 261 | * Write to the ATH6KL through its diagnostic window. No cooperation from |
259 | * the Target is required for this. | 262 | * the Target is required for this. |
260 | */ | 263 | */ |
261 | static int ath6kl_write_reg_diag(struct ath6kl *ar, u32 *address, u32 *data) | 264 | int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value) |
262 | { | 265 | { |
263 | int status; | 266 | int ret; |
264 | 267 | ||
265 | /* set write data */ | 268 | /* set write data */ |
266 | status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data, | 269 | ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) &value, |
267 | sizeof(u32), HIF_WR_SYNC_BYTE_INC); | 270 | sizeof(value), HIF_WR_SYNC_BYTE_INC); |
268 | if (status) { | 271 | if (ret) { |
269 | ath6kl_err("failed to write 0x%x to window data addr\n", *data); | 272 | ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n", |
270 | return status; | 273 | address, value); |
274 | return ret; | ||
271 | } | 275 | } |
272 | 276 | ||
273 | /* set window register, which starts the write cycle */ | 277 | /* set window register, which starts the write cycle */ |
274 | return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, | 278 | return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, |
275 | *address); | 279 | address); |
276 | } | 280 | } |
277 | 281 | ||
278 | int ath6kl_access_datadiag(struct ath6kl *ar, u32 address, | 282 | int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length) |
279 | u8 *data, u32 length, bool read) | 283 | { |
284 | u32 count, *buf = data; | ||
285 | int ret; | ||
286 | |||
287 | if (WARN_ON(length % 4)) | ||
288 | return -EINVAL; | ||
289 | |||
290 | for (count = 0; count < length / 4; count++, address += 4) { | ||
291 | ret = ath6kl_diag_read32(ar, address, &buf[count]); | ||
292 | if (ret) | ||
293 | return ret; | ||
294 | } | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length) | ||
280 | { | 300 | { |
281 | u32 count; | 301 | u32 count; |
282 | int status = 0; | 302 | __le32 *buf = data; |
303 | int ret; | ||
283 | 304 | ||
284 | for (count = 0; count < length; count += 4, address += 4) { | 305 | if (WARN_ON(length % 4)) |
285 | if (read) { | 306 | return -EINVAL; |
286 | status = ath6kl_read_reg_diag(ar, &address, | 307 | |
287 | (u32 *) &data[count]); | 308 | for (count = 0; count < length / 4; count++, address += 4) { |
288 | if (status) | 309 | ret = ath6kl_diag_write32(ar, address, buf[count]); |
289 | break; | 310 | if (ret) |
290 | } else { | 311 | return ret; |
291 | status = ath6kl_write_reg_diag(ar, &address, | 312 | } |
292 | (u32 *) &data[count]); | 313 | |
293 | if (status) | 314 | return 0; |
294 | break; | 315 | } |
295 | } | 316 | |
317 | int ath6kl_read_fwlogs(struct ath6kl *ar) | ||
318 | { | ||
319 | struct ath6kl_dbglog_hdr debug_hdr; | ||
320 | struct ath6kl_dbglog_buf debug_buf; | ||
321 | u32 address, length, dropped, firstbuf, debug_hdr_addr; | ||
322 | int ret = 0, loop; | ||
323 | u8 *buf; | ||
324 | |||
325 | buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL); | ||
326 | if (!buf) | ||
327 | return -ENOMEM; | ||
328 | |||
329 | address = TARG_VTOP(ar->target_type, | ||
330 | ath6kl_get_hi_item_addr(ar, | ||
331 | HI_ITEM(hi_dbglog_hdr))); | ||
332 | |||
333 | ret = ath6kl_diag_read32(ar, address, &debug_hdr_addr); | ||
334 | if (ret) | ||
335 | goto out; | ||
336 | |||
337 | /* Get the contents of the ring buffer */ | ||
338 | if (debug_hdr_addr == 0) { | ||
339 | ath6kl_warn("Invalid address for debug_hdr_addr\n"); | ||
340 | ret = -EINVAL; | ||
341 | goto out; | ||
296 | } | 342 | } |
297 | 343 | ||
298 | return status; | 344 | address = TARG_VTOP(ar->target_type, debug_hdr_addr); |
345 | ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr)); | ||
346 | |||
347 | address = TARG_VTOP(ar->target_type, | ||
348 | le32_to_cpu(debug_hdr.dbuf_addr)); | ||
349 | firstbuf = address; | ||
350 | dropped = le32_to_cpu(debug_hdr.dropped); | ||
351 | ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf)); | ||
352 | |||
353 | loop = 100; | ||
354 | |||
355 | do { | ||
356 | address = TARG_VTOP(ar->target_type, | ||
357 | le32_to_cpu(debug_buf.buffer_addr)); | ||
358 | length = le32_to_cpu(debug_buf.length); | ||
359 | |||
360 | if (length != 0 && (le32_to_cpu(debug_buf.length) <= | ||
361 | le32_to_cpu(debug_buf.bufsize))) { | ||
362 | length = ALIGN(length, 4); | ||
363 | |||
364 | ret = ath6kl_diag_read(ar, address, | ||
365 | buf, length); | ||
366 | if (ret) | ||
367 | goto out; | ||
368 | |||
369 | ath6kl_debug_fwlog_event(ar, buf, length); | ||
370 | } | ||
371 | |||
372 | address = TARG_VTOP(ar->target_type, | ||
373 | le32_to_cpu(debug_buf.next)); | ||
374 | ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf)); | ||
375 | if (ret) | ||
376 | goto out; | ||
377 | |||
378 | loop--; | ||
379 | |||
380 | if (WARN_ON(loop == 0)) { | ||
381 | ret = -ETIMEDOUT; | ||
382 | goto out; | ||
383 | } | ||
384 | } while (address != firstbuf); | ||
385 | |||
386 | out: | ||
387 | kfree(buf); | ||
388 | |||
389 | return ret; | ||
299 | } | 390 | } |
300 | 391 | ||
392 | /* FIXME: move to a better place, target.h? */ | ||
393 | #define AR6003_RESET_CONTROL_ADDRESS 0x00004000 | ||
394 | #define AR6004_RESET_CONTROL_ADDRESS 0x00004000 | ||
395 | |||
301 | static void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, | 396 | static void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, |
302 | bool wait_fot_compltn, bool cold_reset) | 397 | bool wait_fot_compltn, bool cold_reset) |
303 | { | 398 | { |
304 | int status = 0; | 399 | int status = 0; |
305 | u32 address; | 400 | u32 address; |
306 | u32 data; | 401 | __le32 data; |
307 | 402 | ||
308 | if (target_type != TARGET_TYPE_AR6003) | 403 | if (target_type != TARGET_TYPE_AR6003 && |
404 | target_type != TARGET_TYPE_AR6004) | ||
309 | return; | 405 | return; |
310 | 406 | ||
311 | data = cold_reset ? RESET_CONTROL_COLD_RST : RESET_CONTROL_MBOX_RST; | 407 | data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) : |
408 | cpu_to_le32(RESET_CONTROL_MBOX_RST); | ||
312 | 409 | ||
313 | address = RTC_BASE_ADDRESS; | 410 | switch (target_type) { |
314 | status = ath6kl_write_reg_diag(ar, &address, &data); | 411 | case TARGET_TYPE_AR6003: |
412 | address = AR6003_RESET_CONTROL_ADDRESS; | ||
413 | break; | ||
414 | case TARGET_TYPE_AR6004: | ||
415 | address = AR6004_RESET_CONTROL_ADDRESS; | ||
416 | break; | ||
417 | default: | ||
418 | address = AR6003_RESET_CONTROL_ADDRESS; | ||
419 | break; | ||
420 | } | ||
421 | |||
422 | status = ath6kl_diag_write32(ar, address, data); | ||
315 | 423 | ||
316 | if (status) | 424 | if (status) |
317 | ath6kl_err("failed to reset target\n"); | 425 | ath6kl_err("failed to reset target\n"); |
@@ -411,68 +519,107 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar) | |||
411 | } | 519 | } |
412 | } | 520 | } |
413 | 521 | ||
414 | static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, | 522 | void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel) |
415 | u16 listen_int, u16 beacon_int, | ||
416 | u8 assoc_resp_len, u8 *assoc_info) | ||
417 | { | 523 | { |
418 | struct net_device *dev = ar->net_dev; | ||
419 | struct station_info sinfo; | ||
420 | struct ath6kl_req_key *ik; | 524 | struct ath6kl_req_key *ik; |
421 | enum crypto_type keyType = NONE_CRYPT; | 525 | int res; |
526 | u8 key_rsc[ATH6KL_KEY_SEQ_LEN]; | ||
422 | 527 | ||
423 | if (memcmp(dev->dev_addr, bssid, ETH_ALEN) == 0) { | 528 | ik = &ar->ap_mode_bkey; |
424 | ik = &ar->ap_mode_bkey; | ||
425 | 529 | ||
426 | switch (ar->auth_mode) { | 530 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel); |
427 | case NONE_AUTH: | 531 | |
428 | if (ar->prwise_crypto == WEP_CRYPT) | 532 | switch (ar->auth_mode) { |
429 | ath6kl_install_static_wep_keys(ar); | 533 | case NONE_AUTH: |
430 | break; | 534 | if (ar->prwise_crypto == WEP_CRYPT) |
431 | case WPA_PSK_AUTH: | 535 | ath6kl_install_static_wep_keys(ar); |
432 | case WPA2_PSK_AUTH: | 536 | break; |
433 | case (WPA_PSK_AUTH|WPA2_PSK_AUTH): | 537 | case WPA_PSK_AUTH: |
434 | switch (ik->ik_type) { | 538 | case WPA2_PSK_AUTH: |
435 | case ATH6KL_CIPHER_TKIP: | 539 | case (WPA_PSK_AUTH | WPA2_PSK_AUTH): |
436 | keyType = TKIP_CRYPT; | 540 | if (!ik->valid) |
437 | break; | ||
438 | case ATH6KL_CIPHER_AES_CCM: | ||
439 | keyType = AES_CRYPT; | ||
440 | break; | ||
441 | default: | ||
442 | goto skip_key; | ||
443 | } | ||
444 | ath6kl_wmi_addkey_cmd(ar->wmi, ik->ik_keyix, keyType, | ||
445 | GROUP_USAGE, ik->ik_keylen, | ||
446 | (u8 *)&ik->ik_keyrsc, | ||
447 | ik->ik_keydata, | ||
448 | KEY_OP_INIT_VAL, ik->ik_macaddr, | ||
449 | SYNC_BOTH_WMIFLAG); | ||
450 | break; | 541 | break; |
542 | |||
543 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for " | ||
544 | "the initial group key for AP mode\n"); | ||
545 | memset(key_rsc, 0, sizeof(key_rsc)); | ||
546 | res = ath6kl_wmi_addkey_cmd( | ||
547 | ar->wmi, ik->key_index, ik->key_type, | ||
548 | GROUP_USAGE, ik->key_len, key_rsc, ik->key, | ||
549 | KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG); | ||
550 | if (res) { | ||
551 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed " | ||
552 | "addkey failed: %d\n", res); | ||
451 | } | 553 | } |
452 | skip_key: | 554 | break; |
453 | set_bit(CONNECTED, &ar->flag); | ||
454 | return; | ||
455 | } | 555 | } |
456 | 556 | ||
457 | ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", | 557 | ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); |
458 | bssid, channel); | 558 | set_bit(CONNECTED, &ar->flag); |
559 | netif_carrier_on(ar->net_dev); | ||
560 | } | ||
561 | |||
562 | void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr, | ||
563 | u8 keymgmt, u8 ucipher, u8 auth, | ||
564 | u8 assoc_req_len, u8 *assoc_info) | ||
565 | { | ||
566 | u8 *ies = NULL, *wpa_ie = NULL, *pos; | ||
567 | size_t ies_len = 0; | ||
568 | struct station_info sinfo; | ||
459 | 569 | ||
460 | ath6kl_add_new_sta(ar, bssid, channel, assoc_info, assoc_resp_len, | 570 | ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", mac_addr, aid); |
461 | listen_int & 0xFF, beacon_int, | 571 | |
462 | (listen_int >> 8) & 0xFF); | 572 | if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) { |
573 | struct ieee80211_mgmt *mgmt = | ||
574 | (struct ieee80211_mgmt *) assoc_info; | ||
575 | if (ieee80211_is_assoc_req(mgmt->frame_control) && | ||
576 | assoc_req_len >= sizeof(struct ieee80211_hdr_3addr) + | ||
577 | sizeof(mgmt->u.assoc_req)) { | ||
578 | ies = mgmt->u.assoc_req.variable; | ||
579 | ies_len = assoc_info + assoc_req_len - ies; | ||
580 | } else if (ieee80211_is_reassoc_req(mgmt->frame_control) && | ||
581 | assoc_req_len >= sizeof(struct ieee80211_hdr_3addr) | ||
582 | + sizeof(mgmt->u.reassoc_req)) { | ||
583 | ies = mgmt->u.reassoc_req.variable; | ||
584 | ies_len = assoc_info + assoc_req_len - ies; | ||
585 | } | ||
586 | } | ||
587 | |||
588 | pos = ies; | ||
589 | while (pos && pos + 1 < ies + ies_len) { | ||
590 | if (pos + 2 + pos[1] > ies + ies_len) | ||
591 | break; | ||
592 | if (pos[0] == WLAN_EID_RSN) | ||
593 | wpa_ie = pos; /* RSN IE */ | ||
594 | else if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && | ||
595 | pos[1] >= 4 && | ||
596 | pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2) { | ||
597 | if (pos[5] == 0x01) | ||
598 | wpa_ie = pos; /* WPA IE */ | ||
599 | else if (pos[5] == 0x04) { | ||
600 | wpa_ie = pos; /* WPS IE */ | ||
601 | break; /* overrides WPA/RSN IE */ | ||
602 | } | ||
603 | } | ||
604 | pos += 2 + pos[1]; | ||
605 | } | ||
606 | |||
607 | ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie, | ||
608 | wpa_ie ? 2 + wpa_ie[1] : 0, | ||
609 | keymgmt, ucipher, auth); | ||
463 | 610 | ||
464 | /* send event to application */ | 611 | /* send event to application */ |
465 | memset(&sinfo, 0, sizeof(sinfo)); | 612 | memset(&sinfo, 0, sizeof(sinfo)); |
466 | 613 | ||
467 | /* TODO: sinfo.generation */ | 614 | /* TODO: sinfo.generation */ |
468 | /* TODO: need to deliver (Re)AssocReq IEs somehow.. change in | ||
469 | * cfg80211 needed, e.g., by adding those into sinfo | ||
470 | */ | ||
471 | cfg80211_new_sta(ar->net_dev, bssid, &sinfo, GFP_KERNEL); | ||
472 | 615 | ||
473 | netif_wake_queue(ar->net_dev); | 616 | sinfo.assoc_req_ies = ies; |
617 | sinfo.assoc_req_ies_len = ies_len; | ||
618 | sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; | ||
474 | 619 | ||
475 | return; | 620 | cfg80211_new_sta(ar->net_dev, mac_addr, &sinfo, GFP_KERNEL); |
621 | |||
622 | netif_wake_queue(ar->net_dev); | ||
476 | } | 623 | } |
477 | 624 | ||
478 | /* Functions for Tx credit handling */ | 625 | /* Functions for Tx credit handling */ |
@@ -779,6 +926,41 @@ void ath6kl_disconnect(struct ath6kl *ar) | |||
779 | } | 926 | } |
780 | } | 927 | } |
781 | 928 | ||
929 | void ath6kl_deep_sleep_enable(struct ath6kl *ar) | ||
930 | { | ||
931 | switch (ar->sme_state) { | ||
932 | case SME_CONNECTING: | ||
933 | cfg80211_connect_result(ar->net_dev, ar->bssid, NULL, 0, | ||
934 | NULL, 0, | ||
935 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
936 | GFP_KERNEL); | ||
937 | break; | ||
938 | case SME_CONNECTED: | ||
939 | default: | ||
940 | /* | ||
941 | * FIXME: oddly enough smeState is in DISCONNECTED during | ||
942 | * suspend, why? Need to send disconnected event in that | ||
943 | * state. | ||
944 | */ | ||
945 | cfg80211_disconnected(ar->net_dev, 0, NULL, 0, GFP_KERNEL); | ||
946 | break; | ||
947 | } | ||
948 | |||
949 | if (test_bit(CONNECTED, &ar->flag) || | ||
950 | test_bit(CONNECT_PEND, &ar->flag)) | ||
951 | ath6kl_wmi_disconnect_cmd(ar->wmi); | ||
952 | |||
953 | ar->sme_state = SME_DISCONNECTED; | ||
954 | |||
955 | /* disable scanning */ | ||
956 | if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, | ||
957 | 0, 0) != 0) | ||
958 | printk(KERN_WARNING "ath6kl: failed to disable scan " | ||
959 | "during suspend\n"); | ||
960 | |||
961 | ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED); | ||
962 | } | ||
963 | |||
782 | /* WMI Event handlers */ | 964 | /* WMI Event handlers */ |
783 | 965 | ||
784 | static const char *get_hw_id_string(u32 id) | 966 | static const char *get_hw_id_string(u32 id) |
@@ -819,17 +1001,20 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) | |||
819 | set_bit(WMI_READY, &ar->flag); | 1001 | set_bit(WMI_READY, &ar->flag); |
820 | wake_up(&ar->event_wq); | 1002 | wake_up(&ar->event_wq); |
821 | 1003 | ||
822 | ath6kl_info("hw %s fw %s\n", | 1004 | ath6kl_info("hw %s fw %s%s\n", |
823 | get_hw_id_string(ar->wdev->wiphy->hw_version), | 1005 | get_hw_id_string(ar->wdev->wiphy->hw_version), |
824 | ar->wdev->wiphy->fw_version); | 1006 | ar->wdev->wiphy->fw_version, |
1007 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); | ||
825 | } | 1008 | } |
826 | 1009 | ||
827 | void ath6kl_scan_complete_evt(struct ath6kl *ar, int status) | 1010 | void ath6kl_scan_complete_evt(struct ath6kl *ar, int status) |
828 | { | 1011 | { |
829 | ath6kl_cfg80211_scan_complete_event(ar, status); | 1012 | ath6kl_cfg80211_scan_complete_event(ar, status); |
830 | 1013 | ||
831 | if (!ar->usr_bss_filter) | 1014 | if (!ar->usr_bss_filter) { |
1015 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); | ||
832 | ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); | 1016 | ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); |
1017 | } | ||
833 | 1018 | ||
834 | ath6kl_dbg(ATH6KL_DBG_WLAN_SCAN, "scan complete: %d\n", status); | 1019 | ath6kl_dbg(ATH6KL_DBG_WLAN_SCAN, "scan complete: %d\n", status); |
835 | } | 1020 | } |
@@ -842,13 +1027,6 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid, | |||
842 | { | 1027 | { |
843 | unsigned long flags; | 1028 | unsigned long flags; |
844 | 1029 | ||
845 | if (ar->nw_type == AP_NETWORK) { | ||
846 | ath6kl_connect_ap_mode(ar, channel, bssid, listen_int, | ||
847 | beacon_int, assoc_resp_len, | ||
848 | assoc_info); | ||
849 | return; | ||
850 | } | ||
851 | |||
852 | ath6kl_cfg80211_connect_event(ar, channel, bssid, | 1030 | ath6kl_cfg80211_connect_event(ar, channel, bssid, |
853 | listen_int, beacon_int, | 1031 | listen_int, beacon_int, |
854 | net_type, beacon_ie_len, | 1032 | net_type, beacon_ie_len, |
@@ -880,8 +1058,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid, | |||
880 | ar->next_ep_id = ENDPOINT_2; | 1058 | ar->next_ep_id = ENDPOINT_2; |
881 | } | 1059 | } |
882 | 1060 | ||
883 | if (!ar->usr_bss_filter) | 1061 | if (!ar->usr_bss_filter) { |
884 | ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); | 1062 | set_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); |
1063 | ath6kl_wmi_bssfilter_cmd(ar->wmi, CURRENT_BSS_FILTER, 0); | ||
1064 | } | ||
885 | } | 1065 | } |
886 | 1066 | ||
887 | void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast) | 1067 | void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast) |
@@ -915,26 +1095,11 @@ static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len) | |||
915 | (struct wmi_target_stats *) ptr; | 1095 | (struct wmi_target_stats *) ptr; |
916 | struct target_stats *stats = &ar->target_stats; | 1096 | struct target_stats *stats = &ar->target_stats; |
917 | struct tkip_ccmp_stats *ccmp_stats; | 1097 | struct tkip_ccmp_stats *ccmp_stats; |
918 | struct bss *conn_bss = NULL; | ||
919 | struct cserv_stats *c_stats; | ||
920 | u8 ac; | 1098 | u8 ac; |
921 | 1099 | ||
922 | if (len < sizeof(*tgt_stats)) | 1100 | if (len < sizeof(*tgt_stats)) |
923 | return; | 1101 | return; |
924 | 1102 | ||
925 | /* update the RSSI of the connected bss */ | ||
926 | if (test_bit(CONNECTED, &ar->flag)) { | ||
927 | conn_bss = ath6kl_wmi_find_node(ar->wmi, ar->bssid); | ||
928 | if (conn_bss) { | ||
929 | c_stats = &tgt_stats->cserv_stats; | ||
930 | conn_bss->ni_rssi = | ||
931 | a_sle16_to_cpu(c_stats->cs_ave_beacon_rssi); | ||
932 | conn_bss->ni_snr = | ||
933 | tgt_stats->cserv_stats.cs_ave_beacon_snr; | ||
934 | ath6kl_wmi_node_return(ar->wmi, conn_bss); | ||
935 | } | ||
936 | } | ||
937 | |||
938 | ath6kl_dbg(ATH6KL_DBG_TRC, "updating target stats\n"); | 1103 | ath6kl_dbg(ATH6KL_DBG_TRC, "updating target stats\n"); |
939 | 1104 | ||
940 | stats->tx_pkt += le32_to_cpu(tgt_stats->stats.tx.pkt); | 1105 | stats->tx_pkt += le32_to_cpu(tgt_stats->stats.tx.pkt); |
@@ -1165,7 +1330,6 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid, | |||
1165 | u8 assoc_resp_len, u8 *assoc_info, | 1330 | u8 assoc_resp_len, u8 *assoc_info, |
1166 | u16 prot_reason_status) | 1331 | u16 prot_reason_status) |
1167 | { | 1332 | { |
1168 | struct bss *wmi_ssid_node = NULL; | ||
1169 | unsigned long flags; | 1333 | unsigned long flags; |
1170 | 1334 | ||
1171 | if (ar->nw_type == AP_NETWORK) { | 1335 | if (ar->nw_type == AP_NETWORK) { |
@@ -1188,7 +1352,10 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid, | |||
1188 | cfg80211_del_sta(ar->net_dev, bssid, GFP_KERNEL); | 1352 | cfg80211_del_sta(ar->net_dev, bssid, GFP_KERNEL); |
1189 | } | 1353 | } |
1190 | 1354 | ||
1191 | clear_bit(CONNECTED, &ar->flag); | 1355 | if (memcmp(ar->net_dev->dev_addr, bssid, ETH_ALEN) == 0) { |
1356 | memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list)); | ||
1357 | clear_bit(CONNECTED, &ar->flag); | ||
1358 | } | ||
1192 | return; | 1359 | return; |
1193 | } | 1360 | } |
1194 | 1361 | ||
@@ -1222,33 +1389,6 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid, | |||
1222 | } | 1389 | } |
1223 | } | 1390 | } |
1224 | 1391 | ||
1225 | if ((reason == NO_NETWORK_AVAIL) && test_bit(WMI_READY, &ar->flag)) { | ||
1226 | ath6kl_wmi_node_free(ar->wmi, bssid); | ||
1227 | |||
1228 | /* | ||
1229 | * In case any other same SSID nodes are present remove it, | ||
1230 | * since those nodes also not available now. | ||
1231 | */ | ||
1232 | do { | ||
1233 | /* | ||
1234 | * Find the nodes based on SSID and remove it | ||
1235 | * | ||
1236 | * Note: This case will not work out for | ||
1237 | * Hidden-SSID | ||
1238 | */ | ||
1239 | wmi_ssid_node = ath6kl_wmi_find_ssid_node(ar->wmi, | ||
1240 | ar->ssid, | ||
1241 | ar->ssid_len, | ||
1242 | false, | ||
1243 | true); | ||
1244 | |||
1245 | if (wmi_ssid_node) | ||
1246 | ath6kl_wmi_node_free(ar->wmi, | ||
1247 | wmi_ssid_node->ni_macaddr); | ||
1248 | |||
1249 | } while (wmi_ssid_node); | ||
1250 | } | ||
1251 | |||
1252 | /* update connect & link status atomically */ | 1392 | /* update connect & link status atomically */ |
1253 | spin_lock_irqsave(&ar->lock, flags); | 1393 | spin_lock_irqsave(&ar->lock, flags); |
1254 | clear_bit(CONNECTED, &ar->flag); | 1394 | clear_bit(CONNECTED, &ar->flag); |
@@ -1331,7 +1471,7 @@ void init_netdev(struct net_device *dev) | |||
1331 | dev->needed_headroom = ETH_HLEN; | 1471 | dev->needed_headroom = ETH_HLEN; |
1332 | dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) + | 1472 | dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) + |
1333 | sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH | 1473 | sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH |
1334 | + WMI_MAX_TX_META_SZ; | 1474 | + WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES; |
1335 | 1475 | ||
1336 | return; | 1476 | return; |
1337 | } | 1477 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/node.c b/drivers/net/wireless/ath/ath6kl/node.c deleted file mode 100644 index 131205c610b9..000000000000 --- a/drivers/net/wireless/ath/ath6kl/node.c +++ /dev/null | |||
@@ -1,234 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | #include "wmi.h" | ||
19 | #include "debug.h" | ||
20 | |||
21 | struct bss *wlan_node_alloc(int wh_size) | ||
22 | { | ||
23 | struct bss *ni; | ||
24 | |||
25 | ni = kzalloc(sizeof(struct bss), GFP_ATOMIC); | ||
26 | |||
27 | if ((ni != NULL) && wh_size) { | ||
28 | ni->ni_buf = kmalloc(wh_size, GFP_ATOMIC); | ||
29 | if (ni->ni_buf == NULL) { | ||
30 | kfree(ni); | ||
31 | return NULL; | ||
32 | } | ||
33 | } | ||
34 | |||
35 | return ni; | ||
36 | } | ||
37 | |||
38 | void wlan_node_free(struct bss *ni) | ||
39 | { | ||
40 | kfree(ni->ni_buf); | ||
41 | kfree(ni); | ||
42 | } | ||
43 | |||
44 | void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni, | ||
45 | const u8 *mac_addr) | ||
46 | { | ||
47 | int hash; | ||
48 | |||
49 | memcpy(ni->ni_macaddr, mac_addr, ETH_ALEN); | ||
50 | hash = ATH6KL_NODE_HASH(mac_addr); | ||
51 | ni->ni_refcnt = 1; | ||
52 | |||
53 | ni->ni_tstamp = jiffies_to_msecs(jiffies); | ||
54 | ni->ni_actcnt = WLAN_NODE_INACT_CNT; | ||
55 | |||
56 | spin_lock_bh(&nt->nt_nodelock); | ||
57 | |||
58 | /* insert at the end of the node list */ | ||
59 | ni->ni_list_next = NULL; | ||
60 | ni->ni_list_prev = nt->nt_node_last; | ||
61 | if (nt->nt_node_last != NULL) | ||
62 | nt->nt_node_last->ni_list_next = ni; | ||
63 | |||
64 | nt->nt_node_last = ni; | ||
65 | if (nt->nt_node_first == NULL) | ||
66 | nt->nt_node_first = ni; | ||
67 | |||
68 | /* insert into the hash list */ | ||
69 | ni->ni_hash_next = nt->nt_hash[hash]; | ||
70 | if (ni->ni_hash_next != NULL) | ||
71 | nt->nt_hash[hash]->ni_hash_prev = ni; | ||
72 | |||
73 | ni->ni_hash_prev = NULL; | ||
74 | nt->nt_hash[hash] = ni; | ||
75 | |||
76 | spin_unlock_bh(&nt->nt_nodelock); | ||
77 | } | ||
78 | |||
79 | struct bss *wlan_find_node(struct ath6kl_node_table *nt, | ||
80 | const u8 *mac_addr) | ||
81 | { | ||
82 | struct bss *ni, *found_ni = NULL; | ||
83 | int hash; | ||
84 | |||
85 | spin_lock_bh(&nt->nt_nodelock); | ||
86 | |||
87 | hash = ATH6KL_NODE_HASH(mac_addr); | ||
88 | for (ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) { | ||
89 | if (memcmp(ni->ni_macaddr, mac_addr, ETH_ALEN) == 0) { | ||
90 | ni->ni_refcnt++; | ||
91 | found_ni = ni; | ||
92 | break; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | spin_unlock_bh(&nt->nt_nodelock); | ||
97 | |||
98 | return found_ni; | ||
99 | } | ||
100 | |||
101 | void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni) | ||
102 | { | ||
103 | int hash; | ||
104 | |||
105 | spin_lock_bh(&nt->nt_nodelock); | ||
106 | |||
107 | if (ni->ni_list_prev == NULL) | ||
108 | /* fix list head */ | ||
109 | nt->nt_node_first = ni->ni_list_next; | ||
110 | else | ||
111 | ni->ni_list_prev->ni_list_next = ni->ni_list_next; | ||
112 | |||
113 | if (ni->ni_list_next == NULL) | ||
114 | /* fix list tail */ | ||
115 | nt->nt_node_last = ni->ni_list_prev; | ||
116 | else | ||
117 | ni->ni_list_next->ni_list_prev = ni->ni_list_prev; | ||
118 | |||
119 | if (ni->ni_hash_prev == NULL) { | ||
120 | /* first in list so fix the list head */ | ||
121 | hash = ATH6KL_NODE_HASH(ni->ni_macaddr); | ||
122 | nt->nt_hash[hash] = ni->ni_hash_next; | ||
123 | } else { | ||
124 | ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; | ||
125 | } | ||
126 | |||
127 | if (ni->ni_hash_next != NULL) | ||
128 | ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; | ||
129 | |||
130 | wlan_node_free(ni); | ||
131 | |||
132 | spin_unlock_bh(&nt->nt_nodelock); | ||
133 | } | ||
134 | |||
135 | static void wlan_node_dec_free(struct bss *ni) | ||
136 | { | ||
137 | if ((ni->ni_refcnt--) == 1) | ||
138 | wlan_node_free(ni); | ||
139 | } | ||
140 | |||
141 | void wlan_free_allnodes(struct ath6kl_node_table *nt) | ||
142 | { | ||
143 | struct bss *ni; | ||
144 | |||
145 | while ((ni = nt->nt_node_first) != NULL) | ||
146 | wlan_node_reclaim(nt, ni); | ||
147 | } | ||
148 | |||
149 | void wlan_iterate_nodes(struct ath6kl_node_table *nt, void *arg) | ||
150 | { | ||
151 | struct bss *ni; | ||
152 | |||
153 | spin_lock_bh(&nt->nt_nodelock); | ||
154 | for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { | ||
155 | ni->ni_refcnt++; | ||
156 | ath6kl_cfg80211_scan_node(arg, ni); | ||
157 | wlan_node_dec_free(ni); | ||
158 | } | ||
159 | spin_unlock_bh(&nt->nt_nodelock); | ||
160 | } | ||
161 | |||
162 | void wlan_node_table_init(struct ath6kl_node_table *nt) | ||
163 | { | ||
164 | ath6kl_dbg(ATH6KL_DBG_WLAN_NODE, "node table = 0x%lx\n", | ||
165 | (unsigned long)nt); | ||
166 | |||
167 | memset(nt, 0, sizeof(struct ath6kl_node_table)); | ||
168 | |||
169 | spin_lock_init(&nt->nt_nodelock); | ||
170 | |||
171 | nt->nt_node_age = WLAN_NODE_INACT_TIMEOUT_MSEC; | ||
172 | } | ||
173 | |||
174 | void wlan_refresh_inactive_nodes(struct ath6kl *ar) | ||
175 | { | ||
176 | struct ath6kl_node_table *nt = &ar->scan_table; | ||
177 | struct bss *bss; | ||
178 | u32 now; | ||
179 | |||
180 | now = jiffies_to_msecs(jiffies); | ||
181 | bss = nt->nt_node_first; | ||
182 | while (bss != NULL) { | ||
183 | /* refresh all nodes except the current bss */ | ||
184 | if (memcmp(ar->bssid, bss->ni_macaddr, ETH_ALEN) != 0) { | ||
185 | if (((now - bss->ni_tstamp) > nt->nt_node_age) | ||
186 | || --bss->ni_actcnt == 0) { | ||
187 | wlan_node_reclaim(nt, bss); | ||
188 | } | ||
189 | } | ||
190 | bss = bss->ni_list_next; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | void wlan_node_table_cleanup(struct ath6kl_node_table *nt) | ||
195 | { | ||
196 | wlan_free_allnodes(nt); | ||
197 | } | ||
198 | |||
199 | struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 * ssid, | ||
200 | u32 ssid_len, bool is_wpa2, bool match_ssid) | ||
201 | { | ||
202 | struct bss *ni, *found_ni = NULL; | ||
203 | u8 *ie_ssid; | ||
204 | |||
205 | spin_lock_bh(&nt->nt_nodelock); | ||
206 | |||
207 | for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { | ||
208 | |||
209 | ie_ssid = ni->ni_cie.ie_ssid; | ||
210 | |||
211 | if ((ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) && | ||
212 | (memcmp(ssid, &ie_ssid[2], ssid_len) == 0)) { | ||
213 | |||
214 | if (match_ssid || | ||
215 | (is_wpa2 && ni->ni_cie.ie_rsn != NULL) || | ||
216 | (!is_wpa2 && ni->ni_cie.ie_wpa != NULL)) { | ||
217 | ni->ni_refcnt++; | ||
218 | found_ni = ni; | ||
219 | break; | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | |||
224 | spin_unlock_bh(&nt->nt_nodelock); | ||
225 | |||
226 | return found_ni; | ||
227 | } | ||
228 | |||
229 | void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni) | ||
230 | { | ||
231 | spin_lock_bh(&nt->nt_nodelock); | ||
232 | wlan_node_dec_free(ni); | ||
233 | spin_unlock_bh(&nt->nt_nodelock); | ||
234 | } | ||
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 34171604cbe4..f1dc311ee0c7 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "hif-ops.h" | 25 | #include "hif-ops.h" |
26 | #include "target.h" | 26 | #include "target.h" |
27 | #include "debug.h" | 27 | #include "debug.h" |
28 | #include "cfg80211.h" | ||
28 | 29 | ||
29 | struct ath6kl_sdio { | 30 | struct ath6kl_sdio { |
30 | struct sdio_func *func; | 31 | struct sdio_func *func; |
@@ -134,10 +135,12 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr, | |||
134 | int ret = 0; | 135 | int ret = 0; |
135 | 136 | ||
136 | if (request & HIF_WRITE) { | 137 | if (request & HIF_WRITE) { |
138 | /* FIXME: looks like ugly workaround for something */ | ||
137 | if (addr >= HIF_MBOX_BASE_ADDR && | 139 | if (addr >= HIF_MBOX_BASE_ADDR && |
138 | addr <= HIF_MBOX_END_ADDR) | 140 | addr <= HIF_MBOX_END_ADDR) |
139 | addr += (HIF_MBOX_WIDTH - len); | 141 | addr += (HIF_MBOX_WIDTH - len); |
140 | 142 | ||
143 | /* FIXME: this also looks like ugly workaround */ | ||
141 | if (addr == HIF_MBOX0_EXT_BASE_ADDR) | 144 | if (addr == HIF_MBOX0_EXT_BASE_ADDR) |
142 | addr += HIF_MBOX0_EXT_WIDTH - len; | 145 | addr += HIF_MBOX0_EXT_WIDTH - len; |
143 | 146 | ||
@@ -152,6 +155,11 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr, | |||
152 | ret = sdio_memcpy_fromio(func, buf, addr, len); | 155 | ret = sdio_memcpy_fromio(func, buf, addr, len); |
153 | } | 156 | } |
154 | 157 | ||
158 | ath6kl_dbg(ATH6KL_DBG_SDIO, "%s addr 0x%x%s buf 0x%p len %d\n", | ||
159 | request & HIF_WRITE ? "wr" : "rd", addr, | ||
160 | request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len); | ||
161 | ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len); | ||
162 | |||
155 | return ret; | 163 | return ret; |
156 | } | 164 | } |
157 | 165 | ||
@@ -172,7 +180,8 @@ static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio) | |||
172 | list_del(&bus_req->list); | 180 | list_del(&bus_req->list); |
173 | 181 | ||
174 | spin_unlock_irqrestore(&ar_sdio->lock, flag); | 182 | spin_unlock_irqrestore(&ar_sdio->lock, flag); |
175 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req); | 183 | ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n", |
184 | __func__, bus_req); | ||
176 | 185 | ||
177 | return bus_req; | 186 | return bus_req; |
178 | } | 187 | } |
@@ -182,7 +191,8 @@ static void ath6kl_sdio_free_bus_req(struct ath6kl_sdio *ar_sdio, | |||
182 | { | 191 | { |
183 | unsigned long flag; | 192 | unsigned long flag; |
184 | 193 | ||
185 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req); | 194 | ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n", |
195 | __func__, bus_req); | ||
186 | 196 | ||
187 | spin_lock_irqsave(&ar_sdio->lock, flag); | 197 | spin_lock_irqsave(&ar_sdio->lock, flag); |
188 | list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq); | 198 | list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq); |
@@ -213,16 +223,6 @@ static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req, | |||
213 | 223 | ||
214 | /* assemble SG list */ | 224 | /* assemble SG list */ |
215 | for (i = 0; i < scat_req->scat_entries; i++, sg++) { | 225 | for (i = 0; i < scat_req->scat_entries; i++, sg++) { |
216 | if ((unsigned long)scat_req->scat_list[i].buf & 0x3) | ||
217 | /* | ||
218 | * Some scatter engines can handle unaligned | ||
219 | * buffers, print this as informational only. | ||
220 | */ | ||
221 | ath6kl_dbg(ATH6KL_DBG_SCATTER, | ||
222 | "(%s) scatter buffer is unaligned 0x%p\n", | ||
223 | scat_req->req & HIF_WRITE ? "WR" : "RD", | ||
224 | scat_req->scat_list[i].buf); | ||
225 | |||
226 | ath6kl_dbg(ATH6KL_DBG_SCATTER, "%d: addr:0x%p, len:%d\n", | 226 | ath6kl_dbg(ATH6KL_DBG_SCATTER, "%d: addr:0x%p, len:%d\n", |
227 | i, scat_req->scat_list[i].buf, | 227 | i, scat_req->scat_list[i].buf, |
228 | scat_req->scat_list[i].len); | 228 | scat_req->scat_list[i].len); |
@@ -447,6 +447,8 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) | |||
447 | int status; | 447 | int status; |
448 | struct ath6kl_sdio *ar_sdio; | 448 | struct ath6kl_sdio *ar_sdio; |
449 | 449 | ||
450 | ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); | ||
451 | |||
450 | ar_sdio = sdio_get_drvdata(func); | 452 | ar_sdio = sdio_get_drvdata(func); |
451 | atomic_set(&ar_sdio->irq_handling, 1); | 453 | atomic_set(&ar_sdio->irq_handling, 1); |
452 | 454 | ||
@@ -684,7 +686,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar) | |||
684 | MAX_SCATTER_REQUESTS, virt_scat); | 686 | MAX_SCATTER_REQUESTS, virt_scat); |
685 | 687 | ||
686 | if (!ret) { | 688 | if (!ret) { |
687 | ath6kl_dbg(ATH6KL_DBG_ANY, | 689 | ath6kl_dbg(ATH6KL_DBG_SCATTER, |
688 | "hif-scatter enabled: max scatter req : %d entries: %d\n", | 690 | "hif-scatter enabled: max scatter req : %d entries: %d\n", |
689 | MAX_SCATTER_REQUESTS, | 691 | MAX_SCATTER_REQUESTS, |
690 | MAX_SCATTER_ENTRIES_PER_REQ); | 692 | MAX_SCATTER_ENTRIES_PER_REQ); |
@@ -709,7 +711,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar) | |||
709 | return ret; | 711 | return ret; |
710 | } | 712 | } |
711 | 713 | ||
712 | ath6kl_dbg(ATH6KL_DBG_ANY, | 714 | ath6kl_dbg(ATH6KL_DBG_SCATTER, |
713 | "Vitual scatter enabled, max_scat_req:%d, entries:%d\n", | 715 | "Vitual scatter enabled, max_scat_req:%d, entries:%d\n", |
714 | ATH6KL_SCATTER_REQS, ATH6KL_SCATTER_ENTRIES_PER_REQ); | 716 | ATH6KL_SCATTER_REQS, ATH6KL_SCATTER_ENTRIES_PER_REQ); |
715 | 717 | ||
@@ -721,6 +723,34 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar) | |||
721 | return 0; | 723 | return 0; |
722 | } | 724 | } |
723 | 725 | ||
726 | static int ath6kl_sdio_suspend(struct ath6kl *ar) | ||
727 | { | ||
728 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); | ||
729 | struct sdio_func *func = ar_sdio->func; | ||
730 | mmc_pm_flag_t flags; | ||
731 | int ret; | ||
732 | |||
733 | flags = sdio_get_host_pm_caps(func); | ||
734 | |||
735 | if (!(flags & MMC_PM_KEEP_POWER)) | ||
736 | /* as host doesn't support keep power we need to bail out */ | ||
737 | ath6kl_dbg(ATH6KL_DBG_SDIO, | ||
738 | "func %d doesn't support MMC_PM_KEEP_POWER\n", | ||
739 | func->num); | ||
740 | return -EINVAL; | ||
741 | |||
742 | ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | ||
743 | if (ret) { | ||
744 | printk(KERN_ERR "ath6kl: set sdio pm flags failed: %d\n", | ||
745 | ret); | ||
746 | return ret; | ||
747 | } | ||
748 | |||
749 | ath6kl_deep_sleep_enable(ar); | ||
750 | |||
751 | return 0; | ||
752 | } | ||
753 | |||
724 | static const struct ath6kl_hif_ops ath6kl_sdio_ops = { | 754 | static const struct ath6kl_hif_ops ath6kl_sdio_ops = { |
725 | .read_write_sync = ath6kl_sdio_read_write_sync, | 755 | .read_write_sync = ath6kl_sdio_read_write_sync, |
726 | .write_async = ath6kl_sdio_write_async, | 756 | .write_async = ath6kl_sdio_write_async, |
@@ -731,6 +761,7 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = { | |||
731 | .enable_scatter = ath6kl_sdio_enable_scatter, | 761 | .enable_scatter = ath6kl_sdio_enable_scatter, |
732 | .scat_req_rw = ath6kl_sdio_async_rw_scatter, | 762 | .scat_req_rw = ath6kl_sdio_async_rw_scatter, |
733 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, | 763 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, |
764 | .suspend = ath6kl_sdio_suspend, | ||
734 | }; | 765 | }; |
735 | 766 | ||
736 | static int ath6kl_sdio_probe(struct sdio_func *func, | 767 | static int ath6kl_sdio_probe(struct sdio_func *func, |
@@ -741,10 +772,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
741 | struct ath6kl *ar; | 772 | struct ath6kl *ar; |
742 | int count; | 773 | int count; |
743 | 774 | ||
744 | ath6kl_dbg(ATH6KL_DBG_TRC, | 775 | ath6kl_dbg(ATH6KL_DBG_SDIO, |
745 | "%s: func: 0x%X, vendor id: 0x%X, dev id: 0x%X, block size: 0x%X/0x%X\n", | 776 | "new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n", |
746 | __func__, func->num, func->vendor, | 777 | func->num, func->vendor, func->device, |
747 | func->device, func->max_blksize, func->cur_blksize); | 778 | func->max_blksize, func->cur_blksize); |
748 | 779 | ||
749 | ar_sdio = kzalloc(sizeof(struct ath6kl_sdio), GFP_KERNEL); | 780 | ar_sdio = kzalloc(sizeof(struct ath6kl_sdio), GFP_KERNEL); |
750 | if (!ar_sdio) | 781 | if (!ar_sdio) |
@@ -800,10 +831,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
800 | ath6kl_err("Failed to enable 4-bit async irq mode %d\n", | 831 | ath6kl_err("Failed to enable 4-bit async irq mode %d\n", |
801 | ret); | 832 | ret); |
802 | sdio_release_host(func); | 833 | sdio_release_host(func); |
803 | goto err_dma; | 834 | goto err_cfg80211; |
804 | } | 835 | } |
805 | 836 | ||
806 | ath6kl_dbg(ATH6KL_DBG_TRC, "4-bit async irq mode enabled\n"); | 837 | ath6kl_dbg(ATH6KL_DBG_SDIO, "4-bit async irq mode enabled\n"); |
807 | } | 838 | } |
808 | 839 | ||
809 | /* give us some time to enable, in ms */ | 840 | /* give us some time to enable, in ms */ |
@@ -813,7 +844,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
813 | 844 | ||
814 | ret = ath6kl_sdio_power_on(ar_sdio); | 845 | ret = ath6kl_sdio_power_on(ar_sdio); |
815 | if (ret) | 846 | if (ret) |
816 | goto err_dma; | 847 | goto err_cfg80211; |
817 | 848 | ||
818 | sdio_claim_host(func); | 849 | sdio_claim_host(func); |
819 | 850 | ||
@@ -837,6 +868,8 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
837 | 868 | ||
838 | err_off: | 869 | err_off: |
839 | ath6kl_sdio_power_off(ar_sdio); | 870 | ath6kl_sdio_power_off(ar_sdio); |
871 | err_cfg80211: | ||
872 | ath6kl_cfg80211_deinit(ar_sdio->ar); | ||
840 | err_dma: | 873 | err_dma: |
841 | kfree(ar_sdio->dma_buffer); | 874 | kfree(ar_sdio->dma_buffer); |
842 | err_hif: | 875 | err_hif: |
@@ -849,6 +882,10 @@ static void ath6kl_sdio_remove(struct sdio_func *func) | |||
849 | { | 882 | { |
850 | struct ath6kl_sdio *ar_sdio; | 883 | struct ath6kl_sdio *ar_sdio; |
851 | 884 | ||
885 | ath6kl_dbg(ATH6KL_DBG_SDIO, | ||
886 | "removed func %d vendor 0x%x device 0x%x\n", | ||
887 | func->num, func->vendor, func->device); | ||
888 | |||
852 | ar_sdio = sdio_get_drvdata(func); | 889 | ar_sdio = sdio_get_drvdata(func); |
853 | 890 | ||
854 | ath6kl_stop_txrx(ar_sdio->ar); | 891 | ath6kl_stop_txrx(ar_sdio->ar); |
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h index 519a013c9991..c9a76051f042 100644 --- a/drivers/net/wireless/ath/ath6kl/target.h +++ b/drivers/net/wireless/ath/ath6kl/target.h | |||
@@ -20,6 +20,9 @@ | |||
20 | #define AR6003_BOARD_DATA_SZ 1024 | 20 | #define AR6003_BOARD_DATA_SZ 1024 |
21 | #define AR6003_BOARD_EXT_DATA_SZ 768 | 21 | #define AR6003_BOARD_EXT_DATA_SZ 768 |
22 | 22 | ||
23 | #define AR6004_BOARD_DATA_SZ 7168 | ||
24 | #define AR6004_BOARD_EXT_DATA_SZ 0 | ||
25 | |||
23 | #define RESET_CONTROL_ADDRESS 0x00000000 | 26 | #define RESET_CONTROL_ADDRESS 0x00000000 |
24 | #define RESET_CONTROL_COLD_RST 0x00000100 | 27 | #define RESET_CONTROL_COLD_RST 0x00000100 |
25 | #define RESET_CONTROL_MBOX_RST 0x00000004 | 28 | #define RESET_CONTROL_MBOX_RST 0x00000004 |
@@ -135,7 +138,8 @@ | |||
135 | * between the two, and is intended to remain constant (with additions only | 138 | * between the two, and is intended to remain constant (with additions only |
136 | * at the end). | 139 | * at the end). |
137 | */ | 140 | */ |
138 | #define ATH6KL_HI_START_ADDR 0x00540600 | 141 | #define ATH6KL_AR6003_HI_START_ADDR 0x00540600 |
142 | #define ATH6KL_AR6004_HI_START_ADDR 0x00400800 | ||
139 | 143 | ||
140 | /* | 144 | /* |
141 | * These are items that the Host may need to access | 145 | * These are items that the Host may need to access |
@@ -300,6 +304,11 @@ struct host_interest { | |||
300 | #define HI_OPTION_FW_MODE_BSS_STA 0x1 | 304 | #define HI_OPTION_FW_MODE_BSS_STA 0x1 |
301 | #define HI_OPTION_FW_MODE_AP 0x2 | 305 | #define HI_OPTION_FW_MODE_AP 0x2 |
302 | 306 | ||
307 | #define HI_OPTION_FW_SUBMODE_NONE 0x0 | ||
308 | #define HI_OPTION_FW_SUBMODE_P2PDEV 0x1 | ||
309 | #define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2 | ||
310 | #define HI_OPTION_FW_SUBMODE_P2PGO 0x3 | ||
311 | |||
303 | #define HI_OPTION_NUM_DEV_SHIFT 0x9 | 312 | #define HI_OPTION_NUM_DEV_SHIFT 0x9 |
304 | 313 | ||
305 | #define HI_OPTION_FW_BRIDGE_SHIFT 0x04 | 314 | #define HI_OPTION_FW_BRIDGE_SHIFT 0x04 |
@@ -312,20 +321,44 @@ struct host_interest { | |||
312 | |------------------------------------------------------------------------------| | 321 | |------------------------------------------------------------------------------| |
313 | */ | 322 | */ |
314 | #define HI_OPTION_FW_MODE_SHIFT 0xC | 323 | #define HI_OPTION_FW_MODE_SHIFT 0xC |
324 | #define HI_OPTION_FW_SUBMODE_SHIFT 0x14 | ||
315 | 325 | ||
316 | /* Convert a Target virtual address into a Target physical address */ | 326 | /* Convert a Target virtual address into a Target physical address */ |
317 | #define TARG_VTOP(vaddr) (vaddr & 0x001fffff) | 327 | #define AR6003_VTOP(vaddr) ((vaddr) & 0x001fffff) |
328 | #define AR6004_VTOP(vaddr) (vaddr) | ||
329 | |||
330 | #define TARG_VTOP(target_type, vaddr) \ | ||
331 | (((target_type) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \ | ||
332 | (((target_type) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : 0)) | ||
318 | 333 | ||
319 | #define AR6003_REV2_APP_START_OVERRIDE 0x944C00 | ||
320 | #define AR6003_REV2_APP_LOAD_ADDRESS 0x543180 | 334 | #define AR6003_REV2_APP_LOAD_ADDRESS 0x543180 |
321 | #define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500 | 335 | #define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500 |
322 | #define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884 | 336 | #define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884 |
323 | #define AR6003_REV2_RAM_RESERVE_SIZE 6912 | 337 | #define AR6003_REV2_RAM_RESERVE_SIZE 6912 |
324 | 338 | ||
325 | #define AR6003_REV3_APP_START_OVERRIDE 0x945d00 | ||
326 | #define AR6003_REV3_APP_LOAD_ADDRESS 0x545000 | 339 | #define AR6003_REV3_APP_LOAD_ADDRESS 0x545000 |
327 | #define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330 | 340 | #define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330 |
328 | #define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74 | 341 | #define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74 |
329 | #define AR6003_REV3_RAM_RESERVE_SIZE 512 | 342 | #define AR6003_REV3_RAM_RESERVE_SIZE 512 |
330 | 343 | ||
344 | #define AR6004_REV1_BOARD_DATA_ADDRESS 0x435400 | ||
345 | #define AR6004_REV1_BOARD_EXT_DATA_ADDRESS 0x437000 | ||
346 | #define AR6004_REV1_RAM_RESERVE_SIZE 11264 | ||
347 | |||
348 | #define ATH6KL_FWLOG_PAYLOAD_SIZE 1500 | ||
349 | |||
350 | struct ath6kl_dbglog_buf { | ||
351 | __le32 next; | ||
352 | __le32 buffer_addr; | ||
353 | __le32 bufsize; | ||
354 | __le32 length; | ||
355 | __le32 count; | ||
356 | __le32 free; | ||
357 | } __packed; | ||
358 | |||
359 | struct ath6kl_dbglog_hdr { | ||
360 | __le32 dbuf_addr; | ||
361 | __le32 dropped; | ||
362 | } __packed; | ||
363 | |||
331 | #endif | 364 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/testmode.c b/drivers/net/wireless/ath/ath6kl/testmode.c new file mode 100644 index 000000000000..381eb66a605f --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/testmode.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "testmode.h" | ||
18 | |||
19 | #include <net/netlink.h> | ||
20 | |||
21 | enum ath6kl_tm_attr { | ||
22 | __ATH6KL_TM_ATTR_INVALID = 0, | ||
23 | ATH6KL_TM_ATTR_CMD = 1, | ||
24 | ATH6KL_TM_ATTR_DATA = 2, | ||
25 | |||
26 | /* keep last */ | ||
27 | __ATH6KL_TM_ATTR_AFTER_LAST, | ||
28 | ATH6KL_TM_ATTR_MAX = __ATH6KL_TM_ATTR_AFTER_LAST - 1, | ||
29 | }; | ||
30 | |||
31 | enum ath6kl_tm_cmd { | ||
32 | ATH6KL_TM_CMD_TCMD = 0, | ||
33 | ATH6KL_TM_CMD_RX_REPORT = 1, | ||
34 | }; | ||
35 | |||
36 | #define ATH6KL_TM_DATA_MAX_LEN 5000 | ||
37 | |||
38 | static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = { | ||
39 | [ATH6KL_TM_ATTR_CMD] = { .type = NLA_U32 }, | ||
40 | [ATH6KL_TM_ATTR_DATA] = { .type = NLA_BINARY, | ||
41 | .len = ATH6KL_TM_DATA_MAX_LEN }, | ||
42 | }; | ||
43 | |||
44 | void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len) | ||
45 | { | ||
46 | if (down_interruptible(&ar->sem)) | ||
47 | return; | ||
48 | |||
49 | kfree(ar->tm.rx_report); | ||
50 | |||
51 | ar->tm.rx_report = kmemdup(buf, buf_len, GFP_KERNEL); | ||
52 | ar->tm.rx_report_len = buf_len; | ||
53 | |||
54 | up(&ar->sem); | ||
55 | |||
56 | wake_up(&ar->event_wq); | ||
57 | } | ||
58 | |||
59 | static int ath6kl_tm_rx_report(struct ath6kl *ar, void *buf, size_t buf_len, | ||
60 | struct sk_buff *skb) | ||
61 | { | ||
62 | int ret = 0; | ||
63 | long left; | ||
64 | |||
65 | if (down_interruptible(&ar->sem)) | ||
66 | return -ERESTARTSYS; | ||
67 | |||
68 | if (!test_bit(WMI_READY, &ar->flag)) { | ||
69 | ret = -EIO; | ||
70 | goto out; | ||
71 | } | ||
72 | |||
73 | if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { | ||
74 | ret = -EBUSY; | ||
75 | goto out; | ||
76 | } | ||
77 | |||
78 | if (ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len) < 0) { | ||
79 | up(&ar->sem); | ||
80 | return -EIO; | ||
81 | } | ||
82 | |||
83 | left = wait_event_interruptible_timeout(ar->event_wq, | ||
84 | ar->tm.rx_report != NULL, | ||
85 | WMI_TIMEOUT); | ||
86 | |||
87 | if (left == 0) { | ||
88 | ret = -ETIMEDOUT; | ||
89 | goto out; | ||
90 | } else if (left < 0) { | ||
91 | ret = left; | ||
92 | goto out; | ||
93 | } | ||
94 | |||
95 | if (ar->tm.rx_report == NULL || ar->tm.rx_report_len == 0) { | ||
96 | ret = -EINVAL; | ||
97 | goto out; | ||
98 | } | ||
99 | |||
100 | NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, ar->tm.rx_report_len, | ||
101 | ar->tm.rx_report); | ||
102 | |||
103 | kfree(ar->tm.rx_report); | ||
104 | ar->tm.rx_report = NULL; | ||
105 | |||
106 | out: | ||
107 | up(&ar->sem); | ||
108 | |||
109 | return ret; | ||
110 | |||
111 | nla_put_failure: | ||
112 | ret = -ENOBUFS; | ||
113 | goto out; | ||
114 | } | ||
115 | |||
116 | int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) | ||
117 | { | ||
118 | struct ath6kl *ar = wiphy_priv(wiphy); | ||
119 | struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; | ||
120 | int err, buf_len, reply_len; | ||
121 | struct sk_buff *skb; | ||
122 | void *buf; | ||
123 | |||
124 | err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, | ||
125 | ath6kl_tm_policy); | ||
126 | if (err) | ||
127 | return err; | ||
128 | |||
129 | if (!tb[ATH6KL_TM_ATTR_CMD]) | ||
130 | return -EINVAL; | ||
131 | |||
132 | switch (nla_get_u32(tb[ATH6KL_TM_ATTR_CMD])) { | ||
133 | case ATH6KL_TM_CMD_TCMD: | ||
134 | if (!tb[ATH6KL_TM_ATTR_DATA]) | ||
135 | return -EINVAL; | ||
136 | |||
137 | buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); | ||
138 | buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); | ||
139 | |||
140 | ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len); | ||
141 | |||
142 | return 0; | ||
143 | |||
144 | break; | ||
145 | case ATH6KL_TM_CMD_RX_REPORT: | ||
146 | if (!tb[ATH6KL_TM_ATTR_DATA]) | ||
147 | return -EINVAL; | ||
148 | |||
149 | buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); | ||
150 | buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); | ||
151 | |||
152 | reply_len = nla_total_size(ATH6KL_TM_DATA_MAX_LEN); | ||
153 | skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); | ||
154 | if (!skb) | ||
155 | return -ENOMEM; | ||
156 | |||
157 | err = ath6kl_tm_rx_report(ar, buf, buf_len, skb); | ||
158 | if (err < 0) { | ||
159 | kfree_skb(skb); | ||
160 | return err; | ||
161 | } | ||
162 | |||
163 | return cfg80211_testmode_reply(skb); | ||
164 | default: | ||
165 | return -EOPNOTSUPP; | ||
166 | } | ||
167 | } | ||
diff --git a/drivers/net/wireless/ath/ath6kl/testmode.h b/drivers/net/wireless/ath/ath6kl/testmode.h new file mode 100644 index 000000000000..43dffcc11fb1 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/testmode.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "core.h" | ||
18 | |||
19 | #ifdef CONFIG_NL80211_TESTMODE | ||
20 | |||
21 | void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len); | ||
22 | int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len); | ||
23 | |||
24 | #else | ||
25 | |||
26 | static inline void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, | ||
27 | size_t buf_len) | ||
28 | { | ||
29 | } | ||
30 | |||
31 | static inline int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) | ||
32 | { | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | #endif | ||
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 167bdb9cf68d..a7117074f81c 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -239,7 +239,6 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) | |||
239 | u16 htc_tag = ATH6KL_DATA_PKT_TAG; | 239 | u16 htc_tag = ATH6KL_DATA_PKT_TAG; |
240 | u8 ac = 99 ; /* initialize to unmapped ac */ | 240 | u8 ac = 99 ; /* initialize to unmapped ac */ |
241 | bool chk_adhoc_ps_mapping = false, more_data = false; | 241 | bool chk_adhoc_ps_mapping = false, more_data = false; |
242 | struct wmi_tx_meta_v2 meta_v2; | ||
243 | int ret; | 242 | int ret; |
244 | 243 | ||
245 | ath6kl_dbg(ATH6KL_DBG_WLAN_TX, | 244 | ath6kl_dbg(ATH6KL_DBG_WLAN_TX, |
@@ -262,8 +261,6 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) | |||
262 | } | 261 | } |
263 | 262 | ||
264 | if (test_bit(WMI_ENABLED, &ar->flag)) { | 263 | if (test_bit(WMI_ENABLED, &ar->flag)) { |
265 | memset(&meta_v2, 0, sizeof(meta_v2)); | ||
266 | |||
267 | if (skb_headroom(skb) < dev->needed_headroom) { | 264 | if (skb_headroom(skb) < dev->needed_headroom) { |
268 | WARN_ON(1); | 265 | WARN_ON(1); |
269 | goto fail_tx; | 266 | goto fail_tx; |
@@ -320,12 +317,31 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) | |||
320 | 317 | ||
321 | spin_unlock_bh(&ar->lock); | 318 | spin_unlock_bh(&ar->lock); |
322 | 319 | ||
320 | if (!IS_ALIGNED((unsigned long) skb->data - HTC_HDR_LENGTH, 4) && | ||
321 | skb_cloned(skb)) { | ||
322 | /* | ||
323 | * We will touch (move the buffer data to align it. Since the | ||
324 | * skb buffer is cloned and not only the header is changed, we | ||
325 | * have to copy it to allow the changes. Since we are copying | ||
326 | * the data here, we may as well align it by reserving suitable | ||
327 | * headroom to avoid the memmove in ath6kl_htc_tx_buf_align(). | ||
328 | */ | ||
329 | struct sk_buff *nskb; | ||
330 | |||
331 | nskb = skb_copy_expand(skb, HTC_HDR_LENGTH, 0, GFP_ATOMIC); | ||
332 | if (nskb == NULL) | ||
333 | goto fail_tx; | ||
334 | kfree_skb(skb); | ||
335 | skb = nskb; | ||
336 | } | ||
337 | |||
323 | cookie->skb = skb; | 338 | cookie->skb = skb; |
324 | cookie->map_no = map_no; | 339 | cookie->map_no = map_no; |
325 | set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len, | 340 | set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len, |
326 | eid, htc_tag); | 341 | eid, htc_tag); |
327 | 342 | ||
328 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len); | 343 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "tx ", |
344 | skb->data, skb->len); | ||
329 | 345 | ||
330 | /* | 346 | /* |
331 | * HTC interface is asynchronous, if this fails, cleanup will | 347 | * HTC interface is asynchronous, if this fails, cleanup will |
@@ -689,6 +705,8 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint) | |||
689 | break; | 705 | break; |
690 | 706 | ||
691 | packet = (struct htc_packet *) skb->head; | 707 | packet = (struct htc_packet *) skb->head; |
708 | if (!IS_ALIGNED((unsigned long) skb->data, 4)) | ||
709 | skb->data = PTR_ALIGN(skb->data - 4, 4); | ||
692 | set_htc_rxpkt_info(packet, skb, skb->data, | 710 | set_htc_rxpkt_info(packet, skb, skb->data, |
693 | ATH6KL_BUFFER_SIZE, endpoint); | 711 | ATH6KL_BUFFER_SIZE, endpoint); |
694 | list_add_tail(&packet->list, &queue); | 712 | list_add_tail(&packet->list, &queue); |
@@ -709,6 +727,8 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count) | |||
709 | return; | 727 | return; |
710 | 728 | ||
711 | packet = (struct htc_packet *) skb->head; | 729 | packet = (struct htc_packet *) skb->head; |
730 | if (!IS_ALIGNED((unsigned long) skb->data, 4)) | ||
731 | skb->data = PTR_ALIGN(skb->data - 4, 4); | ||
712 | set_htc_rxpkt_info(packet, skb, skb->data, | 732 | set_htc_rxpkt_info(packet, skb, skb->data, |
713 | ATH6KL_AMSDU_BUFFER_SIZE, 0); | 733 | ATH6KL_AMSDU_BUFFER_SIZE, 0); |
714 | spin_lock_bh(&ar->lock); | 734 | spin_lock_bh(&ar->lock); |
@@ -812,7 +832,7 @@ static void aggr_slice_amsdu(struct aggr_info *p_aggr, | |||
812 | /* Add the length of A-MSDU subframe padding bytes - | 832 | /* Add the length of A-MSDU subframe padding bytes - |
813 | * Round to nearest word. | 833 | * Round to nearest word. |
814 | */ | 834 | */ |
815 | frame_8023_len = ALIGN(frame_8023_len + 3, 3); | 835 | frame_8023_len = ALIGN(frame_8023_len, 4); |
816 | 836 | ||
817 | framep += frame_8023_len; | 837 | framep += frame_8023_len; |
818 | amsdu_len -= frame_8023_len; | 838 | amsdu_len -= frame_8023_len; |
@@ -1044,12 +1064,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1044 | ar->net_stats.rx_packets++; | 1064 | ar->net_stats.rx_packets++; |
1045 | ar->net_stats.rx_bytes += packet->act_len; | 1065 | ar->net_stats.rx_bytes += packet->act_len; |
1046 | 1066 | ||
1067 | spin_unlock_bh(&ar->lock); | ||
1068 | |||
1047 | skb_put(skb, packet->act_len + HTC_HDR_LENGTH); | 1069 | skb_put(skb, packet->act_len + HTC_HDR_LENGTH); |
1048 | skb_pull(skb, HTC_HDR_LENGTH); | 1070 | skb_pull(skb, HTC_HDR_LENGTH); |
1049 | 1071 | ||
1050 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len); | 1072 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ", |
1051 | 1073 | skb->data, skb->len); | |
1052 | spin_unlock_bh(&ar->lock); | ||
1053 | 1074 | ||
1054 | skb->dev = ar->net_dev; | 1075 | skb->dev = ar->net_dev; |
1055 | 1076 | ||
@@ -1065,9 +1086,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1065 | return; | 1086 | return; |
1066 | } | 1087 | } |
1067 | 1088 | ||
1068 | min_hdr_len = sizeof(struct ethhdr); | 1089 | min_hdr_len = sizeof(struct ethhdr) + sizeof(struct wmi_data_hdr) + |
1069 | min_hdr_len += sizeof(struct wmi_data_hdr) + | 1090 | sizeof(struct ath6kl_llc_snap_hdr); |
1070 | sizeof(struct ath6kl_llc_snap_hdr); | ||
1071 | 1091 | ||
1072 | dhdr = (struct wmi_data_hdr *) skb->data; | 1092 | dhdr = (struct wmi_data_hdr *) skb->data; |
1073 | 1093 | ||
@@ -1163,8 +1183,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1163 | seq_no = wmi_data_hdr_get_seqno(dhdr); | 1183 | seq_no = wmi_data_hdr_get_seqno(dhdr); |
1164 | meta_type = wmi_data_hdr_get_meta(dhdr); | 1184 | meta_type = wmi_data_hdr_get_meta(dhdr); |
1165 | dot11_hdr = wmi_data_hdr_get_dot11(dhdr); | 1185 | dot11_hdr = wmi_data_hdr_get_dot11(dhdr); |
1166 | 1186 | skb_pull(skb, sizeof(struct wmi_data_hdr)); | |
1167 | ath6kl_wmi_data_hdr_remove(ar->wmi, skb); | ||
1168 | 1187 | ||
1169 | switch (meta_type) { | 1188 | switch (meta_type) { |
1170 | case WMI_META_VERSION_1: | 1189 | case WMI_META_VERSION_1: |
@@ -1231,9 +1250,15 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1231 | ath6kl_data_tx(skb1, ar->net_dev); | 1250 | ath6kl_data_tx(skb1, ar->net_dev); |
1232 | } | 1251 | } |
1233 | 1252 | ||
1234 | if (!aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, | 1253 | datap = (struct ethhdr *) skb->data; |
1235 | is_amsdu, skb)) | 1254 | |
1236 | ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb); | 1255 | if (is_unicast_ether_addr(datap->h_dest) && |
1256 | aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, | ||
1257 | is_amsdu, skb)) | ||
1258 | /* aggregation code will handle the skb */ | ||
1259 | return; | ||
1260 | |||
1261 | ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb); | ||
1237 | } | 1262 | } |
1238 | 1263 | ||
1239 | static void aggr_timeout(unsigned long arg) | 1264 | static void aggr_timeout(unsigned long arg) |
@@ -1250,10 +1275,6 @@ static void aggr_timeout(unsigned long arg) | |||
1250 | if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) | 1275 | if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) |
1251 | continue; | 1276 | continue; |
1252 | 1277 | ||
1253 | /* | ||
1254 | * FIXME: these timeouts happen quite fruently, something | ||
1255 | * line once within 60 seconds. Investigate why. | ||
1256 | */ | ||
1257 | stats->num_timeouts++; | 1278 | stats->num_timeouts++; |
1258 | ath6kl_dbg(ATH6KL_DBG_AGGR, | 1279 | ath6kl_dbg(ATH6KL_DBG_AGGR, |
1259 | "aggr timeout (st %d end %d)\n", | 1280 | "aggr timeout (st %d end %d)\n", |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index f5aa33dd4c42..a7de23cbd2c7 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -17,6 +17,9 @@ | |||
17 | #include <linux/ip.h> | 17 | #include <linux/ip.h> |
18 | #include "core.h" | 18 | #include "core.h" |
19 | #include "debug.h" | 19 | #include "debug.h" |
20 | #include "testmode.h" | ||
21 | #include "../regd.h" | ||
22 | #include "../regd_common.h" | ||
20 | 23 | ||
21 | static int ath6kl_wmi_sync_point(struct wmi *wmi); | 24 | static int ath6kl_wmi_sync_point(struct wmi *wmi); |
22 | 25 | ||
@@ -167,9 +170,11 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, | |||
167 | if (WARN_ON(skb == NULL)) | 170 | if (WARN_ON(skb == NULL)) |
168 | return -EINVAL; | 171 | return -EINVAL; |
169 | 172 | ||
170 | ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info); | 173 | if (tx_meta_info) { |
171 | if (ret) | 174 | ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info); |
172 | return ret; | 175 | if (ret) |
176 | return ret; | ||
177 | } | ||
173 | 178 | ||
174 | skb_push(skb, sizeof(struct wmi_data_hdr)); | 179 | skb_push(skb, sizeof(struct wmi_data_hdr)); |
175 | 180 | ||
@@ -376,35 +381,6 @@ int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb) | |||
376 | return 0; | 381 | return 0; |
377 | } | 382 | } |
378 | 383 | ||
379 | int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb) | ||
380 | { | ||
381 | if (WARN_ON(skb == NULL)) | ||
382 | return -EINVAL; | ||
383 | |||
384 | skb_pull(skb, sizeof(struct wmi_data_hdr)); | ||
385 | |||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static void ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(struct sk_buff *skb, | ||
390 | u8 *datap) | ||
391 | { | ||
392 | struct wmi_bss_info_hdr2 bih2; | ||
393 | struct wmi_bss_info_hdr *bih; | ||
394 | |||
395 | memcpy(&bih2, datap, sizeof(struct wmi_bss_info_hdr2)); | ||
396 | |||
397 | skb_push(skb, 4); | ||
398 | bih = (struct wmi_bss_info_hdr *) skb->data; | ||
399 | |||
400 | bih->ch = bih2.ch; | ||
401 | bih->frame_type = bih2.frame_type; | ||
402 | bih->snr = bih2.snr; | ||
403 | bih->rssi = a_cpu_to_sle16(bih2.snr - 95); | ||
404 | bih->ie_mask = cpu_to_le32(le16_to_cpu(bih2.ie_mask)); | ||
405 | memcpy(bih->bssid, bih2.bssid, ETH_ALEN); | ||
406 | } | ||
407 | |||
408 | static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) | 384 | static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) |
409 | { | 385 | { |
410 | struct tx_complete_msg_v1 *msg_v1; | 386 | struct tx_complete_msg_v1 *msg_v1; |
@@ -433,6 +409,201 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) | |||
433 | return 0; | 409 | return 0; |
434 | } | 410 | } |
435 | 411 | ||
412 | static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap, | ||
413 | int len) | ||
414 | { | ||
415 | struct wmi_remain_on_chnl_event *ev; | ||
416 | u32 freq; | ||
417 | u32 dur; | ||
418 | struct ieee80211_channel *chan; | ||
419 | struct ath6kl *ar = wmi->parent_dev; | ||
420 | |||
421 | if (len < sizeof(*ev)) | ||
422 | return -EINVAL; | ||
423 | |||
424 | ev = (struct wmi_remain_on_chnl_event *) datap; | ||
425 | freq = le32_to_cpu(ev->freq); | ||
426 | dur = le32_to_cpu(ev->duration); | ||
427 | ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: freq=%u dur=%u\n", | ||
428 | freq, dur); | ||
429 | chan = ieee80211_get_channel(ar->wdev->wiphy, freq); | ||
430 | if (!chan) { | ||
431 | ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel " | ||
432 | "(freq=%u)\n", freq); | ||
433 | return -EINVAL; | ||
434 | } | ||
435 | cfg80211_ready_on_channel(ar->net_dev, 1, chan, NL80211_CHAN_NO_HT, | ||
436 | dur, GFP_ATOMIC); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi, | ||
442 | u8 *datap, int len) | ||
443 | { | ||
444 | struct wmi_cancel_remain_on_chnl_event *ev; | ||
445 | u32 freq; | ||
446 | u32 dur; | ||
447 | struct ieee80211_channel *chan; | ||
448 | struct ath6kl *ar = wmi->parent_dev; | ||
449 | |||
450 | if (len < sizeof(*ev)) | ||
451 | return -EINVAL; | ||
452 | |||
453 | ev = (struct wmi_cancel_remain_on_chnl_event *) datap; | ||
454 | freq = le32_to_cpu(ev->freq); | ||
455 | dur = le32_to_cpu(ev->duration); | ||
456 | ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u " | ||
457 | "status=%u\n", freq, dur, ev->status); | ||
458 | chan = ieee80211_get_channel(ar->wdev->wiphy, freq); | ||
459 | if (!chan) { | ||
460 | ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown " | ||
461 | "channel (freq=%u)\n", freq); | ||
462 | return -EINVAL; | ||
463 | } | ||
464 | cfg80211_remain_on_channel_expired(ar->net_dev, 1, chan, | ||
465 | NL80211_CHAN_NO_HT, GFP_ATOMIC); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len) | ||
471 | { | ||
472 | struct wmi_tx_status_event *ev; | ||
473 | u32 id; | ||
474 | struct ath6kl *ar = wmi->parent_dev; | ||
475 | |||
476 | if (len < sizeof(*ev)) | ||
477 | return -EINVAL; | ||
478 | |||
479 | ev = (struct wmi_tx_status_event *) datap; | ||
480 | id = le32_to_cpu(ev->id); | ||
481 | ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n", | ||
482 | id, ev->ack_status); | ||
483 | if (wmi->last_mgmt_tx_frame) { | ||
484 | cfg80211_mgmt_tx_status(ar->net_dev, id, | ||
485 | wmi->last_mgmt_tx_frame, | ||
486 | wmi->last_mgmt_tx_frame_len, | ||
487 | !!ev->ack_status, GFP_ATOMIC); | ||
488 | kfree(wmi->last_mgmt_tx_frame); | ||
489 | wmi->last_mgmt_tx_frame = NULL; | ||
490 | wmi->last_mgmt_tx_frame_len = 0; | ||
491 | } | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len) | ||
497 | { | ||
498 | struct wmi_p2p_rx_probe_req_event *ev; | ||
499 | u32 freq; | ||
500 | u16 dlen; | ||
501 | struct ath6kl *ar = wmi->parent_dev; | ||
502 | |||
503 | if (len < sizeof(*ev)) | ||
504 | return -EINVAL; | ||
505 | |||
506 | ev = (struct wmi_p2p_rx_probe_req_event *) datap; | ||
507 | freq = le32_to_cpu(ev->freq); | ||
508 | dlen = le16_to_cpu(ev->len); | ||
509 | if (datap + len < ev->data + dlen) { | ||
510 | ath6kl_err("invalid wmi_p2p_rx_probe_req_event: " | ||
511 | "len=%d dlen=%u\n", len, dlen); | ||
512 | return -EINVAL; | ||
513 | } | ||
514 | ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u " | ||
515 | "probe_req_report=%d\n", | ||
516 | dlen, freq, ar->probe_req_report); | ||
517 | |||
518 | if (ar->probe_req_report || ar->nw_type == AP_NETWORK) | ||
519 | cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC); | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static int ath6kl_wmi_p2p_capabilities_event_rx(u8 *datap, int len) | ||
525 | { | ||
526 | struct wmi_p2p_capabilities_event *ev; | ||
527 | u16 dlen; | ||
528 | |||
529 | if (len < sizeof(*ev)) | ||
530 | return -EINVAL; | ||
531 | |||
532 | ev = (struct wmi_p2p_capabilities_event *) datap; | ||
533 | dlen = le16_to_cpu(ev->len); | ||
534 | ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_capab: len=%u\n", dlen); | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len) | ||
540 | { | ||
541 | struct wmi_rx_action_event *ev; | ||
542 | u32 freq; | ||
543 | u16 dlen; | ||
544 | struct ath6kl *ar = wmi->parent_dev; | ||
545 | |||
546 | if (len < sizeof(*ev)) | ||
547 | return -EINVAL; | ||
548 | |||
549 | ev = (struct wmi_rx_action_event *) datap; | ||
550 | freq = le32_to_cpu(ev->freq); | ||
551 | dlen = le16_to_cpu(ev->len); | ||
552 | if (datap + len < ev->data + dlen) { | ||
553 | ath6kl_err("invalid wmi_rx_action_event: " | ||
554 | "len=%d dlen=%u\n", len, dlen); | ||
555 | return -EINVAL; | ||
556 | } | ||
557 | ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); | ||
558 | cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static int ath6kl_wmi_p2p_info_event_rx(u8 *datap, int len) | ||
564 | { | ||
565 | struct wmi_p2p_info_event *ev; | ||
566 | u32 flags; | ||
567 | u16 dlen; | ||
568 | |||
569 | if (len < sizeof(*ev)) | ||
570 | return -EINVAL; | ||
571 | |||
572 | ev = (struct wmi_p2p_info_event *) datap; | ||
573 | flags = le32_to_cpu(ev->info_req_flags); | ||
574 | dlen = le16_to_cpu(ev->len); | ||
575 | ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: flags=%x len=%d\n", flags, dlen); | ||
576 | |||
577 | if (flags & P2P_FLAG_CAPABILITIES_REQ) { | ||
578 | struct wmi_p2p_capabilities *cap; | ||
579 | if (dlen < sizeof(*cap)) | ||
580 | return -EINVAL; | ||
581 | cap = (struct wmi_p2p_capabilities *) ev->data; | ||
582 | ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: GO Power Save = %d\n", | ||
583 | cap->go_power_save); | ||
584 | } | ||
585 | |||
586 | if (flags & P2P_FLAG_MACADDR_REQ) { | ||
587 | struct wmi_p2p_macaddr *mac; | ||
588 | if (dlen < sizeof(*mac)) | ||
589 | return -EINVAL; | ||
590 | mac = (struct wmi_p2p_macaddr *) ev->data; | ||
591 | ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: MAC Address = %pM\n", | ||
592 | mac->mac_addr); | ||
593 | } | ||
594 | |||
595 | if (flags & P2P_FLAG_HMODEL_REQ) { | ||
596 | struct wmi_p2p_hmodel *mod; | ||
597 | if (dlen < sizeof(*mod)) | ||
598 | return -EINVAL; | ||
599 | mod = (struct wmi_p2p_hmodel *) ev->data; | ||
600 | ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: P2P Model = %d (%s)\n", | ||
601 | mod->p2p_model, | ||
602 | mod->p2p_model ? "host" : "firmware"); | ||
603 | } | ||
604 | return 0; | ||
605 | } | ||
606 | |||
436 | static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size) | 607 | static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size) |
437 | { | 608 | { |
438 | struct sk_buff *skb; | 609 | struct sk_buff *skb; |
@@ -478,18 +649,84 @@ static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len) | |||
478 | return 0; | 649 | return 0; |
479 | } | 650 | } |
480 | 651 | ||
652 | /* | ||
653 | * Mechanism to modify the roaming behavior in the firmware. The lower rssi | ||
654 | * at which the station has to roam can be passed with | ||
655 | * WMI_SET_LRSSI_SCAN_PARAMS. Subtract 96 from RSSI to get the signal level | ||
656 | * in dBm. | ||
657 | */ | ||
658 | int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi) | ||
659 | { | ||
660 | struct sk_buff *skb; | ||
661 | struct roam_ctrl_cmd *cmd; | ||
662 | |||
663 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
664 | if (!skb) | ||
665 | return -ENOMEM; | ||
666 | |||
667 | cmd = (struct roam_ctrl_cmd *) skb->data; | ||
668 | |||
669 | cmd->info.params.lrssi_scan_period = cpu_to_le16(DEF_LRSSI_SCAN_PERIOD); | ||
670 | cmd->info.params.lrssi_scan_threshold = a_cpu_to_sle16(lrssi + | ||
671 | DEF_SCAN_FOR_ROAM_INTVL); | ||
672 | cmd->info.params.lrssi_roam_threshold = a_cpu_to_sle16(lrssi); | ||
673 | cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR; | ||
674 | cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS; | ||
675 | |||
676 | ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_ROAM_CTRL_CMDID, NO_SYNC_WMIFLAG); | ||
677 | |||
678 | return 0; | ||
679 | } | ||
680 | |||
481 | static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len) | 681 | static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len) |
482 | { | 682 | { |
483 | struct wmi_connect_event *ev; | 683 | struct wmi_connect_event *ev; |
484 | u8 *pie, *peie; | 684 | u8 *pie, *peie; |
685 | struct ath6kl *ar = wmi->parent_dev; | ||
485 | 686 | ||
486 | if (len < sizeof(struct wmi_connect_event)) | 687 | if (len < sizeof(struct wmi_connect_event)) |
487 | return -EINVAL; | 688 | return -EINVAL; |
488 | 689 | ||
489 | ev = (struct wmi_connect_event *) datap; | 690 | ev = (struct wmi_connect_event *) datap; |
490 | 691 | ||
491 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM\n", | 692 | if (ar->nw_type == AP_NETWORK) { |
492 | __func__, ev->ch, ev->bssid); | 693 | /* AP mode start/STA connected event */ |
694 | struct net_device *dev = ar->net_dev; | ||
695 | if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) { | ||
696 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM " | ||
697 | "(AP started)\n", | ||
698 | __func__, le16_to_cpu(ev->u.ap_bss.ch), | ||
699 | ev->u.ap_bss.bssid); | ||
700 | ath6kl_connect_ap_mode_bss( | ||
701 | ar, le16_to_cpu(ev->u.ap_bss.ch)); | ||
702 | } else { | ||
703 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM " | ||
704 | "auth=%u keymgmt=%u cipher=%u apsd_info=%u " | ||
705 | "(STA connected)\n", | ||
706 | __func__, ev->u.ap_sta.aid, | ||
707 | ev->u.ap_sta.mac_addr, | ||
708 | ev->u.ap_sta.auth, | ||
709 | ev->u.ap_sta.keymgmt, | ||
710 | le16_to_cpu(ev->u.ap_sta.cipher), | ||
711 | ev->u.ap_sta.apsd_info); | ||
712 | ath6kl_connect_ap_mode_sta( | ||
713 | ar, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, | ||
714 | ev->u.ap_sta.keymgmt, | ||
715 | le16_to_cpu(ev->u.ap_sta.cipher), | ||
716 | ev->u.ap_sta.auth, ev->assoc_req_len, | ||
717 | ev->assoc_info + ev->beacon_ie_len); | ||
718 | } | ||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | /* STA/IBSS mode connection event */ | ||
723 | |||
724 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
725 | "wmi event connect freq %d bssid %pM listen_intvl %d beacon_intvl %d type %d\n", | ||
726 | le16_to_cpu(ev->u.sta.ch), ev->u.sta.bssid, | ||
727 | le16_to_cpu(ev->u.sta.listen_intvl), | ||
728 | le16_to_cpu(ev->u.sta.beacon_intvl), | ||
729 | le32_to_cpu(ev->u.sta.nw_type)); | ||
493 | 730 | ||
494 | /* Start of assoc rsp IEs */ | 731 | /* Start of assoc rsp IEs */ |
495 | pie = ev->assoc_info + ev->beacon_ie_len + | 732 | pie = ev->assoc_info + ev->beacon_ie_len + |
@@ -518,16 +755,92 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len) | |||
518 | pie += pie[1] + 2; | 755 | pie += pie[1] + 2; |
519 | } | 756 | } |
520 | 757 | ||
521 | ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->ch), ev->bssid, | 758 | ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->u.sta.ch), |
522 | le16_to_cpu(ev->listen_intvl), | 759 | ev->u.sta.bssid, |
523 | le16_to_cpu(ev->beacon_intvl), | 760 | le16_to_cpu(ev->u.sta.listen_intvl), |
524 | le32_to_cpu(ev->nw_type), | 761 | le16_to_cpu(ev->u.sta.beacon_intvl), |
762 | le32_to_cpu(ev->u.sta.nw_type), | ||
525 | ev->beacon_ie_len, ev->assoc_req_len, | 763 | ev->beacon_ie_len, ev->assoc_req_len, |
526 | ev->assoc_resp_len, ev->assoc_info); | 764 | ev->assoc_resp_len, ev->assoc_info); |
527 | 765 | ||
528 | return 0; | 766 | return 0; |
529 | } | 767 | } |
530 | 768 | ||
769 | static struct country_code_to_enum_rd * | ||
770 | ath6kl_regd_find_country(u16 countryCode) | ||
771 | { | ||
772 | int i; | ||
773 | |||
774 | for (i = 0; i < ARRAY_SIZE(allCountries); i++) { | ||
775 | if (allCountries[i].countryCode == countryCode) | ||
776 | return &allCountries[i]; | ||
777 | } | ||
778 | |||
779 | return NULL; | ||
780 | } | ||
781 | |||
782 | static struct reg_dmn_pair_mapping * | ||
783 | ath6kl_get_regpair(u16 regdmn) | ||
784 | { | ||
785 | int i; | ||
786 | |||
787 | if (regdmn == NO_ENUMRD) | ||
788 | return NULL; | ||
789 | |||
790 | for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { | ||
791 | if (regDomainPairs[i].regDmnEnum == regdmn) | ||
792 | return ®DomainPairs[i]; | ||
793 | } | ||
794 | |||
795 | return NULL; | ||
796 | } | ||
797 | |||
798 | static struct country_code_to_enum_rd * | ||
799 | ath6kl_regd_find_country_by_rd(u16 regdmn) | ||
800 | { | ||
801 | int i; | ||
802 | |||
803 | for (i = 0; i < ARRAY_SIZE(allCountries); i++) { | ||
804 | if (allCountries[i].regDmnEnum == regdmn) | ||
805 | return &allCountries[i]; | ||
806 | } | ||
807 | |||
808 | return NULL; | ||
809 | } | ||
810 | |||
811 | static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len) | ||
812 | { | ||
813 | |||
814 | struct ath6kl_wmi_regdomain *ev; | ||
815 | struct country_code_to_enum_rd *country = NULL; | ||
816 | struct reg_dmn_pair_mapping *regpair = NULL; | ||
817 | char alpha2[2]; | ||
818 | u32 reg_code; | ||
819 | |||
820 | ev = (struct ath6kl_wmi_regdomain *) datap; | ||
821 | reg_code = le32_to_cpu(ev->reg_code); | ||
822 | |||
823 | if ((reg_code >> ATH6KL_COUNTRY_RD_SHIFT) & COUNTRY_ERD_FLAG) | ||
824 | country = ath6kl_regd_find_country((u16) reg_code); | ||
825 | else if (!(((u16) reg_code & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)) { | ||
826 | |||
827 | regpair = ath6kl_get_regpair((u16) reg_code); | ||
828 | country = ath6kl_regd_find_country_by_rd((u16) reg_code); | ||
829 | ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n", | ||
830 | regpair->regDmnEnum); | ||
831 | } | ||
832 | |||
833 | if (country) { | ||
834 | alpha2[0] = country->isoName[0]; | ||
835 | alpha2[1] = country->isoName[1]; | ||
836 | |||
837 | regulatory_hint(wmi->parent_dev->wdev->wiphy, alpha2); | ||
838 | |||
839 | ath6kl_dbg(ATH6KL_DBG_WMI, "Country alpha2 being used: %c%c\n", | ||
840 | alpha2[0], alpha2[1]); | ||
841 | } | ||
842 | } | ||
843 | |||
531 | static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len) | 844 | static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len) |
532 | { | 845 | { |
533 | struct wmi_disconnect_event *ev; | 846 | struct wmi_disconnect_event *ev; |
@@ -538,6 +851,11 @@ static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len) | |||
538 | 851 | ||
539 | ev = (struct wmi_disconnect_event *) datap; | 852 | ev = (struct wmi_disconnect_event *) datap; |
540 | 853 | ||
854 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
855 | "wmi event disconnect proto_reason %d bssid %pM wmi_reason %d assoc_resp_len %d\n", | ||
856 | le16_to_cpu(ev->proto_reason_status), ev->bssid, | ||
857 | ev->disconn_reason, ev->assoc_resp_len); | ||
858 | |||
541 | wmi->is_wmm_enabled = false; | 859 | wmi->is_wmm_enabled = false; |
542 | wmi->pair_crypto_type = NONE_CRYPT; | 860 | wmi->pair_crypto_type = NONE_CRYPT; |
543 | wmi->grp_crypto_type = NONE_CRYPT; | 861 | wmi->grp_crypto_type = NONE_CRYPT; |
@@ -582,315 +900,92 @@ static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len) | |||
582 | return 0; | 900 | return 0; |
583 | } | 901 | } |
584 | 902 | ||
585 | static int ath6kl_wlan_parse_beacon(u8 *buf, int frame_len, | ||
586 | struct ath6kl_common_ie *cie) | ||
587 | { | ||
588 | u8 *frm, *efrm; | ||
589 | u8 elemid_ssid = false; | ||
590 | |||
591 | frm = buf; | ||
592 | efrm = (u8 *) (frm + frame_len); | ||
593 | |||
594 | /* | ||
595 | * beacon/probe response frame format | ||
596 | * [8] time stamp | ||
597 | * [2] beacon interval | ||
598 | * [2] capability information | ||
599 | * [tlv] ssid | ||
600 | * [tlv] supported rates | ||
601 | * [tlv] country information | ||
602 | * [tlv] parameter set (FH/DS) | ||
603 | * [tlv] erp information | ||
604 | * [tlv] extended supported rates | ||
605 | * [tlv] WMM | ||
606 | * [tlv] WPA or RSN | ||
607 | * [tlv] Atheros Advanced Capabilities | ||
608 | */ | ||
609 | if ((efrm - frm) < 12) | ||
610 | return -EINVAL; | ||
611 | |||
612 | memset(cie, 0, sizeof(*cie)); | ||
613 | |||
614 | cie->ie_tstamp = frm; | ||
615 | frm += 8; | ||
616 | cie->ie_beaconInt = *(u16 *) frm; | ||
617 | frm += 2; | ||
618 | cie->ie_capInfo = *(u16 *) frm; | ||
619 | frm += 2; | ||
620 | cie->ie_chan = 0; | ||
621 | |||
622 | while (frm < efrm) { | ||
623 | switch (*frm) { | ||
624 | case WLAN_EID_SSID: | ||
625 | if (!elemid_ssid) { | ||
626 | cie->ie_ssid = frm; | ||
627 | elemid_ssid = true; | ||
628 | } | ||
629 | break; | ||
630 | case WLAN_EID_SUPP_RATES: | ||
631 | cie->ie_rates = frm; | ||
632 | break; | ||
633 | case WLAN_EID_COUNTRY: | ||
634 | cie->ie_country = frm; | ||
635 | break; | ||
636 | case WLAN_EID_FH_PARAMS: | ||
637 | break; | ||
638 | case WLAN_EID_DS_PARAMS: | ||
639 | cie->ie_chan = frm[2]; | ||
640 | break; | ||
641 | case WLAN_EID_TIM: | ||
642 | cie->ie_tim = frm; | ||
643 | break; | ||
644 | case WLAN_EID_IBSS_PARAMS: | ||
645 | break; | ||
646 | case WLAN_EID_EXT_SUPP_RATES: | ||
647 | cie->ie_xrates = frm; | ||
648 | break; | ||
649 | case WLAN_EID_ERP_INFO: | ||
650 | if (frm[1] != 1) | ||
651 | return -EINVAL; | ||
652 | |||
653 | cie->ie_erp = frm[2]; | ||
654 | break; | ||
655 | case WLAN_EID_RSN: | ||
656 | cie->ie_rsn = frm; | ||
657 | break; | ||
658 | case WLAN_EID_HT_CAPABILITY: | ||
659 | cie->ie_htcap = frm; | ||
660 | break; | ||
661 | case WLAN_EID_HT_INFORMATION: | ||
662 | cie->ie_htop = frm; | ||
663 | break; | ||
664 | case WLAN_EID_VENDOR_SPECIFIC: | ||
665 | if (frm[1] > 3 && frm[2] == 0x00 && frm[3] == 0x50 && | ||
666 | frm[4] == 0xf2) { | ||
667 | /* OUT Type (00:50:F2) */ | ||
668 | |||
669 | if (frm[5] == WPA_OUI_TYPE) { | ||
670 | /* WPA OUT */ | ||
671 | cie->ie_wpa = frm; | ||
672 | } else if (frm[5] == WMM_OUI_TYPE) { | ||
673 | /* WMM OUT */ | ||
674 | cie->ie_wmm = frm; | ||
675 | } else if (frm[5] == WSC_OUT_TYPE) { | ||
676 | /* WSC OUT */ | ||
677 | cie->ie_wsc = frm; | ||
678 | } | ||
679 | |||
680 | } else if (frm[1] > 3 && frm[2] == 0x00 | ||
681 | && frm[3] == 0x03 && frm[4] == 0x7f | ||
682 | && frm[5] == ATH_OUI_TYPE) { | ||
683 | /* Atheros OUI (00:03:7f) */ | ||
684 | cie->ie_ath = frm; | ||
685 | } | ||
686 | break; | ||
687 | default: | ||
688 | break; | ||
689 | } | ||
690 | frm += frm[1] + 2; | ||
691 | } | ||
692 | |||
693 | if ((cie->ie_rates == NULL) | ||
694 | || (cie->ie_rates[1] > ATH6KL_RATE_MAXSIZE)) | ||
695 | return -EINVAL; | ||
696 | |||
697 | if ((cie->ie_ssid == NULL) | ||
698 | || (cie->ie_ssid[1] > IEEE80211_MAX_SSID_LEN)) | ||
699 | return -EINVAL; | ||
700 | |||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len) | 903 | static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len) |
705 | { | 904 | { |
706 | struct bss *bss = NULL; | 905 | struct wmi_bss_info_hdr2 *bih; |
707 | struct wmi_bss_info_hdr *bih; | 906 | u8 *buf; |
708 | u8 cached_ssid_len = 0; | 907 | struct ieee80211_channel *channel; |
709 | u8 cached_ssid[IEEE80211_MAX_SSID_LEN] = { 0 }; | 908 | struct ath6kl *ar = wmi->parent_dev; |
710 | u8 beacon_ssid_len = 0; | 909 | struct ieee80211_mgmt *mgmt; |
711 | u8 *buf, *ie_ssid; | 910 | struct cfg80211_bss *bss; |
712 | u8 *ni_buf; | ||
713 | int buf_len; | ||
714 | |||
715 | int ret; | ||
716 | 911 | ||
717 | if (len <= sizeof(struct wmi_bss_info_hdr)) | 912 | if (len <= sizeof(struct wmi_bss_info_hdr2)) |
718 | return -EINVAL; | 913 | return -EINVAL; |
719 | 914 | ||
720 | bih = (struct wmi_bss_info_hdr *) datap; | 915 | bih = (struct wmi_bss_info_hdr2 *) datap; |
721 | bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid); | 916 | buf = datap + sizeof(struct wmi_bss_info_hdr2); |
722 | 917 | len -= sizeof(struct wmi_bss_info_hdr2); | |
723 | if (a_sle16_to_cpu(bih->rssi) > 0) { | ||
724 | if (bss == NULL) | ||
725 | return 0; | ||
726 | else | ||
727 | bih->rssi = a_cpu_to_sle16(bss->ni_rssi); | ||
728 | } | ||
729 | |||
730 | buf = datap + sizeof(struct wmi_bss_info_hdr); | ||
731 | len -= sizeof(struct wmi_bss_info_hdr); | ||
732 | 918 | ||
733 | ath6kl_dbg(ATH6KL_DBG_WMI, | 919 | ath6kl_dbg(ATH6KL_DBG_WMI, |
734 | "bss info evt - ch %u, rssi %02x, bssid \"%pM\"\n", | 920 | "bss info evt - ch %u, snr %d, rssi %d, bssid \"%pM\" " |
735 | bih->ch, a_sle16_to_cpu(bih->rssi), bih->bssid); | 921 | "frame_type=%d\n", |
736 | 922 | bih->ch, bih->snr, bih->snr - 95, bih->bssid, | |
737 | if (bss != NULL) { | 923 | bih->frame_type); |
738 | /* | 924 | |
739 | * Free up the node. We are about to allocate a new node. | 925 | if (bih->frame_type != BEACON_FTYPE && |
740 | * In case of hidden AP, beacon will not have ssid, | 926 | bih->frame_type != PROBERESP_FTYPE) |
741 | * but a directed probe response will have it, | 927 | return 0; /* Only update BSS table for now */ |
742 | * so cache the probe-resp-ssid if already present. | 928 | |
743 | */ | 929 | if (bih->frame_type == BEACON_FTYPE && |
744 | if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE)) { | 930 | test_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag)) { |
745 | ie_ssid = bss->ni_cie.ie_ssid; | 931 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); |
746 | if (ie_ssid && (ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) && | 932 | ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); |
747 | (ie_ssid[2] != 0)) { | ||
748 | cached_ssid_len = ie_ssid[1]; | ||
749 | memcpy(cached_ssid, ie_ssid + 2, | ||
750 | cached_ssid_len); | ||
751 | } | ||
752 | } | ||
753 | |||
754 | /* | ||
755 | * Use the current average rssi of associated AP base on | ||
756 | * assumption | ||
757 | * 1. Most os with GUI will update RSSI by | ||
758 | * ath6kl_wmi_get_stats_cmd() periodically. | ||
759 | * 2. ath6kl_wmi_get_stats_cmd(..) will be called when calling | ||
760 | * ath6kl_wmi_startscan_cmd(...) | ||
761 | * The average value of RSSI give end-user better feeling for | ||
762 | * instance value of scan result. It also sync up RSSI info | ||
763 | * in GUI between scan result and RSSI signal icon. | ||
764 | */ | ||
765 | if (memcmp(wmi->parent_dev->bssid, bih->bssid, ETH_ALEN) == 0) { | ||
766 | bih->rssi = a_cpu_to_sle16(bss->ni_rssi); | ||
767 | bih->snr = bss->ni_snr; | ||
768 | } | ||
769 | |||
770 | wlan_node_reclaim(&wmi->parent_dev->scan_table, bss); | ||
771 | } | 933 | } |
772 | 934 | ||
773 | /* | 935 | channel = ieee80211_get_channel(ar->wdev->wiphy, le16_to_cpu(bih->ch)); |
774 | * beacon/probe response frame format | 936 | if (channel == NULL) |
775 | * [8] time stamp | ||
776 | * [2] beacon interval | ||
777 | * [2] capability information | ||
778 | * [tlv] ssid | ||
779 | */ | ||
780 | beacon_ssid_len = buf[SSID_IE_LEN_INDEX]; | ||
781 | |||
782 | /* | ||
783 | * If ssid is cached for this hidden AP, then change | ||
784 | * buffer len accordingly. | ||
785 | */ | ||
786 | if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) && | ||
787 | (cached_ssid_len != 0) && | ||
788 | (beacon_ssid_len == 0 || (cached_ssid_len > beacon_ssid_len && | ||
789 | buf[SSID_IE_LEN_INDEX + 1] == 0))) { | ||
790 | |||
791 | len += (cached_ssid_len - beacon_ssid_len); | ||
792 | } | ||
793 | |||
794 | bss = wlan_node_alloc(len); | ||
795 | if (!bss) | ||
796 | return -ENOMEM; | ||
797 | |||
798 | bss->ni_snr = bih->snr; | ||
799 | bss->ni_rssi = a_sle16_to_cpu(bih->rssi); | ||
800 | |||
801 | if (WARN_ON(!bss->ni_buf)) | ||
802 | return -EINVAL; | 937 | return -EINVAL; |
803 | 938 | ||
804 | /* | 939 | if (len < 8 + 2 + 2) |
805 | * In case of hidden AP, beacon will not have ssid, | ||
806 | * but a directed probe response will have it, | ||
807 | * so place the cached-ssid(probe-resp) in the bss info. | ||
808 | */ | ||
809 | if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) && | ||
810 | (cached_ssid_len != 0) && | ||
811 | (beacon_ssid_len == 0 || (beacon_ssid_len && | ||
812 | buf[SSID_IE_LEN_INDEX + 1] == 0))) { | ||
813 | ni_buf = bss->ni_buf; | ||
814 | buf_len = len; | ||
815 | |||
816 | /* | ||
817 | * Copy the first 14 bytes: | ||
818 | * time-stamp(8), beacon-interval(2), | ||
819 | * cap-info(2), ssid-id(1), ssid-len(1). | ||
820 | */ | ||
821 | memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1); | ||
822 | |||
823 | ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len; | ||
824 | ni_buf += (SSID_IE_LEN_INDEX + 1); | ||
825 | |||
826 | buf += (SSID_IE_LEN_INDEX + 1); | ||
827 | buf_len -= (SSID_IE_LEN_INDEX + 1); | ||
828 | |||
829 | memcpy(ni_buf, cached_ssid, cached_ssid_len); | ||
830 | ni_buf += cached_ssid_len; | ||
831 | |||
832 | buf += beacon_ssid_len; | ||
833 | buf_len -= beacon_ssid_len; | ||
834 | |||
835 | if (cached_ssid_len > beacon_ssid_len) | ||
836 | buf_len -= (cached_ssid_len - beacon_ssid_len); | ||
837 | |||
838 | memcpy(ni_buf, buf, buf_len); | ||
839 | } else | ||
840 | memcpy(bss->ni_buf, buf, len); | ||
841 | |||
842 | bss->ni_framelen = len; | ||
843 | |||
844 | ret = ath6kl_wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie); | ||
845 | if (ret) { | ||
846 | wlan_node_free(bss); | ||
847 | return -EINVAL; | 940 | return -EINVAL; |
941 | |||
942 | if (bih->frame_type == BEACON_FTYPE && test_bit(CONNECTED, &ar->flag) && | ||
943 | memcmp(bih->bssid, ar->bssid, ETH_ALEN) == 0) { | ||
944 | const u8 *tim; | ||
945 | tim = cfg80211_find_ie(WLAN_EID_TIM, buf + 8 + 2 + 2, | ||
946 | len - 8 - 2 - 2); | ||
947 | if (tim && tim[1] >= 2) { | ||
948 | ar->assoc_bss_dtim_period = tim[3]; | ||
949 | set_bit(DTIM_PERIOD_AVAIL, &ar->flag); | ||
950 | } | ||
848 | } | 951 | } |
849 | 952 | ||
850 | /* | 953 | /* |
851 | * Update the frequency in ie_chan, overwriting of channel number | 954 | * In theory, use of cfg80211_inform_bss() would be more natural here |
852 | * which is done in ath6kl_wlan_parse_beacon | 955 | * since we do not have the full frame. However, at least for now, |
956 | * cfg80211 can only distinguish Beacon and Probe Response frames from | ||
957 | * each other when using cfg80211_inform_bss_frame(), so let's build a | ||
958 | * fake IEEE 802.11 header to be able to take benefit of this. | ||
853 | */ | 959 | */ |
854 | bss->ni_cie.ie_chan = le16_to_cpu(bih->ch); | 960 | mgmt = kmalloc(24 + len, GFP_ATOMIC); |
855 | wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid); | 961 | if (mgmt == NULL) |
856 | |||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static int ath6kl_wmi_opt_frame_event_rx(struct wmi *wmi, u8 *datap, int len) | ||
861 | { | ||
862 | struct bss *bss; | ||
863 | struct wmi_opt_rx_info_hdr *bih; | ||
864 | u8 *buf; | ||
865 | |||
866 | if (len <= sizeof(struct wmi_opt_rx_info_hdr)) | ||
867 | return -EINVAL; | 962 | return -EINVAL; |
868 | 963 | ||
869 | bih = (struct wmi_opt_rx_info_hdr *) datap; | 964 | if (bih->frame_type == BEACON_FTYPE) { |
870 | buf = datap + sizeof(struct wmi_opt_rx_info_hdr); | 965 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
871 | len -= sizeof(struct wmi_opt_rx_info_hdr); | 966 | IEEE80211_STYPE_BEACON); |
872 | 967 | memset(mgmt->da, 0xff, ETH_ALEN); | |
873 | ath6kl_dbg(ATH6KL_DBG_WMI, "opt frame event %2.2x:%2.2x\n", | 968 | } else { |
874 | bih->bssid[4], bih->bssid[5]); | 969 | struct net_device *dev = ar->net_dev; |
875 | 970 | ||
876 | bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid); | 971 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
877 | if (bss != NULL) { | 972 | IEEE80211_STYPE_PROBE_RESP); |
878 | /* Free up the node. We are about to allocate a new node. */ | 973 | memcpy(mgmt->da, dev->dev_addr, ETH_ALEN); |
879 | wlan_node_reclaim(&wmi->parent_dev->scan_table, bss); | ||
880 | } | 974 | } |
881 | 975 | mgmt->duration = cpu_to_le16(0); | |
882 | bss = wlan_node_alloc(len); | 976 | memcpy(mgmt->sa, bih->bssid, ETH_ALEN); |
883 | if (!bss) | 977 | memcpy(mgmt->bssid, bih->bssid, ETH_ALEN); |
978 | mgmt->seq_ctrl = cpu_to_le16(0); | ||
979 | |||
980 | memcpy(&mgmt->u.beacon, buf, len); | ||
981 | |||
982 | bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, channel, mgmt, | ||
983 | 24 + len, (bih->snr - 95) * 100, | ||
984 | GFP_ATOMIC); | ||
985 | kfree(mgmt); | ||
986 | if (bss == NULL) | ||
884 | return -ENOMEM; | 987 | return -ENOMEM; |
885 | 988 | cfg80211_put_bss(bss); | |
886 | bss->ni_snr = bih->snr; | ||
887 | bss->ni_cie.ie_chan = le16_to_cpu(bih->ch); | ||
888 | |||
889 | if (WARN_ON(!bss->ni_buf)) | ||
890 | return -EINVAL; | ||
891 | |||
892 | memcpy(bss->ni_buf, buf, len); | ||
893 | wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid); | ||
894 | 989 | ||
895 | return 0; | 990 | return 0; |
896 | } | 991 | } |
@@ -949,6 +1044,13 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len) | |||
949 | return 0; | 1044 | return 0; |
950 | } | 1045 | } |
951 | 1046 | ||
1047 | static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len) | ||
1048 | { | ||
1049 | ath6kl_tm_rx_report_event(wmi->parent_dev, datap, len); | ||
1050 | |||
1051 | return 0; | ||
1052 | } | ||
1053 | |||
952 | static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len) | 1054 | static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len) |
953 | { | 1055 | { |
954 | if (len < sizeof(struct wmi_fix_rates_reply)) | 1056 | if (len < sizeof(struct wmi_fix_rates_reply)) |
@@ -998,15 +1100,41 @@ static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len) | |||
998 | 1100 | ||
999 | ev = (struct wmi_scan_complete_event *) datap; | 1101 | ev = (struct wmi_scan_complete_event *) datap; |
1000 | 1102 | ||
1001 | if (a_sle32_to_cpu(ev->status) == 0) | ||
1002 | wlan_refresh_inactive_nodes(wmi->parent_dev); | ||
1003 | |||
1004 | ath6kl_scan_complete_evt(wmi->parent_dev, a_sle32_to_cpu(ev->status)); | 1103 | ath6kl_scan_complete_evt(wmi->parent_dev, a_sle32_to_cpu(ev->status)); |
1005 | wmi->is_probe_ssid = false; | 1104 | wmi->is_probe_ssid = false; |
1006 | 1105 | ||
1007 | return 0; | 1106 | return 0; |
1008 | } | 1107 | } |
1009 | 1108 | ||
1109 | static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap, | ||
1110 | int len) | ||
1111 | { | ||
1112 | struct wmi_neighbor_report_event *ev; | ||
1113 | u8 i; | ||
1114 | |||
1115 | if (len < sizeof(*ev)) | ||
1116 | return -EINVAL; | ||
1117 | ev = (struct wmi_neighbor_report_event *) datap; | ||
1118 | if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info) | ||
1119 | > len) { | ||
1120 | ath6kl_dbg(ATH6KL_DBG_WMI, "truncated neighbor event " | ||
1121 | "(num=%d len=%d)\n", ev->num_neighbors, len); | ||
1122 | return -EINVAL; | ||
1123 | } | ||
1124 | for (i = 0; i < ev->num_neighbors; i++) { | ||
1125 | ath6kl_dbg(ATH6KL_DBG_WMI, "neighbor %d/%d - %pM 0x%x\n", | ||
1126 | i + 1, ev->num_neighbors, ev->neighbor[i].bssid, | ||
1127 | ev->neighbor[i].bss_flags); | ||
1128 | cfg80211_pmksa_candidate_notify(wmi->parent_dev->net_dev, i, | ||
1129 | ev->neighbor[i].bssid, | ||
1130 | !!(ev->neighbor[i].bss_flags & | ||
1131 | WMI_PREAUTH_CAPABLE_BSS), | ||
1132 | GFP_ATOMIC); | ||
1133 | } | ||
1134 | |||
1135 | return 0; | ||
1136 | } | ||
1137 | |||
1010 | /* | 1138 | /* |
1011 | * Target is reporting a programming error. This is for | 1139 | * Target is reporting a programming error. This is for |
1012 | * developer aid only. Target only checks a few common violations | 1140 | * developer aid only. Target only checks a few common violations |
@@ -1410,6 +1538,11 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb, | |||
1410 | if (WARN_ON(skb == NULL)) | 1538 | if (WARN_ON(skb == NULL)) |
1411 | return -EINVAL; | 1539 | return -EINVAL; |
1412 | 1540 | ||
1541 | ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n", | ||
1542 | cmd_id, skb->len, sync_flag); | ||
1543 | ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi tx ", | ||
1544 | skb->data, skb->len); | ||
1545 | |||
1413 | if (sync_flag >= END_WMIFLAG) { | 1546 | if (sync_flag >= END_WMIFLAG) { |
1414 | dev_kfree_skb(skb); | 1547 | dev_kfree_skb(skb); |
1415 | return -EINVAL; | 1548 | return -EINVAL; |
@@ -1468,6 +1601,13 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type, | |||
1468 | struct wmi_connect_cmd *cc; | 1601 | struct wmi_connect_cmd *cc; |
1469 | int ret; | 1602 | int ret; |
1470 | 1603 | ||
1604 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
1605 | "wmi connect bssid %pM freq %d flags 0x%x ssid_len %d " | ||
1606 | "type %d dot11_auth %d auth %d pairwise %d group %d\n", | ||
1607 | bssid, channel, ctrl_flags, ssid_len, nw_type, | ||
1608 | dot11_auth_mode, auth_mode, pairwise_crypto, group_crypto); | ||
1609 | ath6kl_dbg_dump(ATH6KL_DBG_WMI, NULL, "ssid ", ssid, ssid_len); | ||
1610 | |||
1471 | wmi->traffic_class = 100; | 1611 | wmi->traffic_class = 100; |
1472 | 1612 | ||
1473 | if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT)) | 1613 | if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT)) |
@@ -1513,6 +1653,9 @@ int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel) | |||
1513 | struct wmi_reconnect_cmd *cc; | 1653 | struct wmi_reconnect_cmd *cc; |
1514 | int ret; | 1654 | int ret; |
1515 | 1655 | ||
1656 | ath6kl_dbg(ATH6KL_DBG_WMI, "wmi reconnect bssid %pM freq %d\n", | ||
1657 | bssid, channel); | ||
1658 | |||
1516 | wmi->traffic_class = 100; | 1659 | wmi->traffic_class = 100; |
1517 | 1660 | ||
1518 | skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd)); | 1661 | skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd)); |
@@ -1535,6 +1678,8 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi) | |||
1535 | { | 1678 | { |
1536 | int ret; | 1679 | int ret; |
1537 | 1680 | ||
1681 | ath6kl_dbg(ATH6KL_DBG_WMI, "wmi disconnect\n"); | ||
1682 | |||
1538 | wmi->traffic_class = 100; | 1683 | wmi->traffic_class = 100; |
1539 | 1684 | ||
1540 | /* Disconnect command does not need to do a SYNC before. */ | 1685 | /* Disconnect command does not need to do a SYNC before. */ |
@@ -1551,7 +1696,7 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type, | |||
1551 | struct sk_buff *skb; | 1696 | struct sk_buff *skb; |
1552 | struct wmi_start_scan_cmd *sc; | 1697 | struct wmi_start_scan_cmd *sc; |
1553 | s8 size; | 1698 | s8 size; |
1554 | int ret; | 1699 | int i, ret; |
1555 | 1700 | ||
1556 | size = sizeof(struct wmi_start_scan_cmd); | 1701 | size = sizeof(struct wmi_start_scan_cmd); |
1557 | 1702 | ||
@@ -1576,8 +1721,8 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type, | |||
1576 | sc->force_scan_intvl = cpu_to_le32(force_scan_interval); | 1721 | sc->force_scan_intvl = cpu_to_le32(force_scan_interval); |
1577 | sc->num_ch = num_chan; | 1722 | sc->num_ch = num_chan; |
1578 | 1723 | ||
1579 | if (num_chan) | 1724 | for (i = 0; i < num_chan; i++) |
1580 | memcpy(sc->ch_list, ch_list, num_chan * sizeof(u16)); | 1725 | sc->ch_list[i] = cpu_to_le16(ch_list[i]); |
1581 | 1726 | ||
1582 | ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_START_SCAN_CMDID, | 1727 | ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_START_SCAN_CMDID, |
1583 | NO_SYNC_WMIFLAG); | 1728 | NO_SYNC_WMIFLAG); |
@@ -1770,6 +1915,10 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index, | |||
1770 | struct wmi_add_cipher_key_cmd *cmd; | 1915 | struct wmi_add_cipher_key_cmd *cmd; |
1771 | int ret; | 1916 | int ret; |
1772 | 1917 | ||
1918 | ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d " | ||
1919 | "key_usage=%d key_len=%d key_op_ctrl=%d\n", | ||
1920 | key_index, key_type, key_usage, key_len, key_op_ctrl); | ||
1921 | |||
1773 | if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || | 1922 | if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || |
1774 | (key_material == NULL)) | 1923 | (key_material == NULL)) |
1775 | return -EINVAL; | 1924 | return -EINVAL; |
@@ -2211,6 +2360,25 @@ int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source) | |||
2211 | return ret; | 2360 | return ret; |
2212 | } | 2361 | } |
2213 | 2362 | ||
2363 | int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config) | ||
2364 | { | ||
2365 | struct ath6kl_wmix_dbglog_cfg_module_cmd *cmd; | ||
2366 | struct sk_buff *skb; | ||
2367 | int ret; | ||
2368 | |||
2369 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
2370 | if (!skb) | ||
2371 | return -ENOMEM; | ||
2372 | |||
2373 | cmd = (struct ath6kl_wmix_dbglog_cfg_module_cmd *) skb->data; | ||
2374 | cmd->valid = cpu_to_le32(valid); | ||
2375 | cmd->config = cpu_to_le32(config); | ||
2376 | |||
2377 | ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_DBGLOG_CFG_MODULE_CMDID, | ||
2378 | NO_SYNC_WMIFLAG); | ||
2379 | return ret; | ||
2380 | } | ||
2381 | |||
2214 | int ath6kl_wmi_get_stats_cmd(struct wmi *wmi) | 2382 | int ath6kl_wmi_get_stats_cmd(struct wmi *wmi) |
2215 | { | 2383 | { |
2216 | return ath6kl_wmi_simple_cmd(wmi, WMI_GET_STATISTICS_CMDID); | 2384 | return ath6kl_wmi_simple_cmd(wmi, WMI_GET_STATISTICS_CMDID); |
@@ -2316,49 +2484,29 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl) | |||
2316 | return ret; | 2484 | return ret; |
2317 | } | 2485 | } |
2318 | 2486 | ||
2319 | s32 ath6kl_wmi_get_rate(s8 rate_index) | 2487 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) |
2320 | { | 2488 | { |
2321 | if (rate_index == RATE_AUTO) | 2489 | struct sk_buff *skb; |
2322 | return 0; | 2490 | int ret; |
2323 | 2491 | ||
2324 | return wmi_rate_tbl[(u32) rate_index][0]; | 2492 | skb = ath6kl_wmi_get_new_buf(len); |
2325 | } | 2493 | if (!skb) |
2494 | return -ENOMEM; | ||
2326 | 2495 | ||
2327 | void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss) | 2496 | memcpy(skb->data, buf, len); |
2328 | { | ||
2329 | if (bss) | ||
2330 | wlan_node_return(&wmi->parent_dev->scan_table, bss); | ||
2331 | } | ||
2332 | 2497 | ||
2333 | struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 * ssid, | 2498 | ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_TEST_CMDID, NO_SYNC_WMIFLAG); |
2334 | u32 ssid_len, bool is_wpa2, | ||
2335 | bool match_ssid) | ||
2336 | { | ||
2337 | struct bss *node = NULL; | ||
2338 | 2499 | ||
2339 | node = wlan_find_ssid_node(&wmi->parent_dev->scan_table, ssid, | 2500 | return ret; |
2340 | ssid_len, is_wpa2, match_ssid); | ||
2341 | return node; | ||
2342 | } | 2501 | } |
2343 | 2502 | ||
2344 | struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 * mac_addr) | ||
2345 | { | ||
2346 | struct bss *ni = NULL; | ||
2347 | |||
2348 | ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr); | ||
2349 | |||
2350 | return ni; | ||
2351 | } | ||
2352 | 2503 | ||
2353 | void ath6kl_wmi_node_free(struct wmi *wmi, const u8 * mac_addr) | 2504 | s32 ath6kl_wmi_get_rate(s8 rate_index) |
2354 | { | 2505 | { |
2355 | struct bss *ni = NULL; | 2506 | if (rate_index == RATE_AUTO) |
2356 | 2507 | return 0; | |
2357 | ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr); | ||
2358 | if (ni != NULL) | ||
2359 | wlan_node_reclaim(&wmi->parent_dev->scan_table, ni); | ||
2360 | 2508 | ||
2361 | return; | 2509 | return wmi_rate_tbl[(u32) rate_index][0]; |
2362 | } | 2510 | } |
2363 | 2511 | ||
2364 | static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, | 2512 | static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, |
@@ -2400,6 +2548,47 @@ static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len) | |||
2400 | } | 2548 | } |
2401 | 2549 | ||
2402 | /* AP mode functions */ | 2550 | /* AP mode functions */ |
2551 | |||
2552 | int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p) | ||
2553 | { | ||
2554 | struct sk_buff *skb; | ||
2555 | struct wmi_connect_cmd *cm; | ||
2556 | int res; | ||
2557 | |||
2558 | skb = ath6kl_wmi_get_new_buf(sizeof(*cm)); | ||
2559 | if (!skb) | ||
2560 | return -ENOMEM; | ||
2561 | |||
2562 | cm = (struct wmi_connect_cmd *) skb->data; | ||
2563 | memcpy(cm, p, sizeof(*cm)); | ||
2564 | |||
2565 | res = ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_CONFIG_COMMIT_CMDID, | ||
2566 | NO_SYNC_WMIFLAG); | ||
2567 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u " | ||
2568 | "ctrl_flags=0x%x-> res=%d\n", | ||
2569 | __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch), | ||
2570 | le32_to_cpu(p->ctrl_flags), res); | ||
2571 | return res; | ||
2572 | } | ||
2573 | |||
2574 | int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason) | ||
2575 | { | ||
2576 | struct sk_buff *skb; | ||
2577 | struct wmi_ap_set_mlme_cmd *cm; | ||
2578 | |||
2579 | skb = ath6kl_wmi_get_new_buf(sizeof(*cm)); | ||
2580 | if (!skb) | ||
2581 | return -ENOMEM; | ||
2582 | |||
2583 | cm = (struct wmi_ap_set_mlme_cmd *) skb->data; | ||
2584 | memcpy(cm->mac, mac, ETH_ALEN); | ||
2585 | cm->reason = cpu_to_le16(reason); | ||
2586 | cm->cmd = cmd; | ||
2587 | |||
2588 | return ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_SET_MLME_CMDID, | ||
2589 | NO_SYNC_WMIFLAG); | ||
2590 | } | ||
2591 | |||
2403 | static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len) | 2592 | static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len) |
2404 | { | 2593 | { |
2405 | struct wmi_pspoll_event *ev; | 2594 | struct wmi_pspoll_event *ev; |
@@ -2433,6 +2622,7 @@ int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag) | |||
2433 | 2622 | ||
2434 | cmd = (struct wmi_ap_set_pvb_cmd *) skb->data; | 2623 | cmd = (struct wmi_ap_set_pvb_cmd *) skb->data; |
2435 | cmd->aid = cpu_to_le16(aid); | 2624 | cmd->aid = cpu_to_le16(aid); |
2625 | cmd->rsvd = cpu_to_le16(0); | ||
2436 | cmd->flag = cpu_to_le32(flag); | 2626 | cmd->flag = cpu_to_le32(flag); |
2437 | 2627 | ||
2438 | ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_AP_SET_PVB_CMDID, | 2628 | ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_AP_SET_PVB_CMDID, |
@@ -2464,6 +2654,160 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver, | |||
2464 | return ret; | 2654 | return ret; |
2465 | } | 2655 | } |
2466 | 2656 | ||
2657 | int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie, | ||
2658 | u8 ie_len) | ||
2659 | { | ||
2660 | struct sk_buff *skb; | ||
2661 | struct wmi_set_appie_cmd *p; | ||
2662 | |||
2663 | skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len); | ||
2664 | if (!skb) | ||
2665 | return -ENOMEM; | ||
2666 | |||
2667 | ath6kl_dbg(ATH6KL_DBG_WMI, "set_appie_cmd: mgmt_frm_type=%u " | ||
2668 | "ie_len=%u\n", mgmt_frm_type, ie_len); | ||
2669 | p = (struct wmi_set_appie_cmd *) skb->data; | ||
2670 | p->mgmt_frm_type = mgmt_frm_type; | ||
2671 | p->ie_len = ie_len; | ||
2672 | memcpy(p->ie_info, ie, ie_len); | ||
2673 | return ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_APPIE_CMDID, | ||
2674 | NO_SYNC_WMIFLAG); | ||
2675 | } | ||
2676 | |||
2677 | int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable) | ||
2678 | { | ||
2679 | struct sk_buff *skb; | ||
2680 | struct wmi_disable_11b_rates_cmd *cmd; | ||
2681 | |||
2682 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
2683 | if (!skb) | ||
2684 | return -ENOMEM; | ||
2685 | |||
2686 | ath6kl_dbg(ATH6KL_DBG_WMI, "disable_11b_rates_cmd: disable=%u\n", | ||
2687 | disable); | ||
2688 | cmd = (struct wmi_disable_11b_rates_cmd *) skb->data; | ||
2689 | cmd->disable = disable ? 1 : 0; | ||
2690 | |||
2691 | return ath6kl_wmi_cmd_send(wmi, skb, WMI_DISABLE_11B_RATES_CMDID, | ||
2692 | NO_SYNC_WMIFLAG); | ||
2693 | } | ||
2694 | |||
2695 | int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur) | ||
2696 | { | ||
2697 | struct sk_buff *skb; | ||
2698 | struct wmi_remain_on_chnl_cmd *p; | ||
2699 | |||
2700 | skb = ath6kl_wmi_get_new_buf(sizeof(*p)); | ||
2701 | if (!skb) | ||
2702 | return -ENOMEM; | ||
2703 | |||
2704 | ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl_cmd: freq=%u dur=%u\n", | ||
2705 | freq, dur); | ||
2706 | p = (struct wmi_remain_on_chnl_cmd *) skb->data; | ||
2707 | p->freq = cpu_to_le32(freq); | ||
2708 | p->duration = cpu_to_le32(dur); | ||
2709 | return ath6kl_wmi_cmd_send(wmi, skb, WMI_REMAIN_ON_CHNL_CMDID, | ||
2710 | NO_SYNC_WMIFLAG); | ||
2711 | } | ||
2712 | |||
2713 | int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait, | ||
2714 | const u8 *data, u16 data_len) | ||
2715 | { | ||
2716 | struct sk_buff *skb; | ||
2717 | struct wmi_send_action_cmd *p; | ||
2718 | u8 *buf; | ||
2719 | |||
2720 | if (wait) | ||
2721 | return -EINVAL; /* Offload for wait not supported */ | ||
2722 | |||
2723 | buf = kmalloc(data_len, GFP_KERNEL); | ||
2724 | if (!buf) | ||
2725 | return -ENOMEM; | ||
2726 | |||
2727 | skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len); | ||
2728 | if (!skb) { | ||
2729 | kfree(buf); | ||
2730 | return -ENOMEM; | ||
2731 | } | ||
2732 | |||
2733 | kfree(wmi->last_mgmt_tx_frame); | ||
2734 | wmi->last_mgmt_tx_frame = buf; | ||
2735 | wmi->last_mgmt_tx_frame_len = data_len; | ||
2736 | |||
2737 | ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " | ||
2738 | "len=%u\n", id, freq, wait, data_len); | ||
2739 | p = (struct wmi_send_action_cmd *) skb->data; | ||
2740 | p->id = cpu_to_le32(id); | ||
2741 | p->freq = cpu_to_le32(freq); | ||
2742 | p->wait = cpu_to_le32(wait); | ||
2743 | p->len = cpu_to_le16(data_len); | ||
2744 | memcpy(p->data, data, data_len); | ||
2745 | return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_ACTION_CMDID, | ||
2746 | NO_SYNC_WMIFLAG); | ||
2747 | } | ||
2748 | |||
2749 | int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq, | ||
2750 | const u8 *dst, | ||
2751 | const u8 *data, u16 data_len) | ||
2752 | { | ||
2753 | struct sk_buff *skb; | ||
2754 | struct wmi_p2p_probe_response_cmd *p; | ||
2755 | |||
2756 | skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len); | ||
2757 | if (!skb) | ||
2758 | return -ENOMEM; | ||
2759 | |||
2760 | ath6kl_dbg(ATH6KL_DBG_WMI, "send_probe_response_cmd: freq=%u dst=%pM " | ||
2761 | "len=%u\n", freq, dst, data_len); | ||
2762 | p = (struct wmi_p2p_probe_response_cmd *) skb->data; | ||
2763 | p->freq = cpu_to_le32(freq); | ||
2764 | memcpy(p->destination_addr, dst, ETH_ALEN); | ||
2765 | p->len = cpu_to_le16(data_len); | ||
2766 | memcpy(p->data, data, data_len); | ||
2767 | return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_PROBE_RESPONSE_CMDID, | ||
2768 | NO_SYNC_WMIFLAG); | ||
2769 | } | ||
2770 | |||
2771 | int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable) | ||
2772 | { | ||
2773 | struct sk_buff *skb; | ||
2774 | struct wmi_probe_req_report_cmd *p; | ||
2775 | |||
2776 | skb = ath6kl_wmi_get_new_buf(sizeof(*p)); | ||
2777 | if (!skb) | ||
2778 | return -ENOMEM; | ||
2779 | |||
2780 | ath6kl_dbg(ATH6KL_DBG_WMI, "probe_report_req_cmd: enable=%u\n", | ||
2781 | enable); | ||
2782 | p = (struct wmi_probe_req_report_cmd *) skb->data; | ||
2783 | p->enable = enable ? 1 : 0; | ||
2784 | return ath6kl_wmi_cmd_send(wmi, skb, WMI_PROBE_REQ_REPORT_CMDID, | ||
2785 | NO_SYNC_WMIFLAG); | ||
2786 | } | ||
2787 | |||
2788 | int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags) | ||
2789 | { | ||
2790 | struct sk_buff *skb; | ||
2791 | struct wmi_get_p2p_info *p; | ||
2792 | |||
2793 | skb = ath6kl_wmi_get_new_buf(sizeof(*p)); | ||
2794 | if (!skb) | ||
2795 | return -ENOMEM; | ||
2796 | |||
2797 | ath6kl_dbg(ATH6KL_DBG_WMI, "info_req_cmd: flags=%x\n", | ||
2798 | info_req_flags); | ||
2799 | p = (struct wmi_get_p2p_info *) skb->data; | ||
2800 | p->info_req_flags = cpu_to_le32(info_req_flags); | ||
2801 | return ath6kl_wmi_cmd_send(wmi, skb, WMI_GET_P2P_INFO_CMDID, | ||
2802 | NO_SYNC_WMIFLAG); | ||
2803 | } | ||
2804 | |||
2805 | int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi) | ||
2806 | { | ||
2807 | ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl_cmd\n"); | ||
2808 | return ath6kl_wmi_simple_cmd(wmi, WMI_CANCEL_REMAIN_ON_CHNL_CMDID); | ||
2809 | } | ||
2810 | |||
2467 | static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) | 2811 | static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) |
2468 | { | 2812 | { |
2469 | struct wmix_cmd_hdr *cmd; | 2813 | struct wmix_cmd_hdr *cmd; |
@@ -2488,11 +2832,14 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) | |||
2488 | 2832 | ||
2489 | switch (id) { | 2833 | switch (id) { |
2490 | case WMIX_HB_CHALLENGE_RESP_EVENTID: | 2834 | case WMIX_HB_CHALLENGE_RESP_EVENTID: |
2835 | ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n"); | ||
2491 | break; | 2836 | break; |
2492 | case WMIX_DBGLOG_EVENTID: | 2837 | case WMIX_DBGLOG_EVENTID: |
2838 | ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len); | ||
2839 | ath6kl_debug_fwlog_event(wmi->parent_dev, datap, len); | ||
2493 | break; | 2840 | break; |
2494 | default: | 2841 | default: |
2495 | ath6kl_err("unknown cmd id 0x%x\n", id); | 2842 | ath6kl_warn("unknown cmd id 0x%x\n", id); |
2496 | wmi->stat.cmd_id_err++; | 2843 | wmi->stat.cmd_id_err++; |
2497 | ret = -EINVAL; | 2844 | ret = -EINVAL; |
2498 | break; | 2845 | break; |
@@ -2528,8 +2875,9 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
2528 | datap = skb->data; | 2875 | datap = skb->data; |
2529 | len = skb->len; | 2876 | len = skb->len; |
2530 | 2877 | ||
2531 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: wmi id: %d\n", __func__, id); | 2878 | ath6kl_dbg(ATH6KL_DBG_WMI, "wmi rx id %d len %d\n", id, len); |
2532 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "msg payload ", datap, len); | 2879 | ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi rx ", |
2880 | datap, len); | ||
2533 | 2881 | ||
2534 | switch (id) { | 2882 | switch (id) { |
2535 | case WMI_GET_BITRATE_CMDID: | 2883 | case WMI_GET_BITRATE_CMDID: |
@@ -2566,11 +2914,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
2566 | break; | 2914 | break; |
2567 | case WMI_BSSINFO_EVENTID: | 2915 | case WMI_BSSINFO_EVENTID: |
2568 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n"); | 2916 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n"); |
2569 | ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(skb, datap); | 2917 | ret = ath6kl_wmi_bssinfo_event_rx(wmi, datap, len); |
2570 | ret = ath6kl_wmi_bssinfo_event_rx(wmi, skb->data, skb->len); | ||
2571 | break; | 2918 | break; |
2572 | case WMI_REGDOMAIN_EVENTID: | 2919 | case WMI_REGDOMAIN_EVENTID: |
2573 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n"); | 2920 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n"); |
2921 | ath6kl_wmi_regdomain_event(wmi, datap, len); | ||
2574 | break; | 2922 | break; |
2575 | case WMI_PSTREAM_TIMEOUT_EVENTID: | 2923 | case WMI_PSTREAM_TIMEOUT_EVENTID: |
2576 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n"); | 2924 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n"); |
@@ -2578,6 +2926,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
2578 | break; | 2926 | break; |
2579 | case WMI_NEIGHBOR_REPORT_EVENTID: | 2927 | case WMI_NEIGHBOR_REPORT_EVENTID: |
2580 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n"); | 2928 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n"); |
2929 | ret = ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len); | ||
2581 | break; | 2930 | break; |
2582 | case WMI_SCAN_COMPLETE_EVENTID: | 2931 | case WMI_SCAN_COMPLETE_EVENTID: |
2583 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n"); | 2932 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n"); |
@@ -2600,7 +2949,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
2600 | break; | 2949 | break; |
2601 | case WMI_OPT_RX_FRAME_EVENTID: | 2950 | case WMI_OPT_RX_FRAME_EVENTID: |
2602 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n"); | 2951 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n"); |
2603 | ret = ath6kl_wmi_opt_frame_event_rx(wmi, datap, len); | 2952 | /* this event has been deprecated */ |
2604 | break; | 2953 | break; |
2605 | case WMI_REPORT_ROAM_TBL_EVENTID: | 2954 | case WMI_REPORT_ROAM_TBL_EVENTID: |
2606 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n"); | 2955 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n"); |
@@ -2619,6 +2968,10 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
2619 | case WMI_REPORT_ROAM_DATA_EVENTID: | 2968 | case WMI_REPORT_ROAM_DATA_EVENTID: |
2620 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n"); | 2969 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n"); |
2621 | break; | 2970 | break; |
2971 | case WMI_TEST_EVENTID: | ||
2972 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n"); | ||
2973 | ret = ath6kl_wmi_tcmd_test_report_rx(wmi, datap, len); | ||
2974 | break; | ||
2622 | case WMI_GET_FIXRATES_CMDID: | 2975 | case WMI_GET_FIXRATES_CMDID: |
2623 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); | 2976 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); |
2624 | ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len); | 2977 | ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len); |
@@ -2683,6 +3036,36 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
2683 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); | 3036 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); |
2684 | ret = ath6kl_wmi_tx_complete_event_rx(datap, len); | 3037 | ret = ath6kl_wmi_tx_complete_event_rx(datap, len); |
2685 | break; | 3038 | break; |
3039 | case WMI_REMAIN_ON_CHNL_EVENTID: | ||
3040 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n"); | ||
3041 | ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len); | ||
3042 | break; | ||
3043 | case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID: | ||
3044 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
3045 | "WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n"); | ||
3046 | ret = ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap, | ||
3047 | len); | ||
3048 | break; | ||
3049 | case WMI_TX_STATUS_EVENTID: | ||
3050 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n"); | ||
3051 | ret = ath6kl_wmi_tx_status_event_rx(wmi, datap, len); | ||
3052 | break; | ||
3053 | case WMI_RX_PROBE_REQ_EVENTID: | ||
3054 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n"); | ||
3055 | ret = ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len); | ||
3056 | break; | ||
3057 | case WMI_P2P_CAPABILITIES_EVENTID: | ||
3058 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n"); | ||
3059 | ret = ath6kl_wmi_p2p_capabilities_event_rx(datap, len); | ||
3060 | break; | ||
3061 | case WMI_RX_ACTION_EVENTID: | ||
3062 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n"); | ||
3063 | ret = ath6kl_wmi_rx_action_event_rx(wmi, datap, len); | ||
3064 | break; | ||
3065 | case WMI_P2P_INFO_EVENTID: | ||
3066 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n"); | ||
3067 | ret = ath6kl_wmi_p2p_info_event_rx(datap, len); | ||
3068 | break; | ||
2686 | default: | 3069 | default: |
2687 | ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id); | 3070 | ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id); |
2688 | wmi->stat.cmd_id_err++; | 3071 | wmi->stat.cmd_id_err++; |
@@ -2739,5 +3122,6 @@ void ath6kl_wmi_shutdown(struct wmi *wmi) | |||
2739 | if (!wmi) | 3122 | if (!wmi) |
2740 | return; | 3123 | return; |
2741 | 3124 | ||
3125 | kfree(wmi->last_mgmt_tx_frame); | ||
2742 | kfree(wmi); | 3126 | kfree(wmi); |
2743 | } | 3127 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index fe3ddce64087..f8e644d54aa7 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -129,6 +129,9 @@ struct wmi { | |||
129 | u8 ht_allowed[A_NUM_BANDS]; | 129 | u8 ht_allowed[A_NUM_BANDS]; |
130 | u8 traffic_class; | 130 | u8 traffic_class; |
131 | bool is_probe_ssid; | 131 | bool is_probe_ssid; |
132 | |||
133 | u8 *last_mgmt_tx_frame; | ||
134 | size_t last_mgmt_tx_frame_len; | ||
132 | }; | 135 | }; |
133 | 136 | ||
134 | struct host_app_area { | 137 | struct host_app_area { |
@@ -490,17 +493,61 @@ enum wmi_cmd_id { | |||
490 | WMI_SET_PASSPHRASE_CMDID, | 493 | WMI_SET_PASSPHRASE_CMDID, |
491 | WMI_SEND_ASSOC_RES_CMDID, | 494 | WMI_SEND_ASSOC_RES_CMDID, |
492 | WMI_SET_ASSOC_REQ_RELAY_CMDID, | 495 | WMI_SET_ASSOC_REQ_RELAY_CMDID, |
493 | WMI_GET_RFKILL_MODE_CMDID, | ||
494 | 496 | ||
495 | /* ACS command, consists of sub-commands */ | 497 | /* ACS command, consists of sub-commands */ |
496 | WMI_ACS_CTRL_CMDID, | 498 | WMI_ACS_CTRL_CMDID, |
499 | WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, | ||
500 | WMI_SET_TBD_TIME_CMDID, /*added for wmiconfig command for TBD */ | ||
501 | |||
502 | /* Pktlog cmds */ | ||
503 | WMI_PKTLOG_ENABLE_CMDID, | ||
504 | WMI_PKTLOG_DISABLE_CMDID, | ||
505 | |||
506 | /* More P2P Cmds */ | ||
507 | WMI_P2P_GO_NEG_REQ_RSP_CMDID, | ||
508 | WMI_P2P_GRP_INIT_CMDID, | ||
509 | WMI_P2P_GRP_FORMATION_DONE_CMDID, | ||
510 | WMI_P2P_INVITE_CMDID, | ||
511 | WMI_P2P_INVITE_REQ_RSP_CMDID, | ||
512 | WMI_P2P_PROV_DISC_REQ_CMDID, | ||
513 | WMI_P2P_SET_CMDID, | ||
514 | |||
515 | WMI_GET_RFKILL_MODE_CMDID, | ||
516 | WMI_SET_RFKILL_MODE_CMDID, | ||
517 | WMI_AP_SET_APSD_CMDID, | ||
518 | WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID, | ||
497 | 519 | ||
520 | WMI_P2P_SDPD_TX_CMDID, /* F05C */ | ||
521 | WMI_P2P_STOP_SDPD_CMDID, | ||
522 | WMI_P2P_CANCEL_CMDID, | ||
498 | /* Ultra low power store / recall commands */ | 523 | /* Ultra low power store / recall commands */ |
499 | WMI_STORERECALL_CONFIGURE_CMDID, | 524 | WMI_STORERECALL_CONFIGURE_CMDID, |
500 | WMI_STORERECALL_RECALL_CMDID, | 525 | WMI_STORERECALL_RECALL_CMDID, |
501 | WMI_STORERECALL_HOST_READY_CMDID, | 526 | WMI_STORERECALL_HOST_READY_CMDID, |
502 | WMI_FORCE_TARGET_ASSERT_CMDID, | 527 | WMI_FORCE_TARGET_ASSERT_CMDID, |
503 | WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, | 528 | |
529 | WMI_SET_PROBED_SSID_EX_CMDID, | ||
530 | WMI_SET_NETWORK_LIST_OFFLOAD_CMDID, | ||
531 | WMI_SET_ARP_NS_OFFLOAD_CMDID, | ||
532 | WMI_ADD_WOW_EXT_PATTERN_CMDID, | ||
533 | WMI_GTK_OFFLOAD_OP_CMDID, | ||
534 | WMI_REMAIN_ON_CHNL_CMDID, | ||
535 | WMI_CANCEL_REMAIN_ON_CHNL_CMDID, | ||
536 | WMI_SEND_ACTION_CMDID, | ||
537 | WMI_PROBE_REQ_REPORT_CMDID, | ||
538 | WMI_DISABLE_11B_RATES_CMDID, | ||
539 | WMI_SEND_PROBE_RESPONSE_CMDID, | ||
540 | WMI_GET_P2P_INFO_CMDID, | ||
541 | WMI_AP_JOIN_BSS_CMDID, | ||
542 | }; | ||
543 | |||
544 | enum wmi_mgmt_frame_type { | ||
545 | WMI_FRAME_BEACON = 0, | ||
546 | WMI_FRAME_PROBE_REQ, | ||
547 | WMI_FRAME_PROBE_RESP, | ||
548 | WMI_FRAME_ASSOC_REQ, | ||
549 | WMI_FRAME_ASSOC_RESP, | ||
550 | WMI_NUM_MGMT_FRAME | ||
504 | }; | 551 | }; |
505 | 552 | ||
506 | /* WMI_CONNECT_CMDID */ | 553 | /* WMI_CONNECT_CMDID */ |
@@ -519,11 +566,6 @@ enum dot11_auth_mode { | |||
519 | LEAP_AUTH = 0x04, | 566 | LEAP_AUTH = 0x04, |
520 | }; | 567 | }; |
521 | 568 | ||
522 | enum { | ||
523 | AUTH_IDLE, | ||
524 | AUTH_OPEN_IN_PROGRESS, | ||
525 | }; | ||
526 | |||
527 | enum auth_mode { | 569 | enum auth_mode { |
528 | NONE_AUTH = 0x01, | 570 | NONE_AUTH = 0x01, |
529 | WPA_AUTH = 0x02, | 571 | WPA_AUTH = 0x02, |
@@ -1179,15 +1221,26 @@ enum wmi_event_id { | |||
1179 | WMI_WAC_START_WPS_EVENTID, | 1221 | WMI_WAC_START_WPS_EVENTID, |
1180 | WMI_WAC_CTRL_REQ_REPLY_EVENTID, | 1222 | WMI_WAC_CTRL_REQ_REPLY_EVENTID, |
1181 | 1223 | ||
1224 | WMI_REPORT_WMM_PARAMS_EVENTID, | ||
1225 | WMI_WAC_REJECT_WPS_EVENTID, | ||
1226 | |||
1227 | /* More P2P Events */ | ||
1228 | WMI_P2P_GO_NEG_REQ_EVENTID, | ||
1229 | WMI_P2P_INVITE_REQ_EVENTID, | ||
1230 | WMI_P2P_INVITE_RCVD_RESULT_EVENTID, | ||
1231 | WMI_P2P_INVITE_SENT_RESULT_EVENTID, | ||
1232 | WMI_P2P_PROV_DISC_RESP_EVENTID, | ||
1233 | WMI_P2P_PROV_DISC_REQ_EVENTID, | ||
1234 | |||
1182 | /* RFKILL Events */ | 1235 | /* RFKILL Events */ |
1183 | WMI_RFKILL_STATE_CHANGE_EVENTID, | 1236 | WMI_RFKILL_STATE_CHANGE_EVENTID, |
1184 | WMI_RFKILL_GET_MODE_CMD_EVENTID, | 1237 | WMI_RFKILL_GET_MODE_CMD_EVENTID, |
1185 | WMI_THIN_RESERVED_START_EVENTID = 0x8000, | ||
1186 | 1238 | ||
1187 | /* | 1239 | WMI_P2P_START_SDPD_EVENTID, |
1188 | * Events in this range are reserved for thinmode | 1240 | WMI_P2P_SDPD_RX_EVENTID, |
1189 | * See wmi_thin.h for actual definitions | 1241 | |
1190 | */ | 1242 | WMI_THIN_RESERVED_START_EVENTID = 0x8000, |
1243 | /* Events in this range are reserved for thinmode */ | ||
1191 | WMI_THIN_RESERVED_END_EVENTID = 0x8fff, | 1244 | WMI_THIN_RESERVED_END_EVENTID = 0x8fff, |
1192 | 1245 | ||
1193 | WMI_SET_CHANNEL_EVENTID, | 1246 | WMI_SET_CHANNEL_EVENTID, |
@@ -1195,7 +1248,17 @@ enum wmi_event_id { | |||
1195 | 1248 | ||
1196 | /* Generic ACS event */ | 1249 | /* Generic ACS event */ |
1197 | WMI_ACS_EVENTID, | 1250 | WMI_ACS_EVENTID, |
1198 | WMI_REPORT_WMM_PARAMS_EVENTID | 1251 | WMI_STORERECALL_STORE_EVENTID, |
1252 | WMI_WOW_EXT_WAKE_EVENTID, | ||
1253 | WMI_GTK_OFFLOAD_STATUS_EVENTID, | ||
1254 | WMI_NETWORK_LIST_OFFLOAD_EVENTID, | ||
1255 | WMI_REMAIN_ON_CHNL_EVENTID, | ||
1256 | WMI_CANCEL_REMAIN_ON_CHNL_EVENTID, | ||
1257 | WMI_TX_STATUS_EVENTID, | ||
1258 | WMI_RX_PROBE_REQ_EVENTID, | ||
1259 | WMI_P2P_CAPABILITIES_EVENTID, | ||
1260 | WMI_RX_ACTION_EVENTID, | ||
1261 | WMI_P2P_INFO_EVENTID, | ||
1199 | }; | 1262 | }; |
1200 | 1263 | ||
1201 | struct wmi_ready_event_2 { | 1264 | struct wmi_ready_event_2 { |
@@ -1207,11 +1270,30 @@ struct wmi_ready_event_2 { | |||
1207 | 1270 | ||
1208 | /* Connect Event */ | 1271 | /* Connect Event */ |
1209 | struct wmi_connect_event { | 1272 | struct wmi_connect_event { |
1210 | __le16 ch; | 1273 | union { |
1211 | u8 bssid[ETH_ALEN]; | 1274 | struct { |
1212 | __le16 listen_intvl; | 1275 | __le16 ch; |
1213 | __le16 beacon_intvl; | 1276 | u8 bssid[ETH_ALEN]; |
1214 | __le32 nw_type; | 1277 | __le16 listen_intvl; |
1278 | __le16 beacon_intvl; | ||
1279 | __le32 nw_type; | ||
1280 | } sta; | ||
1281 | struct { | ||
1282 | u8 phymode; | ||
1283 | u8 aid; | ||
1284 | u8 mac_addr[ETH_ALEN]; | ||
1285 | u8 auth; | ||
1286 | u8 keymgmt; | ||
1287 | __le16 cipher; | ||
1288 | u8 apsd_info; | ||
1289 | u8 unused[3]; | ||
1290 | } ap_sta; | ||
1291 | struct { | ||
1292 | __le16 ch; | ||
1293 | u8 bssid[ETH_ALEN]; | ||
1294 | u8 unused[8]; | ||
1295 | } ap_bss; | ||
1296 | } u; | ||
1215 | u8 beacon_ie_len; | 1297 | u8 beacon_ie_len; |
1216 | u8 assoc_req_len; | 1298 | u8 assoc_req_len; |
1217 | u8 assoc_resp_len; | 1299 | u8 assoc_resp_len; |
@@ -1238,6 +1320,12 @@ enum wmi_disconnect_reason { | |||
1238 | IBSS_MERGE = 0xe, | 1320 | IBSS_MERGE = 0xe, |
1239 | }; | 1321 | }; |
1240 | 1322 | ||
1323 | #define ATH6KL_COUNTRY_RD_SHIFT 16 | ||
1324 | |||
1325 | struct ath6kl_wmi_regdomain { | ||
1326 | __le32 reg_code; | ||
1327 | }; | ||
1328 | |||
1241 | struct wmi_disconnect_event { | 1329 | struct wmi_disconnect_event { |
1242 | /* reason code, see 802.11 spec. */ | 1330 | /* reason code, see 802.11 spec. */ |
1243 | __le16 proto_reason_status; | 1331 | __le16 proto_reason_status; |
@@ -1265,33 +1353,54 @@ enum wmi_bi_ftype { | |||
1265 | PROBEREQ_FTYPE, | 1353 | PROBEREQ_FTYPE, |
1266 | }; | 1354 | }; |
1267 | 1355 | ||
1268 | struct wmi_bss_info_hdr { | 1356 | #define DEF_LRSSI_SCAN_PERIOD 5 |
1269 | __le16 ch; | 1357 | #define DEF_LRSSI_ROAM_THRESHOLD 20 |
1358 | #define DEF_LRSSI_ROAM_FLOOR 60 | ||
1359 | #define DEF_SCAN_FOR_ROAM_INTVL 2 | ||
1270 | 1360 | ||
1271 | /* see, enum wmi_bi_ftype */ | 1361 | enum wmi_roam_ctrl { |
1272 | u8 frame_type; | 1362 | WMI_FORCE_ROAM = 1, |
1363 | WMI_SET_ROAM_MODE, | ||
1364 | WMI_SET_HOST_BIAS, | ||
1365 | WMI_SET_LRSSI_SCAN_PARAMS, | ||
1366 | }; | ||
1273 | 1367 | ||
1274 | u8 snr; | 1368 | struct bss_bias { |
1275 | a_sle16 rssi; | ||
1276 | u8 bssid[ETH_ALEN]; | 1369 | u8 bssid[ETH_ALEN]; |
1277 | __le32 ie_mask; | 1370 | u8 bias; |
1278 | } __packed; | 1371 | } __packed; |
1279 | 1372 | ||
1280 | /* | 1373 | struct bss_bias_info { |
1281 | * BSS INFO HDR version 2.0 | 1374 | u8 num_bss; |
1282 | * With 6 bytes HTC header and 6 bytes of WMI header | 1375 | struct bss_bias bss_bias[1]; |
1283 | * WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management | 1376 | } __packed; |
1284 | * header space. | 1377 | |
1285 | * - Reduce the ie_mask to 2 bytes as only two bit flags are used | 1378 | struct low_rssi_scan_params { |
1286 | * - Remove rssi and compute it on the host. rssi = snr - 95 | 1379 | __le16 lrssi_scan_period; |
1287 | */ | 1380 | a_sle16 lrssi_scan_threshold; |
1381 | a_sle16 lrssi_roam_threshold; | ||
1382 | u8 roam_rssi_floor; | ||
1383 | u8 reserved[1]; | ||
1384 | } __packed; | ||
1385 | |||
1386 | struct roam_ctrl_cmd { | ||
1387 | union { | ||
1388 | u8 bssid[ETH_ALEN]; | ||
1389 | u8 roam_mode; | ||
1390 | struct bss_bias_info bss; | ||
1391 | struct low_rssi_scan_params params; | ||
1392 | } __packed info; | ||
1393 | u8 roam_ctrl; | ||
1394 | } __packed; | ||
1395 | |||
1396 | /* BSS INFO HDR version 2.0 */ | ||
1288 | struct wmi_bss_info_hdr2 { | 1397 | struct wmi_bss_info_hdr2 { |
1289 | __le16 ch; | 1398 | __le16 ch; /* frequency in MHz */ |
1290 | 1399 | ||
1291 | /* see, enum wmi_bi_ftype */ | 1400 | /* see, enum wmi_bi_ftype */ |
1292 | u8 frame_type; | 1401 | u8 frame_type; |
1293 | 1402 | ||
1294 | u8 snr; | 1403 | u8 snr; /* note: rssi = snr - 95 dBm */ |
1295 | u8 bssid[ETH_ALEN]; | 1404 | u8 bssid[ETH_ALEN]; |
1296 | __le16 ie_mask; | 1405 | __le16 ie_mask; |
1297 | } __packed; | 1406 | } __packed; |
@@ -1330,6 +1439,16 @@ enum wmi_bss_flags { | |||
1330 | WMI_PMKID_VALID_BSS = 0x02, | 1439 | WMI_PMKID_VALID_BSS = 0x02, |
1331 | }; | 1440 | }; |
1332 | 1441 | ||
1442 | struct wmi_neighbor_info { | ||
1443 | u8 bssid[ETH_ALEN]; | ||
1444 | u8 bss_flags; /* enum wmi_bss_flags */ | ||
1445 | } __packed; | ||
1446 | |||
1447 | struct wmi_neighbor_report_event { | ||
1448 | u8 num_neighbors; | ||
1449 | struct wmi_neighbor_info neighbor[0]; | ||
1450 | } __packed; | ||
1451 | |||
1333 | /* TKIP MIC Error Event */ | 1452 | /* TKIP MIC Error Event */ |
1334 | struct wmi_tkip_micerr_event { | 1453 | struct wmi_tkip_micerr_event { |
1335 | u8 key_id; | 1454 | u8 key_id; |
@@ -1642,6 +1761,12 @@ struct wmi_get_keepalive_cmd { | |||
1642 | u8 keep_alive_intvl; | 1761 | u8 keep_alive_intvl; |
1643 | } __packed; | 1762 | } __packed; |
1644 | 1763 | ||
1764 | struct wmi_set_appie_cmd { | ||
1765 | u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ | ||
1766 | u8 ie_len; | ||
1767 | u8 ie_info[0]; | ||
1768 | } __packed; | ||
1769 | |||
1645 | /* Notify the WSC registration status to the target */ | 1770 | /* Notify the WSC registration status to the target */ |
1646 | #define WSC_REG_ACTIVE 1 | 1771 | #define WSC_REG_ACTIVE 1 |
1647 | #define WSC_REG_INACTIVE 0 | 1772 | #define WSC_REG_INACTIVE 0 |
@@ -1789,8 +1914,26 @@ struct wmi_tx_complete_event { | |||
1789 | 1914 | ||
1790 | /* Used with WMI_AP_SET_NUM_STA_CMDID */ | 1915 | /* Used with WMI_AP_SET_NUM_STA_CMDID */ |
1791 | 1916 | ||
1917 | /* | ||
1918 | * Used with WMI_AP_SET_MLME_CMDID | ||
1919 | */ | ||
1920 | |||
1921 | /* MLME Commands */ | ||
1922 | #define WMI_AP_MLME_ASSOC 1 /* associate station */ | ||
1923 | #define WMI_AP_DISASSOC 2 /* disassociate station */ | ||
1924 | #define WMI_AP_DEAUTH 3 /* deauthenticate station */ | ||
1925 | #define WMI_AP_MLME_AUTHORIZE 4 /* authorize station */ | ||
1926 | #define WMI_AP_MLME_UNAUTHORIZE 5 /* unauthorize station */ | ||
1927 | |||
1928 | struct wmi_ap_set_mlme_cmd { | ||
1929 | u8 mac[ETH_ALEN]; | ||
1930 | __le16 reason; /* 802.11 reason code */ | ||
1931 | u8 cmd; /* operation to perform (WMI_AP_*) */ | ||
1932 | } __packed; | ||
1933 | |||
1792 | struct wmi_ap_set_pvb_cmd { | 1934 | struct wmi_ap_set_pvb_cmd { |
1793 | __le32 flag; | 1935 | __le32 flag; |
1936 | __le16 rsvd; | ||
1794 | __le16 aid; | 1937 | __le16 aid; |
1795 | } __packed; | 1938 | } __packed; |
1796 | 1939 | ||
@@ -1840,6 +1983,100 @@ struct wmi_ap_mode_stat { | |||
1840 | 1983 | ||
1841 | /* End of AP mode definitions */ | 1984 | /* End of AP mode definitions */ |
1842 | 1985 | ||
1986 | struct wmi_remain_on_chnl_cmd { | ||
1987 | __le32 freq; | ||
1988 | __le32 duration; | ||
1989 | } __packed; | ||
1990 | |||
1991 | struct wmi_send_action_cmd { | ||
1992 | __le32 id; | ||
1993 | __le32 freq; | ||
1994 | __le32 wait; | ||
1995 | __le16 len; | ||
1996 | u8 data[0]; | ||
1997 | } __packed; | ||
1998 | |||
1999 | struct wmi_tx_status_event { | ||
2000 | __le32 id; | ||
2001 | u8 ack_status; | ||
2002 | } __packed; | ||
2003 | |||
2004 | struct wmi_probe_req_report_cmd { | ||
2005 | u8 enable; | ||
2006 | } __packed; | ||
2007 | |||
2008 | struct wmi_disable_11b_rates_cmd { | ||
2009 | u8 disable; | ||
2010 | } __packed; | ||
2011 | |||
2012 | struct wmi_set_appie_extended_cmd { | ||
2013 | u8 role_id; | ||
2014 | u8 mgmt_frm_type; | ||
2015 | u8 ie_len; | ||
2016 | u8 ie_info[0]; | ||
2017 | } __packed; | ||
2018 | |||
2019 | struct wmi_remain_on_chnl_event { | ||
2020 | __le32 freq; | ||
2021 | __le32 duration; | ||
2022 | } __packed; | ||
2023 | |||
2024 | struct wmi_cancel_remain_on_chnl_event { | ||
2025 | __le32 freq; | ||
2026 | __le32 duration; | ||
2027 | u8 status; | ||
2028 | } __packed; | ||
2029 | |||
2030 | struct wmi_rx_action_event { | ||
2031 | __le32 freq; | ||
2032 | __le16 len; | ||
2033 | u8 data[0]; | ||
2034 | } __packed; | ||
2035 | |||
2036 | struct wmi_p2p_capabilities_event { | ||
2037 | __le16 len; | ||
2038 | u8 data[0]; | ||
2039 | } __packed; | ||
2040 | |||
2041 | struct wmi_p2p_rx_probe_req_event { | ||
2042 | __le32 freq; | ||
2043 | __le16 len; | ||
2044 | u8 data[0]; | ||
2045 | } __packed; | ||
2046 | |||
2047 | #define P2P_FLAG_CAPABILITIES_REQ (0x00000001) | ||
2048 | #define P2P_FLAG_MACADDR_REQ (0x00000002) | ||
2049 | #define P2P_FLAG_HMODEL_REQ (0x00000002) | ||
2050 | |||
2051 | struct wmi_get_p2p_info { | ||
2052 | __le32 info_req_flags; | ||
2053 | } __packed; | ||
2054 | |||
2055 | struct wmi_p2p_info_event { | ||
2056 | __le32 info_req_flags; | ||
2057 | __le16 len; | ||
2058 | u8 data[0]; | ||
2059 | } __packed; | ||
2060 | |||
2061 | struct wmi_p2p_capabilities { | ||
2062 | u8 go_power_save; | ||
2063 | } __packed; | ||
2064 | |||
2065 | struct wmi_p2p_macaddr { | ||
2066 | u8 mac_addr[ETH_ALEN]; | ||
2067 | } __packed; | ||
2068 | |||
2069 | struct wmi_p2p_hmodel { | ||
2070 | u8 p2p_model; | ||
2071 | } __packed; | ||
2072 | |||
2073 | struct wmi_p2p_probe_response_cmd { | ||
2074 | __le32 freq; | ||
2075 | u8 destination_addr[ETH_ALEN]; | ||
2076 | __le16 len; | ||
2077 | u8 data[0]; | ||
2078 | } __packed; | ||
2079 | |||
1843 | /* Extended WMI (WMIX) | 2080 | /* Extended WMI (WMIX) |
1844 | * | 2081 | * |
1845 | * Extended WMIX commands are encapsulated in a WMI message with | 2082 | * Extended WMIX commands are encapsulated in a WMI message with |
@@ -1898,6 +2135,11 @@ struct wmix_hb_challenge_resp_cmd { | |||
1898 | __le32 source; | 2135 | __le32 source; |
1899 | } __packed; | 2136 | } __packed; |
1900 | 2137 | ||
2138 | struct ath6kl_wmix_dbglog_cfg_module_cmd { | ||
2139 | __le32 valid; | ||
2140 | __le32 config; | ||
2141 | } __packed; | ||
2142 | |||
1901 | /* End of Extended WMI (WMIX) */ | 2143 | /* End of Extended WMI (WMIX) */ |
1902 | 2144 | ||
1903 | enum wmi_sync_flag { | 2145 | enum wmi_sync_flag { |
@@ -1925,14 +2167,11 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, | |||
1925 | 2167 | ||
1926 | int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb); | 2168 | int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb); |
1927 | int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb); | 2169 | int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb); |
1928 | int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb); | ||
1929 | int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb, | 2170 | int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb, |
1930 | u32 layer2_priority, bool wmm_enabled, | 2171 | u32 layer2_priority, bool wmm_enabled, |
1931 | u8 *ac); | 2172 | u8 *ac); |
1932 | 2173 | ||
1933 | int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb); | 2174 | int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb); |
1934 | struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 *mac_addr); | ||
1935 | void ath6kl_wmi_node_free(struct wmi *wmi, const u8 *mac_addr); | ||
1936 | 2175 | ||
1937 | int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb, | 2176 | int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb, |
1938 | enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag); | 2177 | enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag); |
@@ -1978,6 +2217,7 @@ int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, | |||
1978 | u8 preamble_policy); | 2217 | u8 preamble_policy); |
1979 | 2218 | ||
1980 | int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source); | 2219 | int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source); |
2220 | int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config); | ||
1981 | 2221 | ||
1982 | int ath6kl_wmi_get_stats_cmd(struct wmi *wmi); | 2222 | int ath6kl_wmi_get_stats_cmd(struct wmi *wmi); |
1983 | int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index, | 2223 | int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index, |
@@ -1995,23 +2235,47 @@ int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi); | |||
1995 | 2235 | ||
1996 | int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg); | 2236 | int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg); |
1997 | int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl); | 2237 | int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl); |
2238 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); | ||
1998 | 2239 | ||
1999 | s32 ath6kl_wmi_get_rate(s8 rate_index); | 2240 | s32 ath6kl_wmi_get_rate(s8 rate_index); |
2000 | 2241 | ||
2001 | int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd); | 2242 | int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd); |
2243 | int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); | ||
2002 | 2244 | ||
2003 | struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 *ssid, | 2245 | /* AP mode */ |
2004 | u32 ssid_len, bool is_wpa2, | 2246 | int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p); |
2005 | bool match_ssid); | ||
2006 | 2247 | ||
2007 | void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss); | 2248 | int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason); |
2008 | 2249 | ||
2009 | /* AP mode */ | ||
2010 | int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag); | 2250 | int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag); |
2011 | 2251 | ||
2012 | int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_version, | 2252 | int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_version, |
2013 | bool rx_dot11_hdr, bool defrag_on_host); | 2253 | bool rx_dot11_hdr, bool defrag_on_host); |
2014 | 2254 | ||
2255 | int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie, | ||
2256 | u8 ie_len); | ||
2257 | |||
2258 | /* P2P */ | ||
2259 | int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable); | ||
2260 | |||
2261 | int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur); | ||
2262 | |||
2263 | int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait, | ||
2264 | const u8 *data, u16 data_len); | ||
2265 | |||
2266 | int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq, | ||
2267 | const u8 *dst, | ||
2268 | const u8 *data, u16 data_len); | ||
2269 | |||
2270 | int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable); | ||
2271 | |||
2272 | int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags); | ||
2273 | |||
2274 | int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi); | ||
2275 | |||
2276 | int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie, | ||
2277 | u8 ie_len); | ||
2278 | |||
2015 | void *ath6kl_wmi_init(struct ath6kl *devt); | 2279 | void *ath6kl_wmi_init(struct ath6kl *devt); |
2016 | void ath6kl_wmi_shutdown(struct wmi *wmi); | 2280 | void ath6kl_wmi_shutdown(struct wmi *wmi); |
2017 | 2281 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 94d887b65e69..1e8614783181 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -340,7 +340,8 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | |||
340 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 340 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
341 | 341 | ||
342 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); | 342 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); |
343 | bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); | 343 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, |
344 | struct ath_node *an); | ||
344 | 345 | ||
345 | /********/ | 346 | /********/ |
346 | /* VIFs */ | 347 | /* VIFs */ |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index a3c7d0c247a3..5d92f96980e6 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -104,16 +104,11 @@ | |||
104 | #define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \ | 104 | #define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \ |
105 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | 105 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) |
106 | 106 | ||
107 | #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c | ||
108 | #define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 | ||
109 | #define AR_EEPROM_RFSILENT_POLARITY 0x0002 | ||
110 | #define AR_EEPROM_RFSILENT_POLARITY_S 1 | ||
111 | |||
112 | #define EEP_RFSILENT_ENABLED 0x0001 | 107 | #define EEP_RFSILENT_ENABLED 0x0001 |
113 | #define EEP_RFSILENT_ENABLED_S 0 | 108 | #define EEP_RFSILENT_ENABLED_S 0 |
114 | #define EEP_RFSILENT_POLARITY 0x0002 | 109 | #define EEP_RFSILENT_POLARITY 0x0002 |
115 | #define EEP_RFSILENT_POLARITY_S 1 | 110 | #define EEP_RFSILENT_POLARITY_S 1 |
116 | #define EEP_RFSILENT_GPIO_SEL 0x001c | 111 | #define EEP_RFSILENT_GPIO_SEL (AR_SREV_9480(ah) ? 0x00fc : 0x001c) |
117 | #define EEP_RFSILENT_GPIO_SEL_S 2 | 112 | #define EEP_RFSILENT_GPIO_SEL_S 2 |
118 | 113 | ||
119 | #define AR5416_OPFLAGS_11A 0x01 | 114 | #define AR5416_OPFLAGS_11A 0x01 |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index afbf5400a52a..fd0f84ebdb51 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -84,9 +84,14 @@ void ath_init_leds(struct ath_softc *sc) | |||
84 | static bool ath_is_rfkill_set(struct ath_softc *sc) | 84 | static bool ath_is_rfkill_set(struct ath_softc *sc) |
85 | { | 85 | { |
86 | struct ath_hw *ah = sc->sc_ah; | 86 | struct ath_hw *ah = sc->sc_ah; |
87 | bool is_blocked; | ||
87 | 88 | ||
88 | return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == | 89 | ath9k_ps_wakeup(sc); |
90 | is_blocked = ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == | ||
89 | ah->rfkill_polarity; | 91 | ah->rfkill_polarity; |
92 | ath9k_ps_restore(sc); | ||
93 | |||
94 | return is_blocked; | ||
90 | } | 95 | } |
91 | 96 | ||
92 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) | 97 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index d3f4a59cd456..77c8ded8de57 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { | |||
38 | { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ | 38 | { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ |
39 | { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ | 39 | { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ |
40 | { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ | 40 | { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ |
41 | { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ | ||
41 | 42 | ||
42 | { USB_DEVICE(0x0cf3, 0x7015), | 43 | { USB_DEVICE(0x0cf3, 0x7015), |
43 | .driver_info = AR9287_USB }, /* Atheros */ | 44 | .driver_info = AR9287_USB }, /* Atheros */ |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index db2352e5cc0d..e3a02eb8e0cc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -228,8 +228,14 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv) | |||
228 | 228 | ||
229 | static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) | 229 | static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) |
230 | { | 230 | { |
231 | return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == | 231 | bool is_blocked; |
232 | priv->ah->rfkill_polarity; | 232 | |
233 | ath9k_htc_ps_wakeup(priv); | ||
234 | is_blocked = ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == | ||
235 | priv->ah->rfkill_polarity; | ||
236 | ath9k_htc_ps_restore(priv); | ||
237 | |||
238 | return is_blocked; | ||
233 | } | 239 | } |
234 | 240 | ||
235 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) | 241 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 17dbbd9d2f53..0b9a0e8a4958 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1352,7 +1352,8 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, | |||
1352 | return ret; | 1352 | return ret; |
1353 | } | 1353 | } |
1354 | 1354 | ||
1355 | static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1355 | static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, |
1356 | struct ieee80211_vif *vif, u16 queue, | ||
1356 | const struct ieee80211_tx_queue_params *params) | 1357 | const struct ieee80211_tx_queue_params *params) |
1357 | { | 1358 | { |
1358 | struct ath9k_htc_priv *priv = hw->priv; | 1359 | struct ath9k_htc_priv *priv = hw->priv; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f2de7ee047ce..42ebe8fb053a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -284,7 +284,12 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) | |||
284 | ah->hw_version.macVersion = | 284 | ah->hw_version.macVersion = |
285 | (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; | 285 | (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; |
286 | ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); | 286 | ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); |
287 | ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; | 287 | |
288 | if (AR_SREV_9480(ah)) | ||
289 | ah->is_pciexpress = true; | ||
290 | else | ||
291 | ah->is_pciexpress = (val & | ||
292 | AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; | ||
288 | } else { | 293 | } else { |
289 | if (!AR_SREV_9100(ah)) | 294 | if (!AR_SREV_9100(ah)) |
290 | ah->hw_version.macVersion = MS(val, AR_SREV_VERSION); | 295 | ah->hw_version.macVersion = MS(val, AR_SREV_VERSION); |
@@ -2153,6 +2158,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2153 | pCap->num_gpio_pins = AR9271_NUM_GPIO; | 2158 | pCap->num_gpio_pins = AR9271_NUM_GPIO; |
2154 | else if (AR_DEVID_7010(ah)) | 2159 | else if (AR_DEVID_7010(ah)) |
2155 | pCap->num_gpio_pins = AR7010_NUM_GPIO; | 2160 | pCap->num_gpio_pins = AR7010_NUM_GPIO; |
2161 | else if (AR_SREV_9300_20_OR_LATER(ah)) | ||
2162 | pCap->num_gpio_pins = AR9300_NUM_GPIO; | ||
2163 | else if (AR_SREV_9287_11_OR_LATER(ah)) | ||
2164 | pCap->num_gpio_pins = AR9287_NUM_GPIO; | ||
2156 | else if (AR_SREV_9285_12_OR_LATER(ah)) | 2165 | else if (AR_SREV_9285_12_OR_LATER(ah)) |
2157 | pCap->num_gpio_pins = AR9285_NUM_GPIO; | 2166 | pCap->num_gpio_pins = AR9285_NUM_GPIO; |
2158 | else if (AR_SREV_9280_20_OR_LATER(ah)) | 2167 | else if (AR_SREV_9280_20_OR_LATER(ah)) |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index edaa7843bf4c..988318665758 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1833,8 +1833,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, | |||
1833 | switch (cmd) { | 1833 | switch (cmd) { |
1834 | case STA_NOTIFY_SLEEP: | 1834 | case STA_NOTIFY_SLEEP: |
1835 | an->sleeping = true; | 1835 | an->sleeping = true; |
1836 | if (ath_tx_aggr_sleep(sc, an)) | 1836 | ath_tx_aggr_sleep(sta, sc, an); |
1837 | ieee80211_sta_set_tim(sta); | ||
1838 | break; | 1837 | break; |
1839 | case STA_NOTIFY_AWAKE: | 1838 | case STA_NOTIFY_AWAKE: |
1840 | an->sleeping = false; | 1839 | an->sleeping = false; |
@@ -1843,7 +1842,8 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, | |||
1843 | } | 1842 | } |
1844 | } | 1843 | } |
1845 | 1844 | ||
1846 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1845 | static int ath9k_conf_tx(struct ieee80211_hw *hw, |
1846 | struct ieee80211_vif *vif, u16 queue, | ||
1847 | const struct ieee80211_tx_queue_params *params) | 1847 | const struct ieee80211_tx_queue_params *params) |
1848 | { | 1848 | { |
1849 | struct ath_softc *sc = hw->priv; | 1849 | struct ath_softc *sc = hw->priv; |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 4f1301881137..8448281dd069 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1362,12 +1362,6 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1362 | if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) | 1362 | if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) |
1363 | return; | 1363 | return; |
1364 | 1364 | ||
1365 | if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) { | ||
1366 | tx_info->status.ampdu_ack_len = | ||
1367 | (tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0); | ||
1368 | tx_info->status.ampdu_len = 1; | ||
1369 | } | ||
1370 | |||
1371 | if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) | 1365 | if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) |
1372 | tx_status = 1; | 1366 | tx_status = 1; |
1373 | 1367 | ||
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 49843500fe7c..f658ec60b510 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -586,22 +586,11 @@ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) | |||
586 | 586 | ||
587 | static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | 587 | static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) |
588 | { | 588 | { |
589 | struct ieee80211_mgmt *mgmt; | ||
590 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 589 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
591 | 590 | ||
592 | if (skb->len < 24 + 8 + 2 + 2) | 591 | if (skb->len < 24 + 8 + 2 + 2) |
593 | return; | 592 | return; |
594 | 593 | ||
595 | mgmt = (struct ieee80211_mgmt *)skb->data; | ||
596 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) { | ||
597 | /* TODO: This doesn't work well if you have stations | ||
598 | * associated to two different APs because curbssid | ||
599 | * is just the last AP that any of the stations associated | ||
600 | * with. | ||
601 | */ | ||
602 | return; /* not from our current AP */ | ||
603 | } | ||
604 | |||
605 | sc->ps_flags &= ~PS_WAIT_FOR_BEACON; | 594 | sc->ps_flags &= ~PS_WAIT_FOR_BEACON; |
606 | 595 | ||
607 | if (sc->ps_flags & PS_BEACON_SYNC) { | 596 | if (sc->ps_flags & PS_BEACON_SYNC) { |
@@ -637,7 +626,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
637 | } | 626 | } |
638 | } | 627 | } |
639 | 628 | ||
640 | static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | 629 | static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon) |
641 | { | 630 | { |
642 | struct ieee80211_hdr *hdr; | 631 | struct ieee80211_hdr *hdr; |
643 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 632 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -646,7 +635,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
646 | 635 | ||
647 | /* Process Beacon and CAB receive in PS state */ | 636 | /* Process Beacon and CAB receive in PS state */ |
648 | if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) | 637 | if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) |
649 | && ieee80211_is_beacon(hdr->frame_control)) | 638 | && mybeacon) |
650 | ath_rx_ps_beacon(sc, skb); | 639 | ath_rx_ps_beacon(sc, skb); |
651 | else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && | 640 | else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && |
652 | (ieee80211_is_data(hdr->frame_control) || | 641 | (ieee80211_is_data(hdr->frame_control) || |
@@ -1952,10 +1941,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1952 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 1941 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
1953 | 1942 | ||
1954 | if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | | 1943 | if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | |
1955 | PS_WAIT_FOR_CAB | | 1944 | PS_WAIT_FOR_CAB | |
1956 | PS_WAIT_FOR_PSPOLL_DATA)) || | 1945 | PS_WAIT_FOR_PSPOLL_DATA)) || |
1957 | ath9k_check_auto_sleep(sc)) | 1946 | ath9k_check_auto_sleep(sc)) |
1958 | ath_rx_ps(sc, skb); | 1947 | ath_rx_ps(sc, skb, rs.is_mybeacon); |
1959 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 1948 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
1960 | 1949 | ||
1961 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3) | 1950 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3) |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index fa3dcfdf7174..c2bfc57958d8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -542,7 +542,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
542 | /* prepend un-acked frames to the beginning of the pending frame queue */ | 542 | /* prepend un-acked frames to the beginning of the pending frame queue */ |
543 | if (!skb_queue_empty(&bf_pending)) { | 543 | if (!skb_queue_empty(&bf_pending)) { |
544 | if (an->sleeping) | 544 | if (an->sleeping) |
545 | ieee80211_sta_set_tim(sta); | 545 | ieee80211_sta_set_buffered(sta, tid->tidno, true); |
546 | 546 | ||
547 | spin_lock_bh(&txq->axq_lock); | 547 | spin_lock_bh(&txq->axq_lock); |
548 | if (clear_filter) | 548 | if (clear_filter) |
@@ -1153,12 +1153,13 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
1153 | ath_tx_flush_tid(sc, txtid); | 1153 | ath_tx_flush_tid(sc, txtid); |
1154 | } | 1154 | } |
1155 | 1155 | ||
1156 | bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) | 1156 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, |
1157 | struct ath_node *an) | ||
1157 | { | 1158 | { |
1158 | struct ath_atx_tid *tid; | 1159 | struct ath_atx_tid *tid; |
1159 | struct ath_atx_ac *ac; | 1160 | struct ath_atx_ac *ac; |
1160 | struct ath_txq *txq; | 1161 | struct ath_txq *txq; |
1161 | bool buffered = false; | 1162 | bool buffered; |
1162 | int tidno; | 1163 | int tidno; |
1163 | 1164 | ||
1164 | for (tidno = 0, tid = &an->tid[tidno]; | 1165 | for (tidno = 0, tid = &an->tid[tidno]; |
@@ -1172,8 +1173,7 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) | |||
1172 | 1173 | ||
1173 | spin_lock_bh(&txq->axq_lock); | 1174 | spin_lock_bh(&txq->axq_lock); |
1174 | 1175 | ||
1175 | if (!skb_queue_empty(&tid->buf_q)) | 1176 | buffered = !skb_queue_empty(&tid->buf_q); |
1176 | buffered = true; | ||
1177 | 1177 | ||
1178 | tid->sched = false; | 1178 | tid->sched = false; |
1179 | list_del(&tid->list); | 1179 | list_del(&tid->list); |
@@ -1184,9 +1184,9 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) | |||
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | spin_unlock_bh(&txq->axq_lock); | 1186 | spin_unlock_bh(&txq->axq_lock); |
1187 | } | ||
1188 | 1187 | ||
1189 | return buffered; | 1188 | ieee80211_sta_set_buffered(sta, tidno, buffered); |
1189 | } | ||
1190 | } | 1190 | } |
1191 | 1191 | ||
1192 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | 1192 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) |
@@ -2043,10 +2043,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, | |||
2043 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU; | 2043 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU; |
2044 | 2044 | ||
2045 | BUG_ON(nbad > nframes); | 2045 | BUG_ON(nbad > nframes); |
2046 | |||
2047 | tx_info->status.ampdu_len = nframes; | ||
2048 | tx_info->status.ampdu_ack_len = nframes - nbad; | ||
2049 | } | 2046 | } |
2047 | tx_info->status.ampdu_len = nframes; | ||
2048 | tx_info->status.ampdu_ack_len = nframes - nbad; | ||
2050 | 2049 | ||
2051 | if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && | 2050 | if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && |
2052 | (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) { | 2051 | (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) { |
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 8b780d6d470f..beca71073e9b 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -1305,7 +1305,8 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw, | |||
1305 | return 0; | 1305 | return 0; |
1306 | } | 1306 | } |
1307 | 1307 | ||
1308 | static int carl9170_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1308 | static int carl9170_op_conf_tx(struct ieee80211_hw *hw, |
1309 | struct ieee80211_vif *vif, u16 queue, | ||
1309 | const struct ieee80211_tx_queue_params *param) | 1310 | const struct ieee80211_tx_queue_params *param) |
1310 | { | 1311 | { |
1311 | struct ar9170 *ar = hw->priv; | 1312 | struct ar9170 *ar = hw->priv; |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 43400fb62e1c..7cf4125a1624 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -3559,7 +3559,8 @@ static void b43_qos_init(struct b43_wldev *dev) | |||
3559 | b43dbg(dev->wl, "QoS enabled\n"); | 3559 | b43dbg(dev->wl, "QoS enabled\n"); |
3560 | } | 3560 | } |
3561 | 3561 | ||
3562 | static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue, | 3562 | static int b43_op_conf_tx(struct ieee80211_hw *hw, |
3563 | struct ieee80211_vif *vif, u16 _queue, | ||
3563 | const struct ieee80211_tx_queue_params *params) | 3564 | const struct ieee80211_tx_queue_params *params) |
3564 | { | 3565 | { |
3565 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3566 | struct b43_wl *wl = hw_to_b43_wl(hw); |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 468d1836548e..a3b72cd72c66 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -2466,7 +2466,8 @@ out: | |||
2466 | } | 2466 | } |
2467 | } | 2467 | } |
2468 | 2468 | ||
2469 | static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | 2469 | static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, |
2470 | struct ieee80211_vif *vif, u16 queue, | ||
2470 | const struct ieee80211_tx_queue_params *params) | 2471 | const struct ieee80211_tx_queue_params *params) |
2471 | { | 2472 | { |
2472 | return 0; | 2473 | return 0; |
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c index ac4f64de1363..7f12e3638bae 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c | |||
@@ -335,7 +335,7 @@ int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
335 | sta_priv = (void *)sta->drv_priv; | 335 | sta_priv = (void *)sta->drv_priv; |
336 | 336 | ||
337 | if (sta_priv && sta_priv->asleep && | 337 | if (sta_priv && sta_priv->asleep && |
338 | (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) { | 338 | (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) { |
339 | /* | 339 | /* |
340 | * This sends an asynchronous command to the device, | 340 | * This sends an asynchronous command to the device, |
341 | * but we can rely on it being processed before the | 341 | * but we can rely on it being processed before the |
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index 8928d47432df..2bd5659310d7 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c | |||
@@ -1250,7 +1250,8 @@ void iwl_legacy_clear_isr_stats(struct iwl_priv *priv) | |||
1250 | memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); | 1250 | memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); |
1251 | } | 1251 | } |
1252 | 1252 | ||
1253 | int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1253 | int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, |
1254 | struct ieee80211_vif *vif, u16 queue, | ||
1254 | const struct ieee80211_tx_queue_params *params) | 1255 | const struct ieee80211_tx_queue_params *params) |
1255 | { | 1256 | { |
1256 | struct iwl_priv *priv = hw->priv; | 1257 | struct iwl_priv *priv = hw->priv; |
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h index b2df01c8f8f5..d1271fe07d4b 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.h +++ b/drivers/net/wireless/iwlegacy/iwl-core.h | |||
@@ -286,7 +286,8 @@ struct iwl_cfg { | |||
286 | ***************************/ | 286 | ***************************/ |
287 | 287 | ||
288 | struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg); | 288 | struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg); |
289 | int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 289 | int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, |
290 | struct ieee80211_vif *vif, u16 queue, | ||
290 | const struct ieee80211_tx_queue_params *params); | 291 | const struct ieee80211_tx_queue_params *params); |
291 | int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw); | 292 | int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw); |
292 | void iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv, | 293 | void iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 1d7572f9887f..e0441033788c 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | config IWLAGN | 1 | config IWLWIFI |
2 | tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlagn) " | 2 | tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) " |
3 | depends on PCI && MAC80211 | 3 | depends on PCI && MAC80211 |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | select NEW_LEDS | 5 | select NEW_LEDS |
@@ -39,14 +39,14 @@ config IWLAGN | |||
39 | If you want to compile the driver as a module ( = code which can be | 39 | If you want to compile the driver as a module ( = code which can be |
40 | inserted in and removed from the running kernel whenever you want), | 40 | inserted in and removed from the running kernel whenever you want), |
41 | say M here and read <file:Documentation/kbuild/modules.txt>. The | 41 | say M here and read <file:Documentation/kbuild/modules.txt>. The |
42 | module will be called iwlagn. | 42 | module will be called iwlwifi. |
43 | 43 | ||
44 | menu "Debugging Options" | 44 | menu "Debugging Options" |
45 | depends on IWLAGN | 45 | depends on IWLWIFI |
46 | 46 | ||
47 | config IWLWIFI_DEBUG | 47 | config IWLWIFI_DEBUG |
48 | bool "Enable full debugging output in the iwlagn driver" | 48 | bool "Enable full debugging output in the iwlwifi driver" |
49 | depends on IWLAGN | 49 | depends on IWLWIFI |
50 | ---help--- | 50 | ---help--- |
51 | This option will enable debug tracing output for the iwlwifi drivers | 51 | This option will enable debug tracing output for the iwlwifi drivers |
52 | 52 | ||
@@ -70,8 +70,8 @@ config IWLWIFI_DEBUG | |||
70 | any problems you may encounter. | 70 | any problems you may encounter. |
71 | 71 | ||
72 | config IWLWIFI_DEBUGFS | 72 | config IWLWIFI_DEBUGFS |
73 | bool "iwlagn debugfs support" | 73 | bool "iwlwifi debugfs support" |
74 | depends on IWLAGN && MAC80211_DEBUGFS | 74 | depends on IWLWIFI && MAC80211_DEBUGFS |
75 | ---help--- | 75 | ---help--- |
76 | Enable creation of debugfs files for the iwlwifi drivers. This | 76 | Enable creation of debugfs files for the iwlwifi drivers. This |
77 | is a low-impact option that allows getting insight into the | 77 | is a low-impact option that allows getting insight into the |
@@ -79,13 +79,13 @@ config IWLWIFI_DEBUGFS | |||
79 | 79 | ||
80 | config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | 80 | config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE |
81 | bool "Experimental uCode support" | 81 | bool "Experimental uCode support" |
82 | depends on IWLAGN && IWLWIFI_DEBUG | 82 | depends on IWLWIFI && IWLWIFI_DEBUG |
83 | ---help--- | 83 | ---help--- |
84 | Enable use of experimental ucode for testing and debugging. | 84 | Enable use of experimental ucode for testing and debugging. |
85 | 85 | ||
86 | config IWLWIFI_DEVICE_TRACING | 86 | config IWLWIFI_DEVICE_TRACING |
87 | bool "iwlwifi device access tracing" | 87 | bool "iwlwifi device access tracing" |
88 | depends on IWLAGN | 88 | depends on IWLWIFI |
89 | depends on EVENT_TRACING | 89 | depends on EVENT_TRACING |
90 | help | 90 | help |
91 | Say Y here to trace all commands, including TX frames and IO | 91 | Say Y here to trace all commands, including TX frames and IO |
@@ -104,7 +104,7 @@ endmenu | |||
104 | 104 | ||
105 | config IWLWIFI_DEVICE_SVTOOL | 105 | config IWLWIFI_DEVICE_SVTOOL |
106 | bool "iwlwifi device svtool support" | 106 | bool "iwlwifi device svtool support" |
107 | depends on IWLAGN | 107 | depends on IWLWIFI |
108 | select NL80211_TESTMODE | 108 | select NL80211_TESTMODE |
109 | help | 109 | help |
110 | This option enables the svtool support for iwlwifi device through | 110 | This option enables the svtool support for iwlwifi device through |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 8fa59cdb3b49..bacafa4a5f48 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,25 +1,25 @@ | |||
1 | # AGN | 1 | # WIFI |
2 | obj-$(CONFIG_IWLAGN) += iwlagn.o | 2 | obj-$(CONFIG_IWLWIFI) += iwlwifi.o |
3 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o | 3 | iwlwifi-objs := iwl-agn.o iwl-agn-rs.o |
4 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o | 4 | iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o |
5 | iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o | 5 | iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o |
6 | iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o | 6 | iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o |
7 | 7 | ||
8 | iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-power.o | 8 | iwlwifi-objs += iwl-core.o iwl-eeprom.o iwl-power.o |
9 | iwlagn-objs += iwl-rx.o iwl-sta.o | 9 | iwlwifi-objs += iwl-rx.o iwl-sta.o |
10 | iwlagn-objs += iwl-scan.o iwl-led.o | 10 | iwlwifi-objs += iwl-scan.o iwl-led.o |
11 | iwlagn-objs += iwl-agn-rxon.o | 11 | iwlwifi-objs += iwl-agn-rxon.o |
12 | iwlagn-objs += iwl-5000.o | 12 | iwlwifi-objs += iwl-5000.o |
13 | iwlagn-objs += iwl-6000.o | 13 | iwlwifi-objs += iwl-6000.o |
14 | iwlagn-objs += iwl-1000.o | 14 | iwlwifi-objs += iwl-1000.o |
15 | iwlagn-objs += iwl-2000.o | 15 | iwlwifi-objs += iwl-2000.o |
16 | iwlagn-objs += iwl-pci.o | 16 | iwlwifi-objs += iwl-pci.o |
17 | iwlagn-objs += iwl-trans.o | 17 | iwlwifi-objs += iwl-trans.o |
18 | iwlagn-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o | 18 | iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o |
19 | 19 | ||
20 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 20 | iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
21 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 21 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
22 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o | 22 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o |
23 | 23 | ||
24 | CFLAGS_iwl-devtrace.o := -I$(src) | 24 | CFLAGS_iwl-devtrace.o := -I$(src) |
25 | 25 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index c14f8d6fd7d8..7d6a3bf64950 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -2273,9 +2273,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2273 | info->flags & IEEE80211_TX_CTL_NO_ACK) | 2273 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
2274 | return; | 2274 | return; |
2275 | 2275 | ||
2276 | if (!sta || !lq_sta) | ||
2277 | return; | ||
2278 | |||
2279 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; | 2276 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; |
2280 | 2277 | ||
2281 | tid = rs_tl_add_packet(lq_sta, hdr); | 2278 | tid = rs_tl_add_packet(lq_sta, hdr); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 0e5d6498be21..dcb3bd67d4f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -300,7 +300,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
300 | sta_priv = (void *)info->control.sta->drv_priv; | 300 | sta_priv = (void *)info->control.sta->drv_priv; |
301 | 301 | ||
302 | if (sta_priv && sta_priv->asleep && | 302 | if (sta_priv && sta_priv->asleep && |
303 | (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) { | 303 | (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) { |
304 | /* | 304 | /* |
305 | * This sends an asynchronous command to the device, | 305 | * This sends an asynchronous command to the device, |
306 | * but we can rely on it being processed before the | 306 | * but we can rely on it being processed before the |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index baaf48616cc7..d0fd6f063bf8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -79,6 +79,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); | |||
79 | MODULE_VERSION(DRV_VERSION); | 79 | MODULE_VERSION(DRV_VERSION); |
80 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | 80 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); |
81 | MODULE_LICENSE("GPL"); | 81 | MODULE_LICENSE("GPL"); |
82 | MODULE_ALIAS("iwlagn"); | ||
82 | 83 | ||
83 | void iwl_update_chain_flags(struct iwl_priv *priv) | 84 | void iwl_update_chain_flags(struct iwl_priv *priv) |
84 | { | 85 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index fc400bb2bdff..0725603dbf1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -1123,8 +1123,9 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | |||
1123 | &statistics_cmd); | 1123 | &statistics_cmd); |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1126 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, |
1127 | const struct ieee80211_tx_queue_params *params) | 1127 | struct ieee80211_vif *vif, u16 queue, |
1128 | const struct ieee80211_tx_queue_params *params) | ||
1128 | { | 1129 | { |
1129 | struct iwl_priv *priv = hw->priv; | 1130 | struct iwl_priv *priv = hw->priv; |
1130 | struct iwl_rxon_context *ctx; | 1131 | struct iwl_rxon_context *ctx; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e55ffad83950..db50b650756c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -236,7 +236,8 @@ struct iwl_cfg { | |||
236 | * L i b * | 236 | * L i b * |
237 | ***************************/ | 237 | ***************************/ |
238 | 238 | ||
239 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 239 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, |
240 | struct ieee80211_vif *vif, u16 queue, | ||
240 | const struct ieee80211_tx_queue_params *params); | 241 | const struct ieee80211_tx_queue_params *params); |
241 | int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); | 242 | int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); |
242 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | 243 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 8747bbdf8983..3a24b477b8fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h | |||
@@ -100,7 +100,7 @@ struct iwl_priv; | |||
100 | struct iwl_sensitivity_ranges; | 100 | struct iwl_sensitivity_ranges; |
101 | struct iwl_trans_ops; | 101 | struct iwl_trans_ops; |
102 | 102 | ||
103 | #define DRV_NAME "iwlagn" | 103 | #define DRV_NAME "iwlwifi" |
104 | #define IWLWIFI_VERSION "in-tree:" | 104 | #define IWLWIFI_VERSION "in-tree:" |
105 | #define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" | 105 | #define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" |
106 | #define DRV_AUTHOR "<ilw@linux.intel.com>" | 106 | #define DRV_AUTHOR "<ilw@linux.intel.com>" |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index fb3e40bf5902..f3fd447131c2 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -158,6 +158,7 @@ struct lbs_private { | |||
158 | /* protected by hard_start_xmit serialization */ | 158 | /* protected by hard_start_xmit serialization */ |
159 | u8 txretrycount; | 159 | u8 txretrycount; |
160 | struct sk_buff *currenttxskb; | 160 | struct sk_buff *currenttxskb; |
161 | struct timer_list tx_lockup_timer; | ||
161 | 162 | ||
162 | /* Locks */ | 163 | /* Locks */ |
163 | struct mutex lock; | 164 | struct mutex lock; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index d1c1d52931f1..c50ae07e2e89 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -188,6 +188,7 @@ int lbs_stop_iface(struct lbs_private *priv) | |||
188 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 188 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
189 | 189 | ||
190 | cancel_work_sync(&priv->mcast_work); | 190 | cancel_work_sync(&priv->mcast_work); |
191 | del_timer_sync(&priv->tx_lockup_timer); | ||
191 | 192 | ||
192 | /* Disable command processing, and wait for all commands to complete */ | 193 | /* Disable command processing, and wait for all commands to complete */ |
193 | lbs_deb_main("waiting for commands to complete\n"); | 194 | lbs_deb_main("waiting for commands to complete\n"); |
@@ -243,6 +244,7 @@ void lbs_host_to_card_done(struct lbs_private *priv) | |||
243 | lbs_deb_enter(LBS_DEB_THREAD); | 244 | lbs_deb_enter(LBS_DEB_THREAD); |
244 | 245 | ||
245 | spin_lock_irqsave(&priv->driver_lock, flags); | 246 | spin_lock_irqsave(&priv->driver_lock, flags); |
247 | del_timer(&priv->tx_lockup_timer); | ||
246 | 248 | ||
247 | priv->dnld_sent = DNLD_RES_RECEIVED; | 249 | priv->dnld_sent = DNLD_RES_RECEIVED; |
248 | 250 | ||
@@ -585,6 +587,9 @@ static int lbs_thread(void *data) | |||
585 | if (ret) { | 587 | if (ret) { |
586 | lbs_deb_tx("host_to_card failed %d\n", ret); | 588 | lbs_deb_tx("host_to_card failed %d\n", ret); |
587 | priv->dnld_sent = DNLD_RES_RECEIVED; | 589 | priv->dnld_sent = DNLD_RES_RECEIVED; |
590 | } else { | ||
591 | mod_timer(&priv->tx_lockup_timer, | ||
592 | jiffies + (HZ * 5)); | ||
588 | } | 593 | } |
589 | priv->tx_pending_len = 0; | 594 | priv->tx_pending_len = 0; |
590 | if (!priv->currenttxskb) { | 595 | if (!priv->currenttxskb) { |
@@ -601,6 +606,7 @@ static int lbs_thread(void *data) | |||
601 | } | 606 | } |
602 | 607 | ||
603 | del_timer(&priv->command_timer); | 608 | del_timer(&priv->command_timer); |
609 | del_timer(&priv->tx_lockup_timer); | ||
604 | del_timer(&priv->auto_deepsleep_timer); | 610 | del_timer(&priv->auto_deepsleep_timer); |
605 | 611 | ||
606 | lbs_deb_leave(LBS_DEB_THREAD); | 612 | lbs_deb_leave(LBS_DEB_THREAD); |
@@ -735,6 +741,32 @@ out: | |||
735 | } | 741 | } |
736 | 742 | ||
737 | /** | 743 | /** |
744 | * lbs_tx_lockup_handler - handles the timeout of the passing of TX frames | ||
745 | * to the hardware. This is known to frequently happen with SD8686 when | ||
746 | * waking up after a Wake-on-WLAN-triggered resume. | ||
747 | * | ||
748 | * @data: &struct lbs_private pointer | ||
749 | */ | ||
750 | static void lbs_tx_lockup_handler(unsigned long data) | ||
751 | { | ||
752 | struct lbs_private *priv = (struct lbs_private *)data; | ||
753 | unsigned long flags; | ||
754 | |||
755 | lbs_deb_enter(LBS_DEB_TX); | ||
756 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
757 | |||
758 | netdev_info(priv->dev, "TX lockup detected\n"); | ||
759 | if (priv->reset_card) | ||
760 | priv->reset_card(priv); | ||
761 | |||
762 | priv->dnld_sent = DNLD_RES_RECEIVED; | ||
763 | wake_up_interruptible(&priv->waitq); | ||
764 | |||
765 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
766 | lbs_deb_leave(LBS_DEB_TX); | ||
767 | } | ||
768 | |||
769 | /** | ||
738 | * auto_deepsleep_timer_fn - put the device back to deep sleep mode when | 770 | * auto_deepsleep_timer_fn - put the device back to deep sleep mode when |
739 | * timer expires and no activity (command, event, data etc.) is detected. | 771 | * timer expires and no activity (command, event, data etc.) is detected. |
740 | * @data: &struct lbs_private pointer | 772 | * @data: &struct lbs_private pointer |
@@ -820,6 +852,8 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
820 | 852 | ||
821 | setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, | 853 | setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, |
822 | (unsigned long)priv); | 854 | (unsigned long)priv); |
855 | setup_timer(&priv->tx_lockup_timer, lbs_tx_lockup_handler, | ||
856 | (unsigned long)priv); | ||
823 | setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn, | 857 | setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn, |
824 | (unsigned long)priv); | 858 | (unsigned long)priv); |
825 | 859 | ||
@@ -857,6 +891,7 @@ static void lbs_free_adapter(struct lbs_private *priv) | |||
857 | lbs_free_cmd_buffer(priv); | 891 | lbs_free_cmd_buffer(priv); |
858 | kfifo_free(&priv->event_fifo); | 892 | kfifo_free(&priv->event_fifo); |
859 | del_timer(&priv->command_timer); | 893 | del_timer(&priv->command_timer); |
894 | del_timer(&priv->tx_lockup_timer); | ||
860 | del_timer(&priv->auto_deepsleep_timer); | 895 | del_timer(&priv->auto_deepsleep_timer); |
861 | 896 | ||
862 | lbs_deb_leave(LBS_DEB_MAIN); | 897 | lbs_deb_leave(LBS_DEB_MAIN); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 34b79fc91e39..68455a2307cb 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -970,7 +970,8 @@ static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw, | |||
970 | } | 970 | } |
971 | 971 | ||
972 | static int mac80211_hwsim_conf_tx( | 972 | static int mac80211_hwsim_conf_tx( |
973 | struct ieee80211_hw *hw, u16 queue, | 973 | struct ieee80211_hw *hw, |
974 | struct ieee80211_vif *vif, u16 queue, | ||
974 | const struct ieee80211_tx_queue_params *params) | 975 | const struct ieee80211_tx_queue_params *params) |
975 | { | 976 | { |
976 | wiphy_debug(hw->wiphy, | 977 | wiphy_debug(hw->wiphy, |
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 1a453a605b3f..9e63d16365e3 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c | |||
@@ -193,7 +193,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
193 | skb_src = skb_dequeue(&pra_list->skb_head); | 193 | skb_src = skb_dequeue(&pra_list->skb_head); |
194 | 194 | ||
195 | pra_list->total_pkts_size -= skb_src->len; | 195 | pra_list->total_pkts_size -= skb_src->len; |
196 | pra_list->total_pkts--; | ||
197 | 196 | ||
198 | atomic_dec(&priv->wmm.tx_pkts_queued); | 197 | atomic_dec(&priv->wmm.tx_pkts_queued); |
199 | 198 | ||
@@ -269,7 +268,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
269 | skb_queue_tail(&pra_list->skb_head, skb_aggr); | 268 | skb_queue_tail(&pra_list->skb_head, skb_aggr); |
270 | 269 | ||
271 | pra_list->total_pkts_size += skb_aggr->len; | 270 | pra_list->total_pkts_size += skb_aggr->len; |
272 | pra_list->total_pkts++; | ||
273 | 271 | ||
274 | atomic_inc(&priv->wmm.tx_pkts_queued); | 272 | atomic_inc(&priv->wmm.tx_pkts_queued); |
275 | 273 | ||
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.h b/drivers/net/wireless/mwifiex/11n_aggr.h index 9c6dca7ab02c..900e1c62a0cc 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.h +++ b/drivers/net/wireless/mwifiex/11n_aggr.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define _MWIFIEX_11N_AGGR_H_ | 21 | #define _MWIFIEX_11N_AGGR_H_ |
22 | 22 | ||
23 | #define PKT_TYPE_AMSDU 0xE6 | 23 | #define PKT_TYPE_AMSDU 0xE6 |
24 | #define MIN_NUM_AMSDU 2 | ||
24 | 25 | ||
25 | int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, | 26 | int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, |
26 | struct sk_buff *skb); | 27 | struct sk_buff *skb); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0ddcdca63cf7..462c71067bfb 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -543,12 +543,28 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
543 | ret = -EFAULT; | 543 | ret = -EFAULT; |
544 | } | 544 | } |
545 | 545 | ||
546 | /* | ||
547 | * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid | ||
548 | * MCS index values for us are 0 to 7. | ||
549 | */ | ||
550 | if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 8)) { | ||
551 | sinfo->txrate.mcs = priv->tx_rate; | ||
552 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | ||
553 | /* 40MHz rate */ | ||
554 | if (priv->tx_htinfo & BIT(1)) | ||
555 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
556 | /* SGI enabled */ | ||
557 | if (priv->tx_htinfo & BIT(2)) | ||
558 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
559 | } | ||
560 | |||
546 | sinfo->rx_bytes = priv->stats.rx_bytes; | 561 | sinfo->rx_bytes = priv->stats.rx_bytes; |
547 | sinfo->tx_bytes = priv->stats.tx_bytes; | 562 | sinfo->tx_bytes = priv->stats.tx_bytes; |
548 | sinfo->rx_packets = priv->stats.rx_packets; | 563 | sinfo->rx_packets = priv->stats.rx_packets; |
549 | sinfo->tx_packets = priv->stats.tx_packets; | 564 | sinfo->tx_packets = priv->stats.tx_packets; |
550 | sinfo->signal = priv->qual_level; | 565 | sinfo->signal = priv->qual_level; |
551 | sinfo->txrate.legacy = rate.rate; | 566 | /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */ |
567 | sinfo->txrate.legacy = rate.rate * 5; | ||
552 | 568 | ||
553 | return ret; | 569 | return ret; |
554 | } | 570 | } |
@@ -565,8 +581,6 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
565 | { | 581 | { |
566 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 582 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
567 | 583 | ||
568 | mwifiex_dump_station_info(priv, sinfo); | ||
569 | |||
570 | if (!priv->media_connected) | 584 | if (!priv->media_connected) |
571 | return -ENOENT; | 585 | return -ENOENT; |
572 | if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) | 586 | if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) |
@@ -1148,8 +1162,150 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, | |||
1148 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 1162 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
1149 | } | 1163 | } |
1150 | 1164 | ||
1165 | /* | ||
1166 | * create a new virtual interface with the given name | ||
1167 | */ | ||
1168 | struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | ||
1169 | char *name, | ||
1170 | enum nl80211_iftype type, | ||
1171 | u32 *flags, | ||
1172 | struct vif_params *params) | ||
1173 | { | ||
1174 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | ||
1175 | struct mwifiex_adapter *adapter; | ||
1176 | struct net_device *dev; | ||
1177 | void *mdev_priv; | ||
1178 | |||
1179 | if (!priv) | ||
1180 | return NULL; | ||
1181 | |||
1182 | adapter = priv->adapter; | ||
1183 | if (!adapter) | ||
1184 | return NULL; | ||
1185 | |||
1186 | switch (type) { | ||
1187 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1188 | case NL80211_IFTYPE_STATION: | ||
1189 | case NL80211_IFTYPE_ADHOC: | ||
1190 | if (priv->bss_mode) { | ||
1191 | wiphy_err(wiphy, "cannot create multiple" | ||
1192 | " station/adhoc interfaces\n"); | ||
1193 | return NULL; | ||
1194 | } | ||
1195 | |||
1196 | if (type == NL80211_IFTYPE_UNSPECIFIED) | ||
1197 | priv->bss_mode = NL80211_IFTYPE_STATION; | ||
1198 | else | ||
1199 | priv->bss_mode = type; | ||
1200 | |||
1201 | priv->bss_type = MWIFIEX_BSS_TYPE_STA; | ||
1202 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | ||
1203 | priv->bss_priority = 0; | ||
1204 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | ||
1205 | priv->bss_index = 0; | ||
1206 | priv->bss_num = 0; | ||
1207 | |||
1208 | break; | ||
1209 | default: | ||
1210 | wiphy_err(wiphy, "type not supported\n"); | ||
1211 | return NULL; | ||
1212 | } | ||
1213 | |||
1214 | dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name, | ||
1215 | ether_setup, 1); | ||
1216 | if (!dev) { | ||
1217 | wiphy_err(wiphy, "no memory available for netdevice\n"); | ||
1218 | goto error; | ||
1219 | } | ||
1220 | |||
1221 | dev_net_set(dev, wiphy_net(wiphy)); | ||
1222 | dev->ieee80211_ptr = priv->wdev; | ||
1223 | dev->ieee80211_ptr->iftype = priv->bss_mode; | ||
1224 | memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); | ||
1225 | memcpy(dev->perm_addr, wiphy->perm_addr, ETH_ALEN); | ||
1226 | SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); | ||
1227 | |||
1228 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | ||
1229 | dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; | ||
1230 | dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; | ||
1231 | |||
1232 | mdev_priv = netdev_priv(dev); | ||
1233 | *((unsigned long *) mdev_priv) = (unsigned long) priv; | ||
1234 | |||
1235 | priv->netdev = dev; | ||
1236 | mwifiex_init_priv_params(priv, dev); | ||
1237 | |||
1238 | SET_NETDEV_DEV(dev, adapter->dev); | ||
1239 | |||
1240 | /* Register network device */ | ||
1241 | if (register_netdevice(dev)) { | ||
1242 | wiphy_err(wiphy, "cannot register virtual network device\n"); | ||
1243 | goto error; | ||
1244 | } | ||
1245 | |||
1246 | sema_init(&priv->async_sem, 1); | ||
1247 | priv->scan_pending_on_block = false; | ||
1248 | |||
1249 | dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); | ||
1250 | |||
1251 | #ifdef CONFIG_DEBUG_FS | ||
1252 | mwifiex_dev_debugfs_init(priv); | ||
1253 | #endif | ||
1254 | return dev; | ||
1255 | error: | ||
1256 | if (dev && (dev->reg_state == NETREG_UNREGISTERED)) | ||
1257 | free_netdev(dev); | ||
1258 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | ||
1259 | |||
1260 | return NULL; | ||
1261 | } | ||
1262 | EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); | ||
1263 | |||
1264 | /* | ||
1265 | * del_virtual_intf: remove the virtual interface determined by dev | ||
1266 | */ | ||
1267 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) | ||
1268 | { | ||
1269 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | ||
1270 | |||
1271 | if (!priv || !dev) | ||
1272 | return 0; | ||
1273 | |||
1274 | #ifdef CONFIG_DEBUG_FS | ||
1275 | mwifiex_dev_debugfs_remove(priv); | ||
1276 | #endif | ||
1277 | |||
1278 | if (!netif_queue_stopped(priv->netdev)) | ||
1279 | netif_stop_queue(priv->netdev); | ||
1280 | |||
1281 | if (netif_carrier_ok(priv->netdev)) | ||
1282 | netif_carrier_off(priv->netdev); | ||
1283 | |||
1284 | if (dev->reg_state == NETREG_REGISTERED) | ||
1285 | unregister_netdevice(dev); | ||
1286 | |||
1287 | if (dev->reg_state == NETREG_UNREGISTERED) | ||
1288 | free_netdev(dev); | ||
1289 | |||
1290 | /* Clear the priv in adapter */ | ||
1291 | priv->netdev = NULL; | ||
1292 | |||
1293 | priv->media_connected = false; | ||
1294 | |||
1295 | cancel_work_sync(&priv->cfg_workqueue); | ||
1296 | flush_workqueue(priv->workqueue); | ||
1297 | destroy_workqueue(priv->workqueue); | ||
1298 | |||
1299 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | ||
1300 | |||
1301 | return 0; | ||
1302 | } | ||
1303 | EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); | ||
1304 | |||
1151 | /* station cfg80211 operations */ | 1305 | /* station cfg80211 operations */ |
1152 | static struct cfg80211_ops mwifiex_cfg80211_ops = { | 1306 | static struct cfg80211_ops mwifiex_cfg80211_ops = { |
1307 | .add_virtual_intf = mwifiex_add_virtual_intf, | ||
1308 | .del_virtual_intf = mwifiex_del_virtual_intf, | ||
1153 | .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf, | 1309 | .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf, |
1154 | .scan = mwifiex_cfg80211_scan, | 1310 | .scan = mwifiex_cfg80211_scan, |
1155 | .connect = mwifiex_cfg80211_connect, | 1311 | .connect = mwifiex_cfg80211_connect, |
@@ -1174,8 +1330,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
1174 | * default parameters and handler function pointers, and finally | 1330 | * default parameters and handler function pointers, and finally |
1175 | * registers the device. | 1331 | * registers the device. |
1176 | */ | 1332 | */ |
1177 | int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, | 1333 | int mwifiex_register_cfg80211(struct mwifiex_private *priv) |
1178 | struct mwifiex_private *priv) | ||
1179 | { | 1334 | { |
1180 | int ret; | 1335 | int ret; |
1181 | void *wdev_priv; | 1336 | void *wdev_priv; |
@@ -1215,7 +1370,7 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, | |||
1215 | wdev->wiphy->cipher_suites = mwifiex_cipher_suites; | 1370 | wdev->wiphy->cipher_suites = mwifiex_cipher_suites; |
1216 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); | 1371 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); |
1217 | 1372 | ||
1218 | memcpy(wdev->wiphy->perm_addr, mac, 6); | 1373 | memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); |
1219 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 1374 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
1220 | 1375 | ||
1221 | /* We are using custom domains */ | 1376 | /* We are using custom domains */ |
@@ -1245,17 +1400,8 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, | |||
1245 | "info: successfully registered wiphy device\n"); | 1400 | "info: successfully registered wiphy device\n"); |
1246 | } | 1401 | } |
1247 | 1402 | ||
1248 | dev_net_set(dev, wiphy_net(wdev->wiphy)); | ||
1249 | dev->ieee80211_ptr = wdev; | ||
1250 | memcpy(dev->dev_addr, wdev->wiphy->perm_addr, 6); | ||
1251 | memcpy(dev->perm_addr, wdev->wiphy->perm_addr, 6); | ||
1252 | SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); | ||
1253 | priv->wdev = wdev; | 1403 | priv->wdev = wdev; |
1254 | 1404 | ||
1255 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | ||
1256 | dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; | ||
1257 | dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; | ||
1258 | |||
1259 | return ret; | 1405 | return ret; |
1260 | } | 1406 | } |
1261 | 1407 | ||
diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h index c4db8f36aa16..8d010f2500c5 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.h +++ b/drivers/net/wireless/mwifiex/cfg80211.h | |||
@@ -24,8 +24,7 @@ | |||
24 | 24 | ||
25 | #include "main.h" | 25 | #include "main.h" |
26 | 26 | ||
27 | int mwifiex_register_cfg80211(struct net_device *, u8 *, | 27 | int mwifiex_register_cfg80211(struct mwifiex_private *); |
28 | struct mwifiex_private *); | ||
29 | 28 | ||
30 | void mwifiex_cfg80211_results(struct work_struct *work); | 29 | void mwifiex_cfg80211_results(struct work_struct *work); |
31 | #endif | 30 | #endif |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 94ddc9038cb3..6ca62c809cb9 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -114,14 +114,6 @@ struct mwifiex_txinfo { | |||
114 | u8 bss_index; | 114 | u8 bss_index; |
115 | }; | 115 | }; |
116 | 116 | ||
117 | struct mwifiex_bss_attr { | ||
118 | u8 bss_type; | ||
119 | u8 frame_type; | ||
120 | u8 active; | ||
121 | u8 bss_priority; | ||
122 | u8 bss_num; | ||
123 | }; | ||
124 | |||
125 | enum mwifiex_wmm_ac_e { | 117 | enum mwifiex_wmm_ac_e { |
126 | WMM_AC_BK, | 118 | WMM_AC_BK, |
127 | WMM_AC_BE, | 119 | WMM_AC_BE, |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 26e685a31bc0..e1076b46401e 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -76,7 +76,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) | |||
76 | memset(priv->curr_addr, 0xff, ETH_ALEN); | 76 | memset(priv->curr_addr, 0xff, ETH_ALEN); |
77 | 77 | ||
78 | priv->pkt_tx_ctrl = 0; | 78 | priv->pkt_tx_ctrl = 0; |
79 | priv->bss_mode = NL80211_IFTYPE_STATION; | 79 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
80 | priv->data_rate = 0; /* Initially indicate the rate as auto */ | 80 | priv->data_rate = 0; /* Initially indicate the rate as auto */ |
81 | priv->is_data_rate_auto = true; | 81 | priv->is_data_rate_auto = true; |
82 | priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; | 82 | priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 48b4d95219fb..4c7491ec3f2b 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -26,21 +26,6 @@ | |||
26 | 26 | ||
27 | const char driver_version[] = "mwifiex " VERSION " (%s) "; | 27 | const char driver_version[] = "mwifiex " VERSION " (%s) "; |
28 | 28 | ||
29 | static struct mwifiex_bss_attr mwifiex_bss_sta[] = { | ||
30 | {MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0}, | ||
31 | }; | ||
32 | |||
33 | static int drv_mode = DRV_MODE_STA; | ||
34 | |||
35 | /* Supported drv_mode table */ | ||
36 | static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { | ||
37 | { | ||
38 | .drv_mode = DRV_MODE_STA, | ||
39 | .intf_num = ARRAY_SIZE(mwifiex_bss_sta), | ||
40 | .bss_attr = mwifiex_bss_sta, | ||
41 | }, | ||
42 | }; | ||
43 | |||
44 | /* | 29 | /* |
45 | * This function registers the device and performs all the necessary | 30 | * This function registers the device and performs all the necessary |
46 | * initializations. | 31 | * initializations. |
@@ -57,7 +42,6 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { | |||
57 | * proper cleanup before exiting. | 42 | * proper cleanup before exiting. |
58 | */ | 43 | */ |
59 | static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, | 44 | static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, |
60 | struct mwifiex_drv_mode *drv_mode_ptr, | ||
61 | void **padapter) | 45 | void **padapter) |
62 | { | 46 | { |
63 | struct mwifiex_adapter *adapter; | 47 | struct mwifiex_adapter *adapter; |
@@ -78,44 +62,20 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, | |||
78 | goto error; | 62 | goto error; |
79 | 63 | ||
80 | adapter->priv_num = 0; | 64 | adapter->priv_num = 0; |
81 | for (i = 0; i < drv_mode_ptr->intf_num; i++) { | ||
82 | adapter->priv[i] = NULL; | ||
83 | |||
84 | if (!drv_mode_ptr->bss_attr[i].active) | ||
85 | continue; | ||
86 | |||
87 | /* Allocate memory for private structure */ | ||
88 | adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private), | ||
89 | GFP_KERNEL); | ||
90 | if (!adapter->priv[i]) { | ||
91 | dev_err(adapter->dev, "%s: failed to alloc priv[%d]\n", | ||
92 | __func__, i); | ||
93 | goto error; | ||
94 | } | ||
95 | 65 | ||
96 | adapter->priv_num++; | 66 | /* Allocate memory for private structure */ |
97 | adapter->priv[i]->adapter = adapter; | 67 | adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private), |
98 | /* Save bss_type, frame_type & bss_priority */ | 68 | GFP_KERNEL); |
99 | adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type; | 69 | if (!adapter->priv[0]) { |
100 | adapter->priv[i]->frame_type = | 70 | dev_err(adapter->dev, "%s: failed to alloc priv[0]\n", |
101 | drv_mode_ptr->bss_attr[i].frame_type; | 71 | __func__); |
102 | adapter->priv[i]->bss_priority = | 72 | goto error; |
103 | drv_mode_ptr->bss_attr[i].bss_priority; | ||
104 | |||
105 | if (drv_mode_ptr->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA) | ||
106 | adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA; | ||
107 | else if (drv_mode_ptr->bss_attr[i].bss_type == | ||
108 | MWIFIEX_BSS_TYPE_UAP) | ||
109 | adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP; | ||
110 | |||
111 | /* Save bss_index & bss_num */ | ||
112 | adapter->priv[i]->bss_index = i; | ||
113 | adapter->priv[i]->bss_num = drv_mode_ptr->bss_attr[i].bss_num; | ||
114 | } | 73 | } |
115 | adapter->drv_mode = drv_mode_ptr; | ||
116 | 74 | ||
117 | if (mwifiex_init_lock_list(adapter)) | 75 | adapter->priv_num++; |
118 | goto error; | 76 | |
77 | adapter->priv[0]->adapter = adapter; | ||
78 | mwifiex_init_lock_list(adapter); | ||
119 | 79 | ||
120 | init_timer(&adapter->cmd_timer); | 80 | init_timer(&adapter->cmd_timer); |
121 | adapter->cmd_timer.function = mwifiex_cmd_timeout_func; | 81 | adapter->cmd_timer.function = mwifiex_cmd_timeout_func; |
@@ -126,9 +86,9 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, | |||
126 | error: | 86 | error: |
127 | dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n"); | 87 | dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n"); |
128 | 88 | ||
129 | mwifiex_free_lock_list(adapter); | 89 | for (i = 0; i < adapter->priv_num; i++) |
130 | for (i = 0; i < drv_mode_ptr->intf_num; i++) | ||
131 | kfree(adapter->priv[i]); | 90 | kfree(adapter->priv[i]); |
91 | |||
132 | kfree(adapter); | 92 | kfree(adapter); |
133 | 93 | ||
134 | return -1; | 94 | return -1; |
@@ -316,38 +276,6 @@ exit_main_proc: | |||
316 | } | 276 | } |
317 | 277 | ||
318 | /* | 278 | /* |
319 | * This function initializes the software. | ||
320 | * | ||
321 | * The main work includes allocating and initializing the adapter structure | ||
322 | * and initializing the private structures. | ||
323 | */ | ||
324 | static int | ||
325 | mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **padapter) | ||
326 | { | ||
327 | int i; | ||
328 | struct mwifiex_drv_mode *drv_mode_ptr; | ||
329 | |||
330 | /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */ | ||
331 | drv_mode_ptr = NULL; | ||
332 | for (i = 0; i < ARRAY_SIZE(mwifiex_drv_mode_tbl); i++) { | ||
333 | if (mwifiex_drv_mode_tbl[i].drv_mode == drv_mode) { | ||
334 | drv_mode_ptr = &mwifiex_drv_mode_tbl[i]; | ||
335 | break; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | if (!drv_mode_ptr) { | ||
340 | pr_err("invalid drv_mode=%d\n", drv_mode); | ||
341 | return -1; | ||
342 | } | ||
343 | |||
344 | if (mwifiex_register(card, if_ops, drv_mode_ptr, padapter)) | ||
345 | return -1; | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * This function frees the adapter structure. | 279 | * This function frees the adapter structure. |
352 | * | 280 | * |
353 | * Additionally, this closes the netlink socket, frees the timers | 281 | * Additionally, this closes the netlink socket, frees the timers |
@@ -649,8 +577,8 @@ static const struct net_device_ops mwifiex_netdev_ops = { | |||
649 | * | 577 | * |
650 | * In addition, the CFG80211 work queue is also created. | 578 | * In addition, the CFG80211 work queue is also created. |
651 | */ | 579 | */ |
652 | static void | 580 | void mwifiex_init_priv_params(struct mwifiex_private *priv, |
653 | mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) | 581 | struct net_device *dev) |
654 | { | 582 | { |
655 | dev->netdev_ops = &mwifiex_netdev_ops; | 583 | dev->netdev_ops = &mwifiex_netdev_ops; |
656 | /* Initialize private structure */ | 584 | /* Initialize private structure */ |
@@ -664,118 +592,6 @@ mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) | |||
664 | } | 592 | } |
665 | 593 | ||
666 | /* | 594 | /* |
667 | * This function adds a new logical interface. | ||
668 | * | ||
669 | * It allocates, initializes and registers the interface by performing | ||
670 | * the following opearations - | ||
671 | * - Allocate a new net device structure | ||
672 | * - Assign device name | ||
673 | * - Register the new device with CFG80211 subsystem | ||
674 | * - Initialize semaphore and private structure | ||
675 | * - Register the new device with kernel | ||
676 | * - Create the complete debug FS structure if configured | ||
677 | */ | ||
678 | static struct mwifiex_private *mwifiex_add_interface( | ||
679 | struct mwifiex_adapter *adapter, | ||
680 | u8 bss_index, u8 bss_type) | ||
681 | { | ||
682 | struct net_device *dev; | ||
683 | struct mwifiex_private *priv; | ||
684 | void *mdev_priv; | ||
685 | |||
686 | dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d", | ||
687 | ether_setup, 1); | ||
688 | if (!dev) { | ||
689 | dev_err(adapter->dev, "no memory available for netdevice\n"); | ||
690 | goto error; | ||
691 | } | ||
692 | |||
693 | if (mwifiex_register_cfg80211(dev, adapter->priv[bss_index]->curr_addr, | ||
694 | adapter->priv[bss_index]) != 0) { | ||
695 | dev_err(adapter->dev, "cannot register netdevice with cfg80211\n"); | ||
696 | goto error; | ||
697 | } | ||
698 | /* Save the priv pointer in netdev */ | ||
699 | priv = adapter->priv[bss_index]; | ||
700 | mdev_priv = netdev_priv(dev); | ||
701 | *((unsigned long *) mdev_priv) = (unsigned long) priv; | ||
702 | |||
703 | priv->netdev = dev; | ||
704 | |||
705 | sema_init(&priv->async_sem, 1); | ||
706 | priv->scan_pending_on_block = false; | ||
707 | |||
708 | mwifiex_init_priv_params(priv, dev); | ||
709 | |||
710 | SET_NETDEV_DEV(dev, adapter->dev); | ||
711 | |||
712 | /* Register network device */ | ||
713 | if (register_netdev(dev)) { | ||
714 | dev_err(adapter->dev, "cannot register virtual network device\n"); | ||
715 | goto error; | ||
716 | } | ||
717 | |||
718 | dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); | ||
719 | #ifdef CONFIG_DEBUG_FS | ||
720 | mwifiex_dev_debugfs_init(priv); | ||
721 | #endif | ||
722 | return priv; | ||
723 | error: | ||
724 | if (dev) | ||
725 | free_netdev(dev); | ||
726 | return NULL; | ||
727 | } | ||
728 | |||
729 | /* | ||
730 | * This function removes a logical interface. | ||
731 | * | ||
732 | * It deregisters, resets and frees the interface by performing | ||
733 | * the following operations - | ||
734 | * - Disconnect the device if connected, send wireless event to | ||
735 | * notify applications. | ||
736 | * - Remove the debug FS structure if configured | ||
737 | * - Unregister the device from kernel | ||
738 | * - Free the net device structure | ||
739 | * - Cancel all works and destroy work queue | ||
740 | * - Unregister and free the wireless device from CFG80211 subsystem | ||
741 | */ | ||
742 | static void | ||
743 | mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) | ||
744 | { | ||
745 | struct net_device *dev; | ||
746 | struct mwifiex_private *priv = adapter->priv[bss_index]; | ||
747 | |||
748 | if (!priv) | ||
749 | return; | ||
750 | dev = priv->netdev; | ||
751 | |||
752 | if (priv->media_connected) | ||
753 | priv->media_connected = false; | ||
754 | |||
755 | #ifdef CONFIG_DEBUG_FS | ||
756 | mwifiex_dev_debugfs_remove(priv); | ||
757 | #endif | ||
758 | /* Last reference is our one */ | ||
759 | dev_dbg(adapter->dev, "info: %s: refcnt = %d\n", | ||
760 | dev->name, netdev_refcnt_read(dev)); | ||
761 | |||
762 | if (dev->reg_state == NETREG_REGISTERED) | ||
763 | unregister_netdev(dev); | ||
764 | |||
765 | /* Clear the priv in adapter */ | ||
766 | priv->netdev = NULL; | ||
767 | if (dev) | ||
768 | free_netdev(dev); | ||
769 | |||
770 | cancel_work_sync(&priv->cfg_workqueue); | ||
771 | flush_workqueue(priv->workqueue); | ||
772 | destroy_workqueue(priv->workqueue); | ||
773 | wiphy_unregister(priv->wdev->wiphy); | ||
774 | wiphy_free(priv->wdev->wiphy); | ||
775 | kfree(priv->wdev); | ||
776 | } | ||
777 | |||
778 | /* | ||
779 | * This function check if command is pending. | 595 | * This function check if command is pending. |
780 | */ | 596 | */ |
781 | int is_command_pending(struct mwifiex_adapter *adapter) | 597 | int is_command_pending(struct mwifiex_adapter *adapter) |
@@ -847,14 +663,14 @@ int | |||
847 | mwifiex_add_card(void *card, struct semaphore *sem, | 663 | mwifiex_add_card(void *card, struct semaphore *sem, |
848 | struct mwifiex_if_ops *if_ops) | 664 | struct mwifiex_if_ops *if_ops) |
849 | { | 665 | { |
850 | int i; | ||
851 | struct mwifiex_adapter *adapter; | 666 | struct mwifiex_adapter *adapter; |
852 | char fmt[64]; | 667 | char fmt[64]; |
668 | struct mwifiex_private *priv; | ||
853 | 669 | ||
854 | if (down_interruptible(sem)) | 670 | if (down_interruptible(sem)) |
855 | goto exit_sem_err; | 671 | goto exit_sem_err; |
856 | 672 | ||
857 | if (mwifiex_init_sw(card, if_ops, (void **)&adapter)) { | 673 | if (mwifiex_register(card, if_ops, (void **)&adapter)) { |
858 | pr_err("%s: software init failed\n", __func__); | 674 | pr_err("%s: software init failed\n", __func__); |
859 | goto err_init_sw; | 675 | goto err_init_sw; |
860 | } | 676 | } |
@@ -888,14 +704,26 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
888 | goto err_init_fw; | 704 | goto err_init_fw; |
889 | } | 705 | } |
890 | 706 | ||
891 | /* Add interfaces */ | 707 | priv = adapter->priv[0]; |
892 | for (i = 0; i < adapter->drv_mode->intf_num; i++) { | 708 | |
893 | if (!mwifiex_add_interface(adapter, i, | 709 | if (mwifiex_register_cfg80211(priv) != 0) { |
894 | adapter->drv_mode->bss_attr[i].bss_type)) { | 710 | dev_err(adapter->dev, "cannot register netdevice" |
895 | goto err_add_intf; | 711 | " with cfg80211\n"); |
896 | } | 712 | goto err_init_fw; |
713 | } | ||
714 | |||
715 | rtnl_lock(); | ||
716 | /* Create station interface by default */ | ||
717 | if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d", | ||
718 | NL80211_IFTYPE_STATION, NULL, NULL)) { | ||
719 | rtnl_unlock(); | ||
720 | dev_err(adapter->dev, "cannot create default station" | ||
721 | " interface\n"); | ||
722 | goto err_add_intf; | ||
897 | } | 723 | } |
898 | 724 | ||
725 | rtnl_unlock(); | ||
726 | |||
899 | up(sem); | 727 | up(sem); |
900 | 728 | ||
901 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); | 729 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); |
@@ -904,8 +732,9 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
904 | return 0; | 732 | return 0; |
905 | 733 | ||
906 | err_add_intf: | 734 | err_add_intf: |
907 | for (i = 0; i < adapter->priv_num; i++) | 735 | rtnl_lock(); |
908 | mwifiex_remove_interface(adapter, i); | 736 | mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); |
737 | rtnl_unlock(); | ||
909 | err_init_fw: | 738 | err_init_fw: |
910 | pr_debug("info: %s: unregister device\n", __func__); | 739 | pr_debug("info: %s: unregister device\n", __func__); |
911 | adapter->if_ops.unregister_dev(adapter); | 740 | adapter->if_ops.unregister_dev(adapter); |
@@ -960,7 +789,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) | |||
960 | /* Stop data */ | 789 | /* Stop data */ |
961 | for (i = 0; i < adapter->priv_num; i++) { | 790 | for (i = 0; i < adapter->priv_num; i++) { |
962 | priv = adapter->priv[i]; | 791 | priv = adapter->priv[i]; |
963 | if (priv) { | 792 | if (priv && priv->netdev) { |
964 | if (!netif_queue_stopped(priv->netdev)) | 793 | if (!netif_queue_stopped(priv->netdev)) |
965 | netif_stop_queue(priv->netdev); | 794 | netif_stop_queue(priv->netdev); |
966 | if (netif_carrier_ok(priv->netdev)) | 795 | if (netif_carrier_ok(priv->netdev)) |
@@ -985,9 +814,20 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) | |||
985 | atomic_read(&adapter->cmd_pending)); | 814 | atomic_read(&adapter->cmd_pending)); |
986 | } | 815 | } |
987 | 816 | ||
988 | /* Remove interface */ | 817 | for (i = 0; i < adapter->priv_num; i++) { |
989 | for (i = 0; i < adapter->priv_num; i++) | 818 | priv = adapter->priv[i]; |
990 | mwifiex_remove_interface(adapter, i); | 819 | |
820 | if (!priv) | ||
821 | continue; | ||
822 | |||
823 | rtnl_lock(); | ||
824 | mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); | ||
825 | rtnl_unlock(); | ||
826 | } | ||
827 | |||
828 | wiphy_unregister(priv->wdev->wiphy); | ||
829 | wiphy_free(priv->wdev->wiphy); | ||
830 | kfree(priv->wdev); | ||
991 | 831 | ||
992 | mwifiex_terminate_workqueue(adapter); | 832 | mwifiex_terminate_workqueue(adapter); |
993 | 833 | ||
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 1e801328a558..907ab746dc4b 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -45,15 +45,6 @@ enum { | |||
45 | MWIFIEX_SYNC_CMD | 45 | MWIFIEX_SYNC_CMD |
46 | }; | 46 | }; |
47 | 47 | ||
48 | #define DRV_MODE_STA 0x1 | ||
49 | |||
50 | struct mwifiex_drv_mode { | ||
51 | u16 drv_mode; | ||
52 | u16 intf_num; | ||
53 | struct mwifiex_bss_attr *bss_attr; | ||
54 | }; | ||
55 | |||
56 | |||
57 | #define MWIFIEX_MAX_AP 64 | 48 | #define MWIFIEX_MAX_AP 64 |
58 | 49 | ||
59 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) | 50 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) |
@@ -182,7 +173,6 @@ struct mwifiex_ra_list_tbl { | |||
182 | struct sk_buff_head skb_head; | 173 | struct sk_buff_head skb_head; |
183 | u8 ra[ETH_ALEN]; | 174 | u8 ra[ETH_ALEN]; |
184 | u32 total_pkts_size; | 175 | u32 total_pkts_size; |
185 | u32 total_pkts; | ||
186 | u32 is_11n_enabled; | 176 | u32 is_11n_enabled; |
187 | }; | 177 | }; |
188 | 178 | ||
@@ -546,7 +536,6 @@ struct mwifiex_if_ops { | |||
546 | struct mwifiex_adapter { | 536 | struct mwifiex_adapter { |
547 | struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; | 537 | struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; |
548 | u8 priv_num; | 538 | u8 priv_num; |
549 | struct mwifiex_drv_mode *drv_mode; | ||
550 | const struct firmware *firmware; | 539 | const struct firmware *firmware; |
551 | char fw_name[32]; | 540 | char fw_name[32]; |
552 | struct device *dev; | 541 | struct device *dev; |
@@ -792,6 +781,8 @@ int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, | |||
792 | int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | 781 | int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, |
793 | struct host_cmd_ds_command *resp); | 782 | struct host_cmd_ds_command *resp); |
794 | int is_command_pending(struct mwifiex_adapter *adapter); | 783 | int is_command_pending(struct mwifiex_adapter *adapter); |
784 | void mwifiex_init_priv_params(struct mwifiex_private *priv, | ||
785 | struct net_device *dev); | ||
795 | 786 | ||
796 | /* | 787 | /* |
797 | * This function checks if the queuing is RA based or not. | 788 | * This function checks if the queuing is RA based or not. |
@@ -966,6 +957,12 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | |||
966 | int mwifiex_check_network_compatibility(struct mwifiex_private *priv, | 957 | int mwifiex_check_network_compatibility(struct mwifiex_private *priv, |
967 | struct mwifiex_bssdescriptor *bss_desc); | 958 | struct mwifiex_bssdescriptor *bss_desc); |
968 | 959 | ||
960 | struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | ||
961 | char *name, enum nl80211_iftype type, | ||
962 | u32 *flags, struct vif_params *params); | ||
963 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); | ||
964 | |||
965 | |||
969 | #ifdef CONFIG_DEBUG_FS | 966 | #ifdef CONFIG_DEBUG_FS |
970 | void mwifiex_debugfs_init(void); | 967 | void mwifiex_debugfs_init(void); |
971 | void mwifiex_debugfs_remove(void); | 968 | void mwifiex_debugfs_remove(void); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index a9dfeb1b4ace..520800b618e7 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -720,51 +720,9 @@ done: | |||
720 | static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, | 720 | static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, |
721 | struct mwifiex_rate_cfg *rate_cfg) | 721 | struct mwifiex_rate_cfg *rate_cfg) |
722 | { | 722 | { |
723 | struct mwifiex_adapter *adapter = priv->adapter; | ||
724 | |||
725 | rate_cfg->is_rate_auto = priv->is_data_rate_auto; | 723 | rate_cfg->is_rate_auto = priv->is_data_rate_auto; |
726 | if (!priv->media_connected) { | 724 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, |
727 | switch (adapter->config_bands) { | 725 | HostCmd_ACT_GEN_GET, 0, NULL); |
728 | case BAND_B: | ||
729 | /* Return the lowest supported rate for B band */ | ||
730 | rate_cfg->rate = supported_rates_b[0] & 0x7f; | ||
731 | break; | ||
732 | case BAND_G: | ||
733 | case BAND_G | BAND_GN: | ||
734 | /* Return the lowest supported rate for G band */ | ||
735 | rate_cfg->rate = supported_rates_g[0] & 0x7f; | ||
736 | break; | ||
737 | case BAND_B | BAND_G: | ||
738 | case BAND_A | BAND_B | BAND_G: | ||
739 | case BAND_A | BAND_B: | ||
740 | case BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN: | ||
741 | case BAND_B | BAND_G | BAND_GN: | ||
742 | /* Return the lowest supported rate for BG band */ | ||
743 | rate_cfg->rate = supported_rates_bg[0] & 0x7f; | ||
744 | break; | ||
745 | case BAND_A: | ||
746 | case BAND_A | BAND_G: | ||
747 | case BAND_A | BAND_G | BAND_AN | BAND_GN: | ||
748 | case BAND_A | BAND_AN: | ||
749 | /* Return the lowest supported rate for A band */ | ||
750 | rate_cfg->rate = supported_rates_a[0] & 0x7f; | ||
751 | break; | ||
752 | case BAND_GN: | ||
753 | /* Return the lowest supported rate for N band */ | ||
754 | rate_cfg->rate = supported_rates_n[0] & 0x7f; | ||
755 | break; | ||
756 | default: | ||
757 | dev_warn(adapter->dev, "invalid band %#x\n", | ||
758 | adapter->config_bands); | ||
759 | break; | ||
760 | } | ||
761 | } else { | ||
762 | return mwifiex_send_cmd_sync(priv, | ||
763 | HostCmd_CMD_802_11_TX_RATE_QUERY, | ||
764 | HostCmd_ACT_GEN_GET, 0, NULL); | ||
765 | } | ||
766 | |||
767 | return 0; | ||
768 | } | 726 | } |
769 | 727 | ||
770 | /* | 728 | /* |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 69e260b41711..eda24474c1fc 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -121,7 +121,6 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) | |||
121 | memcpy(ra_list->ra, ra, ETH_ALEN); | 121 | memcpy(ra_list->ra, ra, ETH_ALEN); |
122 | 122 | ||
123 | ra_list->total_pkts_size = 0; | 123 | ra_list->total_pkts_size = 0; |
124 | ra_list->total_pkts = 0; | ||
125 | 124 | ||
126 | dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list); | 125 | dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list); |
127 | 126 | ||
@@ -648,7 +647,6 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, | |||
648 | skb_queue_tail(&ra_list->skb_head, skb); | 647 | skb_queue_tail(&ra_list->skb_head, skb); |
649 | 648 | ||
650 | ra_list->total_pkts_size += skb->len; | 649 | ra_list->total_pkts_size += skb->len; |
651 | ra_list->total_pkts++; | ||
652 | 650 | ||
653 | atomic_inc(&priv->wmm.tx_pkts_queued); | 651 | atomic_inc(&priv->wmm.tx_pkts_queued); |
654 | 652 | ||
@@ -975,6 +973,28 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
975 | } | 973 | } |
976 | 974 | ||
977 | /* | 975 | /* |
976 | * This function checks if 11n aggregation is possible. | ||
977 | */ | ||
978 | static int | ||
979 | mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv, | ||
980 | struct mwifiex_ra_list_tbl *ptr, | ||
981 | int max_buf_size) | ||
982 | { | ||
983 | int count = 0, total_size = 0; | ||
984 | struct sk_buff *skb, *tmp; | ||
985 | |||
986 | skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { | ||
987 | total_size += skb->len; | ||
988 | if (total_size >= max_buf_size) | ||
989 | break; | ||
990 | if (++count >= MIN_NUM_AMSDU) | ||
991 | return true; | ||
992 | } | ||
993 | |||
994 | return false; | ||
995 | } | ||
996 | |||
997 | /* | ||
978 | * This function sends a single packet to firmware for transmission. | 998 | * This function sends a single packet to firmware for transmission. |
979 | */ | 999 | */ |
980 | static void | 1000 | static void |
@@ -1001,7 +1021,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, | |||
1001 | dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb); | 1021 | dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb); |
1002 | 1022 | ||
1003 | ptr->total_pkts_size -= skb->len; | 1023 | ptr->total_pkts_size -= skb->len; |
1004 | ptr->total_pkts--; | ||
1005 | 1024 | ||
1006 | if (!skb_queue_empty(&ptr->skb_head)) | 1025 | if (!skb_queue_empty(&ptr->skb_head)) |
1007 | skb_next = skb_peek(&ptr->skb_head); | 1026 | skb_next = skb_peek(&ptr->skb_head); |
@@ -1027,7 +1046,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, | |||
1027 | skb_queue_tail(&ptr->skb_head, skb); | 1046 | skb_queue_tail(&ptr->skb_head, skb); |
1028 | 1047 | ||
1029 | ptr->total_pkts_size += skb->len; | 1048 | ptr->total_pkts_size += skb->len; |
1030 | ptr->total_pkts++; | ||
1031 | tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; | 1049 | tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; |
1032 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 1050 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
1033 | ra_list_flags); | 1051 | ra_list_flags); |
@@ -1213,11 +1231,9 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) | |||
1213 | mwifiex_send_delba(priv, tid_del, ra, 1); | 1231 | mwifiex_send_delba(priv, tid_del, ra, 1); |
1214 | } | 1232 | } |
1215 | } | 1233 | } |
1216 | /* Minimum number of AMSDU */ | ||
1217 | #define MIN_NUM_AMSDU 2 | ||
1218 | |||
1219 | if (mwifiex_is_amsdu_allowed(priv, tid) && | 1234 | if (mwifiex_is_amsdu_allowed(priv, tid) && |
1220 | (ptr->total_pkts >= MIN_NUM_AMSDU)) | 1235 | mwifiex_is_11n_aggragation_possible(priv, ptr, |
1236 | adapter->tx_buf_size)) | ||
1221 | mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, | 1237 | mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, |
1222 | ptr_index, flags); | 1238 | ptr_index, flags); |
1223 | /* ra_list_spinlock has been freed in | 1239 | /* ra_list_spinlock has been freed in |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ea1395aafa39..995695c28d5c 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -4915,7 +4915,8 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw, | |||
4915 | return ret; | 4915 | return ret; |
4916 | } | 4916 | } |
4917 | 4917 | ||
4918 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 4918 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, |
4919 | struct ieee80211_vif *vif, u16 queue, | ||
4919 | const struct ieee80211_tx_queue_params *params) | 4920 | const struct ieee80211_tx_queue_params *params) |
4920 | { | 4921 | { |
4921 | struct mwl8k_priv *priv = hw->priv; | 4922 | struct mwl8k_priv *priv = hw->priv; |
@@ -5462,7 +5463,7 @@ static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image) | |||
5462 | goto fail; | 5463 | goto fail; |
5463 | 5464 | ||
5464 | for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) { | 5465 | for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) { |
5465 | rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]); | 5466 | rc = mwl8k_conf_tx(hw, NULL, i, &priv->wmm_params[i]); |
5466 | if (rc) | 5467 | if (rc) |
5467 | goto fail; | 5468 | goto fail; |
5468 | } | 5469 | } |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 726a9343f514..ad9ae04d07aa 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -404,7 +404,8 @@ static void p54_configure_filter(struct ieee80211_hw *dev, | |||
404 | p54_set_groupfilter(priv); | 404 | p54_set_groupfilter(priv); |
405 | } | 405 | } |
406 | 406 | ||
407 | static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue, | 407 | static int p54_conf_tx(struct ieee80211_hw *dev, |
408 | struct ieee80211_vif *vif, u16 queue, | ||
408 | const struct ieee80211_tx_queue_params *params) | 409 | const struct ieee80211_tx_queue_params *params) |
409 | { | 410 | { |
410 | struct p54_common *priv = dev->priv; | 411 | struct p54_common *priv = dev->priv; |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 2b97a89e7ff8..f485784a60ae 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -689,7 +689,7 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, | |||
689 | if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) | 689 | if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) |
690 | *flags |= P54_HDR_FLAG_DATA_OUT_SEQNR; | 690 | *flags |= P54_HDR_FLAG_DATA_OUT_SEQNR; |
691 | 691 | ||
692 | if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE) | 692 | if (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE) |
693 | *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; | 693 | *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; |
694 | 694 | ||
695 | if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) | 695 | if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 7e9272b8f01d..3a6b40239bc1 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1648,7 +1648,8 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1648 | /* | 1648 | /* |
1649 | * IEEE80211 stack callback functions. | 1649 | * IEEE80211 stack callback functions. |
1650 | */ | 1650 | */ |
1651 | static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1651 | static int rt2400pci_conf_tx(struct ieee80211_hw *hw, |
1652 | struct ieee80211_vif *vif, u16 queue, | ||
1652 | const struct ieee80211_tx_queue_params *params) | 1653 | const struct ieee80211_tx_queue_params *params) |
1653 | { | 1654 | { |
1654 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1655 | struct rt2x00_dev *rt2x00dev = hw->priv; |
@@ -1661,7 +1662,7 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1661 | if (queue != 0) | 1662 | if (queue != 0) |
1662 | return -EINVAL; | 1663 | return -EINVAL; |
1663 | 1664 | ||
1664 | if (rt2x00mac_conf_tx(hw, queue, params)) | 1665 | if (rt2x00mac_conf_tx(hw, vif, queue, params)) |
1665 | return -EINVAL; | 1666 | return -EINVAL; |
1666 | 1667 | ||
1667 | /* | 1668 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9688dd0a7ebd..3f183a15186e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -4398,7 +4398,8 @@ int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
4398 | } | 4398 | } |
4399 | EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold); | 4399 | EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold); |
4400 | 4400 | ||
4401 | int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | 4401 | int rt2800_conf_tx(struct ieee80211_hw *hw, |
4402 | struct ieee80211_vif *vif, u16 queue_idx, | ||
4402 | const struct ieee80211_tx_queue_params *params) | 4403 | const struct ieee80211_tx_queue_params *params) |
4403 | { | 4404 | { |
4404 | struct rt2x00_dev *rt2x00dev = hw->priv; | 4405 | struct rt2x00_dev *rt2x00dev = hw->priv; |
@@ -4414,7 +4415,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
4414 | * we are free to update the registers based on the value | 4415 | * we are free to update the registers based on the value |
4415 | * in the queue parameter. | 4416 | * in the queue parameter. |
4416 | */ | 4417 | */ |
4417 | retval = rt2x00mac_conf_tx(hw, queue_idx, params); | 4418 | retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params); |
4418 | if (retval) | 4419 | if (retval) |
4419 | return retval; | 4420 | return retval; |
4420 | 4421 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 6de128e9c612..8c3c281904fe 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -197,7 +197,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev); | |||
197 | void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, | 197 | void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, |
198 | u16 *iv16); | 198 | u16 *iv16); |
199 | int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value); | 199 | int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value); |
200 | int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | 200 | int rt2800_conf_tx(struct ieee80211_hw *hw, |
201 | struct ieee80211_vif *vif, u16 queue_idx, | ||
201 | const struct ieee80211_tx_queue_params *params); | 202 | const struct ieee80211_tx_queue_params *params); |
202 | u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 203 | u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
203 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 204 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index cbf8eb334e96..2ec5c00235e6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -1299,7 +1299,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
1299 | struct ieee80211_vif *vif, | 1299 | struct ieee80211_vif *vif, |
1300 | struct ieee80211_bss_conf *bss_conf, | 1300 | struct ieee80211_bss_conf *bss_conf, |
1301 | u32 changes); | 1301 | u32 changes); |
1302 | int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1302 | int rt2x00mac_conf_tx(struct ieee80211_hw *hw, |
1303 | struct ieee80211_vif *vif, u16 queue, | ||
1303 | const struct ieee80211_tx_queue_params *params); | 1304 | const struct ieee80211_tx_queue_params *params); |
1304 | void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); | 1305 | void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); |
1305 | void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); | 1306 | void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index cef1c878c37e..bf0acff07807 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -713,7 +713,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
713 | } | 713 | } |
714 | EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); | 714 | EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); |
715 | 715 | ||
716 | int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | 716 | int rt2x00mac_conf_tx(struct ieee80211_hw *hw, |
717 | struct ieee80211_vif *vif, u16 queue_idx, | ||
717 | const struct ieee80211_tx_queue_params *params) | 718 | const struct ieee80211_tx_queue_params *params) |
718 | { | 719 | { |
719 | struct rt2x00_dev *rt2x00dev = hw->priv; | 720 | struct rt2x00_dev *rt2x00dev = hw->priv; |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 6b6a8e2dcddc..bf55b4a311e3 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -2883,7 +2883,8 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2883 | /* | 2883 | /* |
2884 | * IEEE80211 stack callback functions. | 2884 | * IEEE80211 stack callback functions. |
2885 | */ | 2885 | */ |
2886 | static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | 2886 | static int rt61pci_conf_tx(struct ieee80211_hw *hw, |
2887 | struct ieee80211_vif *vif, u16 queue_idx, | ||
2887 | const struct ieee80211_tx_queue_params *params) | 2888 | const struct ieee80211_tx_queue_params *params) |
2888 | { | 2889 | { |
2889 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2890 | struct rt2x00_dev *rt2x00dev = hw->priv; |
@@ -2899,7 +2900,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
2899 | * we are free to update the registers based on the value | 2900 | * we are free to update the registers based on the value |
2900 | * in the queue parameter. | 2901 | * in the queue parameter. |
2901 | */ | 2902 | */ |
2902 | retval = rt2x00mac_conf_tx(hw, queue_idx, params); | 2903 | retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params); |
2903 | if (retval) | 2904 | if (retval) |
2904 | return retval; | 2905 | return retval; |
2905 | 2906 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6f51e39f5595..cfb19dbb0a67 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -2222,7 +2222,8 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2222 | /* | 2222 | /* |
2223 | * IEEE80211 stack callback functions. | 2223 | * IEEE80211 stack callback functions. |
2224 | */ | 2224 | */ |
2225 | static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | 2225 | static int rt73usb_conf_tx(struct ieee80211_hw *hw, |
2226 | struct ieee80211_vif *vif, u16 queue_idx, | ||
2226 | const struct ieee80211_tx_queue_params *params) | 2227 | const struct ieee80211_tx_queue_params *params) |
2227 | { | 2228 | { |
2228 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2229 | struct rt2x00_dev *rt2x00dev = hw->priv; |
@@ -2238,7 +2239,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
2238 | * we are free to update the registers based on the value | 2239 | * we are free to update the registers based on the value |
2239 | * in the queue parameter. | 2240 | * in the queue parameter. |
2240 | */ | 2241 | */ |
2241 | retval = rt2x00mac_conf_tx(hw, queue_idx, params); | 2242 | retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params); |
2242 | if (retval) | 2243 | if (retval) |
2243 | return retval; | 2244 | return retval; |
2244 | 2245 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index f5afa155ce91..24873b55b55c 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c | |||
@@ -1241,7 +1241,8 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev, | |||
1241 | rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); | 1241 | rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); |
1242 | } | 1242 | } |
1243 | 1243 | ||
1244 | static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue, | 1244 | static int rtl8187_conf_tx(struct ieee80211_hw *dev, |
1245 | struct ieee80211_vif *vif, u16 queue, | ||
1245 | const struct ieee80211_tx_queue_params *params) | 1246 | const struct ieee80211_tx_queue_params *params) |
1246 | { | 1247 | { |
1247 | struct rtl8187_priv *priv = dev->priv; | 1248 | struct rtl8187_priv *priv = dev->priv; |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 21e40f62a8d7..3f0f056fae9c 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -504,7 +504,8 @@ static int _rtl_get_hal_qnum(u16 queue) | |||
504 | *for mac80211 VO=0, VI=1, BE=2, BK=3 | 504 | *for mac80211 VO=0, VI=1, BE=2, BK=3 |
505 | *for rtl819x BE=0, BK=1, VI=2, VO=3 | 505 | *for rtl819x BE=0, BK=1, VI=2, VO=3 |
506 | */ | 506 | */ |
507 | static int rtl_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | 507 | static int rtl_op_conf_tx(struct ieee80211_hw *hw, |
508 | struct ieee80211_vif *vif, u16 queue, | ||
508 | const struct ieee80211_tx_queue_params *param) | 509 | const struct ieee80211_tx_queue_params *param) |
509 | { | 510 | { |
510 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 511 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 4bf3cf457ef0..b42c2e2b2055 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -191,44 +191,6 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val) | |||
191 | _usb_write_async(to_usb_device(dev), addr, val, 4); | 191 | _usb_write_async(to_usb_device(dev), addr, val, 4); |
192 | } | 192 | } |
193 | 193 | ||
194 | static int _usb_nbytes_read_write(struct usb_device *udev, bool read, u32 addr, | ||
195 | u16 len, u8 *pdata) | ||
196 | { | ||
197 | int status; | ||
198 | u8 request; | ||
199 | u16 wvalue; | ||
200 | u16 index; | ||
201 | |||
202 | request = REALTEK_USB_VENQT_CMD_REQ; | ||
203 | index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ | ||
204 | wvalue = (u16)addr; | ||
205 | if (read) | ||
206 | status = _usbctrl_vendorreq_sync_read(udev, request, wvalue, | ||
207 | index, pdata, len); | ||
208 | else | ||
209 | status = _usbctrl_vendorreq_async_write(udev, request, wvalue, | ||
210 | index, pdata, len); | ||
211 | return status; | ||
212 | } | ||
213 | |||
214 | static int _usb_readN_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len, | ||
215 | u8 *pdata) | ||
216 | { | ||
217 | struct device *dev = rtlpriv->io.dev; | ||
218 | |||
219 | return _usb_nbytes_read_write(to_usb_device(dev), true, addr, len, | ||
220 | pdata); | ||
221 | } | ||
222 | |||
223 | static int _usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, u16 len, | ||
224 | u8 *pdata) | ||
225 | { | ||
226 | struct device *dev = rtlpriv->io.dev; | ||
227 | |||
228 | return _usb_nbytes_read_write(to_usb_device(dev), false, addr, len, | ||
229 | pdata); | ||
230 | } | ||
231 | |||
232 | static void _rtl_usb_io_handler_init(struct device *dev, | 194 | static void _rtl_usb_io_handler_init(struct device *dev, |
233 | struct ieee80211_hw *hw) | 195 | struct ieee80211_hw *hw) |
234 | { | 196 | { |
@@ -239,11 +201,9 @@ static void _rtl_usb_io_handler_init(struct device *dev, | |||
239 | rtlpriv->io.write8_async = _usb_write8_async; | 201 | rtlpriv->io.write8_async = _usb_write8_async; |
240 | rtlpriv->io.write16_async = _usb_write16_async; | 202 | rtlpriv->io.write16_async = _usb_write16_async; |
241 | rtlpriv->io.write32_async = _usb_write32_async; | 203 | rtlpriv->io.write32_async = _usb_write32_async; |
242 | rtlpriv->io.writeN_async = _usb_writeN_async; | ||
243 | rtlpriv->io.read8_sync = _usb_read8_sync; | 204 | rtlpriv->io.read8_sync = _usb_read8_sync; |
244 | rtlpriv->io.read16_sync = _usb_read16_sync; | 205 | rtlpriv->io.read16_sync = _usb_read16_sync; |
245 | rtlpriv->io.read32_sync = _usb_read32_sync; | 206 | rtlpriv->io.read32_sync = _usb_read32_sync; |
246 | rtlpriv->io.readN_sync = _usb_readN_sync; | ||
247 | } | 207 | } |
248 | 208 | ||
249 | static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) | 209 | static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 615f6b4463e6..3126485393d9 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -942,16 +942,12 @@ struct rtl_io { | |||
942 | unsigned long pci_base_addr; /*device I/O address */ | 942 | unsigned long pci_base_addr; /*device I/O address */ |
943 | 943 | ||
944 | void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); | 944 | void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); |
945 | void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val); | 945 | void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, __le16 val); |
946 | void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val); | 946 | void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, __le32 val); |
947 | int (*writeN_async) (struct rtl_priv *rtlpriv, u32 addr, u16 len, | ||
948 | u8 *pdata); | ||
949 | 947 | ||
950 | u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); | 948 | u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); |
951 | u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr); | 949 | u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr); |
952 | u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); | 950 | u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); |
953 | int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len, | ||
954 | u8 *pdata); | ||
955 | 951 | ||
956 | }; | 952 | }; |
957 | 953 | ||
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c index a14a48c99cdc..ba3268ea81fe 100644 --- a/drivers/net/wireless/wl1251/main.c +++ b/drivers/net/wireless/wl1251/main.c | |||
@@ -1158,7 +1158,8 @@ static struct ieee80211_channel wl1251_channels[] = { | |||
1158 | { .hw_value = 13, .center_freq = 2472}, | 1158 | { .hw_value = 13, .center_freq = 2472}, |
1159 | }; | 1159 | }; |
1160 | 1160 | ||
1161 | static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1161 | static int wl1251_op_conf_tx(struct ieee80211_hw *hw, |
1162 | struct ieee80211_vif *vif, u16 queue, | ||
1162 | const struct ieee80211_tx_queue_params *params) | 1163 | const struct ieee80211_tx_queue_params *params) |
1163 | { | 1164 | { |
1164 | enum wl1251_acx_ps_scheme ps_scheme; | 1165 | enum wl1251_acx_ps_scheme ps_scheme; |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 7d409b0f3357..e2d6edd2fcd2 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -3744,7 +3744,8 @@ out: | |||
3744 | mutex_unlock(&wl->mutex); | 3744 | mutex_unlock(&wl->mutex); |
3745 | } | 3745 | } |
3746 | 3746 | ||
3747 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | 3747 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, |
3748 | struct ieee80211_vif *vif, u16 queue, | ||
3748 | const struct ieee80211_tx_queue_params *params) | 3749 | const struct ieee80211_tx_queue_params *params) |
3749 | { | 3750 | { |
3750 | struct wl1271 *wl = hw->priv; | 3751 | struct wl1271 *wl = hw->priv; |
diff --git a/drivers/staging/brcm80211/brcmsmac/mac80211_if.c b/drivers/staging/brcm80211/brcmsmac/mac80211_if.c index 315dd91800b6..6d71cba3a0a5 100644 --- a/drivers/staging/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/staging/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -141,8 +141,9 @@ static void brcms_ops_sta_notify(struct ieee80211_hw *hw, | |||
141 | struct ieee80211_vif *vif, | 141 | struct ieee80211_vif *vif, |
142 | enum sta_notify_cmd cmd, | 142 | enum sta_notify_cmd cmd, |
143 | struct ieee80211_sta *sta); | 143 | struct ieee80211_sta *sta); |
144 | static int brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, | 144 | static int brcms_ops_conf_tx(struct ieee80211_hw *hw, |
145 | const struct ieee80211_tx_queue_params *params); | 145 | struct ieee80211_vif *vif, u16 queue, |
146 | const struct ieee80211_tx_queue_params *params); | ||
146 | static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, | 147 | static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, |
147 | struct ieee80211_vif *vif); | 148 | struct ieee80211_vif *vif); |
148 | static int brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 149 | static int brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
@@ -556,7 +557,7 @@ brcms_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
556 | } | 557 | } |
557 | 558 | ||
558 | static int | 559 | static int |
559 | brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, | 560 | brcms_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, |
560 | const struct ieee80211_tx_queue_params *params) | 561 | const struct ieee80211_tx_queue_params *params) |
561 | { | 562 | { |
562 | struct brcms_info *wl = hw->priv; | 563 | struct brcms_info *wl = hw->priv; |