aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath6kl/wmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/wmi.c')
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c1126
1 files changed, 755 insertions, 371 deletions
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
21static int ath6kl_wmi_sync_point(struct wmi *wmi); 24static 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
379int 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
389static 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
408static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) 384static 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
412static 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
441static 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
470static 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
496static 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
524static 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
539static 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
563static 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
436static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size) 607static 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 */
658int 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
481static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len) 681static 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
769static struct country_code_to_enum_rd *
770ath6kl_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
782static struct reg_dmn_pair_mapping *
783ath6kl_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 &regDomainPairs[i];
793 }
794
795 return NULL;
796}
797
798static struct country_code_to_enum_rd *
799ath6kl_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
811static 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
531static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len) 844static 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
585static 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
704static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len) 903static 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
860static 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
1047static 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
952static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len) 1054static 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
1109static 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
2363int 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
2214int ath6kl_wmi_get_stats_cmd(struct wmi *wmi) 2382int 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
2319s32 ath6kl_wmi_get_rate(s8 rate_index) 2487int 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
2327void 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
2333struct 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
2344struct 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
2353void ath6kl_wmi_node_free(struct wmi *wmi, const u8 * mac_addr) 2504s32 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
2364static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, 2512static 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
2552int 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
2574int 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
2403static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len) 2592static 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
2657int 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
2677int 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
2695int 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
2713int 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
2749int 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
2771int 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
2788int 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
2805int 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
2467static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) 2811static 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}