diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/wmi.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.c | 1126 |
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 | ||
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 | } |