diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 228 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 41 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/htc_mbox.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/init.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/main.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/target.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/txrx.c | 48 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.c | 148 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.h | 58 |
10 files changed, 472 insertions, 112 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index b869a358ce4..fd7dbd4609d 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -53,6 +53,11 @@ | |||
53 | 53 | ||
54 | #define DEFAULT_BG_SCAN_PERIOD 60 | 54 | #define DEFAULT_BG_SCAN_PERIOD 60 |
55 | 55 | ||
56 | struct ath6kl_cfg80211_match_probe_ssid { | ||
57 | struct cfg80211_ssid ssid; | ||
58 | u8 flag; | ||
59 | }; | ||
60 | |||
56 | static struct ieee80211_rate ath6kl_rates[] = { | 61 | static struct ieee80211_rate ath6kl_rates[] = { |
57 | RATETAB_ENT(10, 0x1, 0), | 62 | RATETAB_ENT(10, 0x1, 0), |
58 | RATETAB_ENT(20, 0x2, 0), | 63 | RATETAB_ENT(20, 0x2, 0), |
@@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
576 | 581 | ||
577 | vif->nw_type = vif->next_mode; | 582 | vif->nw_type = vif->next_mode; |
578 | 583 | ||
584 | /* enable enhanced bmiss detection if applicable */ | ||
585 | ath6kl_cfg80211_sta_bmiss_enhance(vif, true); | ||
586 | |||
579 | if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) | 587 | if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) |
580 | nw_subtype = SUBTYPE_P2PCLIENT; | 588 | nw_subtype = SUBTYPE_P2PCLIENT; |
581 | 589 | ||
@@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, | |||
852 | } | 860 | } |
853 | } | 861 | } |
854 | 862 | ||
855 | /* | ||
856 | * Send a disconnect command to target when a disconnect event is | ||
857 | * received with reason code other than 3 (DISCONNECT_CMD - disconnect | ||
858 | * request from host) to make the firmware stop trying to connect even | ||
859 | * after giving disconnect event. There will be one more disconnect | ||
860 | * event for this disconnect command with reason code DISCONNECT_CMD | ||
861 | * which will be notified to cfg80211. | ||
862 | */ | ||
863 | |||
864 | if (reason != DISCONNECT_CMD) { | ||
865 | ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); | ||
866 | return; | ||
867 | } | ||
868 | |||
869 | clear_bit(CONNECT_PEND, &vif->flags); | 863 | clear_bit(CONNECT_PEND, &vif->flags); |
870 | 864 | ||
871 | if (vif->sme_state == SME_CONNECTING) { | 865 | if (vif->sme_state == SME_CONNECTING) { |
@@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, | |||
875 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 869 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
876 | GFP_KERNEL); | 870 | GFP_KERNEL); |
877 | } else if (vif->sme_state == SME_CONNECTED) { | 871 | } else if (vif->sme_state == SME_CONNECTED) { |
878 | cfg80211_disconnected(vif->ndev, reason, | 872 | cfg80211_disconnected(vif->ndev, proto_reason, |
879 | NULL, 0, GFP_KERNEL); | 873 | NULL, 0, GFP_KERNEL); |
880 | } | 874 | } |
881 | 875 | ||
882 | vif->sme_state = SME_DISCONNECTED; | 876 | vif->sme_state = SME_DISCONNECTED; |
877 | |||
878 | /* | ||
879 | * Send a disconnect command to target when a disconnect event is | ||
880 | * received with reason code other than 3 (DISCONNECT_CMD - disconnect | ||
881 | * request from host) to make the firmware stop trying to connect even | ||
882 | * after giving disconnect event. There will be one more disconnect | ||
883 | * event for this disconnect command with reason code DISCONNECT_CMD | ||
884 | * which won't be notified to cfg80211. | ||
885 | */ | ||
886 | if (reason != DISCONNECT_CMD) | ||
887 | ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); | ||
883 | } | 888 | } |
884 | 889 | ||
885 | static int ath6kl_set_probed_ssids(struct ath6kl *ar, | 890 | static int ath6kl_set_probed_ssids(struct ath6kl *ar, |
886 | struct ath6kl_vif *vif, | 891 | struct ath6kl_vif *vif, |
887 | struct cfg80211_ssid *ssids, int n_ssids) | 892 | struct cfg80211_ssid *ssids, int n_ssids, |
893 | struct cfg80211_match_set *match_set, | ||
894 | int n_match_ssid) | ||
888 | { | 895 | { |
889 | u8 i; | 896 | u8 i, j, index_to_add, ssid_found = false; |
897 | struct ath6kl_cfg80211_match_probe_ssid ssid_list[MAX_PROBED_SSIDS]; | ||
890 | 898 | ||
891 | if (n_ssids > MAX_PROBED_SSID_INDEX) | 899 | memset(ssid_list, 0, sizeof(ssid_list)); |
900 | |||
901 | if (n_ssids > MAX_PROBED_SSIDS || | ||
902 | n_match_ssid > MAX_PROBED_SSIDS) | ||
892 | return -EINVAL; | 903 | return -EINVAL; |
893 | 904 | ||
894 | for (i = 0; i < n_ssids; i++) { | 905 | for (i = 0; i < n_ssids; i++) { |
906 | memcpy(ssid_list[i].ssid.ssid, | ||
907 | ssids[i].ssid, | ||
908 | ssids[i].ssid_len); | ||
909 | ssid_list[i].ssid.ssid_len = ssids[i].ssid_len; | ||
910 | |||
911 | if (ssids[i].ssid_len) | ||
912 | ssid_list[i].flag = SPECIFIC_SSID_FLAG; | ||
913 | else | ||
914 | ssid_list[i].flag = ANY_SSID_FLAG; | ||
915 | |||
916 | if (n_match_ssid == 0) | ||
917 | ssid_list[i].flag |= MATCH_SSID_FLAG; | ||
918 | } | ||
919 | |||
920 | index_to_add = i; | ||
921 | |||
922 | for (i = 0; i < n_match_ssid; i++) { | ||
923 | ssid_found = false; | ||
924 | |||
925 | for (j = 0; j < n_ssids; j++) { | ||
926 | if ((match_set[i].ssid.ssid_len == | ||
927 | ssid_list[j].ssid.ssid_len) && | ||
928 | (!memcmp(ssid_list[j].ssid.ssid, | ||
929 | match_set[i].ssid.ssid, | ||
930 | match_set[i].ssid.ssid_len))) { | ||
931 | ssid_list[j].flag |= MATCH_SSID_FLAG; | ||
932 | ssid_found = true; | ||
933 | break; | ||
934 | } | ||
935 | } | ||
936 | |||
937 | if (ssid_found) | ||
938 | continue; | ||
939 | |||
940 | if (index_to_add >= MAX_PROBED_SSIDS) | ||
941 | continue; | ||
942 | |||
943 | ssid_list[index_to_add].ssid.ssid_len = | ||
944 | match_set[i].ssid.ssid_len; | ||
945 | memcpy(ssid_list[index_to_add].ssid.ssid, | ||
946 | match_set[i].ssid.ssid, | ||
947 | match_set[i].ssid.ssid_len); | ||
948 | ssid_list[index_to_add].flag |= MATCH_SSID_FLAG; | ||
949 | index_to_add++; | ||
950 | } | ||
951 | |||
952 | for (i = 0; i < index_to_add; i++) { | ||
895 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | 953 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, |
896 | ssids[i].ssid_len ? | 954 | ssid_list[i].flag, |
897 | SPECIFIC_SSID_FLAG : ANY_SSID_FLAG, | 955 | ssid_list[i].ssid.ssid_len, |
898 | ssids[i].ssid_len, | 956 | ssid_list[i].ssid.ssid); |
899 | ssids[i].ssid); | 957 | |
900 | } | 958 | } |
901 | 959 | ||
902 | /* Make sure no old entries are left behind */ | 960 | /* Make sure no old entries are left behind */ |
903 | for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) { | 961 | for (i = index_to_add; i < MAX_PROBED_SSIDS; i++) { |
904 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | 962 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, |
905 | DISABLE_SSID_FLAG, 0, NULL); | 963 | DISABLE_SSID_FLAG, 0, NULL); |
906 | } | 964 | } |
@@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
934 | } | 992 | } |
935 | 993 | ||
936 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, | 994 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
937 | request->n_ssids); | 995 | request->n_ssids, NULL, 0); |
938 | if (ret < 0) | 996 | if (ret < 0) |
939 | return ret; | 997 | return ret; |
940 | 998 | ||
@@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
943 | WMI_FRAME_PROBE_REQ, | 1001 | WMI_FRAME_PROBE_REQ, |
944 | request->ie, request->ie_len); | 1002 | request->ie, request->ie_len); |
945 | if (ret) { | 1003 | if (ret) { |
946 | ath6kl_err("failed to set Probe Request appie for scan"); | 1004 | ath6kl_err("failed to set Probe Request appie for scan\n"); |
947 | return ret; | 1005 | return ret; |
948 | } | 1006 | } |
949 | 1007 | ||
@@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, | |||
1512 | } | 1570 | } |
1513 | } | 1571 | } |
1514 | 1572 | ||
1573 | /* need to clean up enhanced bmiss detection fw state */ | ||
1574 | ath6kl_cfg80211_sta_bmiss_enhance(vif, false); | ||
1575 | |||
1515 | set_iface_type: | 1576 | set_iface_type: |
1516 | switch (type) { | 1577 | switch (type) { |
1517 | case NL80211_IFTYPE_STATION: | 1578 | case NL80211_IFTYPE_STATION: |
@@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
2074 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) | 2135 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) |
2075 | return -EINVAL; | 2136 | return -EINVAL; |
2076 | 2137 | ||
2077 | if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) { | 2138 | if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) && |
2139 | test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, | ||
2140 | ar->fw_capabilities)) { | ||
2078 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | 2141 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, |
2079 | vif->fw_vif_idx, false); | 2142 | vif->fw_vif_idx, false); |
2080 | if (ret) | 2143 | if (ret) |
@@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
2209 | 2272 | ||
2210 | ar->state = ATH6KL_STATE_ON; | 2273 | ar->state = ATH6KL_STATE_ON; |
2211 | 2274 | ||
2212 | if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) { | 2275 | if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) && |
2276 | test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, | ||
2277 | ar->fw_capabilities)) { | ||
2213 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | 2278 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, |
2214 | vif->fw_vif_idx, true); | 2279 | vif->fw_vif_idx, true); |
2215 | if (ret) | 2280 | if (ret) |
@@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar) | |||
2475 | static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, | 2540 | static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, |
2476 | bool ht_enable) | 2541 | bool ht_enable) |
2477 | { | 2542 | { |
2478 | struct ath6kl_htcap *htcap = &vif->htcap; | 2543 | struct ath6kl_htcap *htcap = &vif->htcap[band]; |
2479 | 2544 | ||
2480 | if (htcap->ht_enable == ht_enable) | 2545 | if (htcap->ht_enable == ht_enable) |
2481 | return 0; | 2546 | return 0; |
@@ -2585,33 +2650,28 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, | |||
2585 | return 0; | 2650 | return 0; |
2586 | } | 2651 | } |
2587 | 2652 | ||
2588 | static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, | 2653 | void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable) |
2589 | struct ieee80211_channel *chan, | ||
2590 | enum nl80211_channel_type channel_type) | ||
2591 | { | 2654 | { |
2592 | struct ath6kl_vif *vif; | 2655 | int err; |
2593 | 2656 | ||
2594 | /* | 2657 | if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag))) |
2595 | * 'dev' could be NULL if a channel change is required for the hardware | 2658 | return; |
2596 | * device itself, instead of a particular VIF. | ||
2597 | * | ||
2598 | * FIXME: To be handled properly when monitor mode is supported. | ||
2599 | */ | ||
2600 | if (!dev) | ||
2601 | return -EBUSY; | ||
2602 | 2659 | ||
2603 | vif = netdev_priv(dev); | 2660 | if (vif->nw_type != INFRA_NETWORK) |
2661 | return; | ||
2604 | 2662 | ||
2605 | if (!ath6kl_cfg80211_ready(vif)) | 2663 | if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, |
2606 | return -EIO; | 2664 | vif->ar->fw_capabilities)) |
2665 | return; | ||
2607 | 2666 | ||
2608 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", | 2667 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n", |
2609 | __func__, chan->center_freq, chan->hw_value); | 2668 | enable ? "enable" : "disable"); |
2610 | vif->next_chan = chan->center_freq; | ||
2611 | vif->next_ch_type = channel_type; | ||
2612 | vif->next_ch_band = chan->band; | ||
2613 | 2669 | ||
2614 | return 0; | 2670 | err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi, |
2671 | vif->fw_vif_idx, enable); | ||
2672 | if (err) | ||
2673 | ath6kl_err("failed to %s enhanced bmiss detection: %d\n", | ||
2674 | enable ? "enable" : "disable", err); | ||
2615 | } | 2675 | } |
2616 | 2676 | ||
2617 | static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, | 2677 | static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, |
@@ -2694,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2694 | 2754 | ||
2695 | /* TODO: | 2755 | /* TODO: |
2696 | * info->interval | 2756 | * info->interval |
2697 | * info->dtim_period | ||
2698 | */ | 2757 | */ |
2699 | 2758 | ||
2759 | ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx, | ||
2760 | info->dtim_period); | ||
2761 | |||
2762 | /* ignore error, just print a warning and continue normally */ | ||
2763 | if (ret) | ||
2764 | ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret); | ||
2765 | |||
2700 | if (info->beacon.head == NULL) | 2766 | if (info->beacon.head == NULL) |
2701 | return -EINVAL; | 2767 | return -EINVAL; |
2702 | mgmt = (struct ieee80211_mgmt *) info->beacon.head; | 2768 | mgmt = (struct ieee80211_mgmt *) info->beacon.head; |
@@ -2791,7 +2857,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2791 | p.ssid_len = vif->ssid_len; | 2857 | p.ssid_len = vif->ssid_len; |
2792 | memcpy(p.ssid, vif->ssid, vif->ssid_len); | 2858 | memcpy(p.ssid, vif->ssid, vif->ssid_len); |
2793 | p.dot11_auth_mode = vif->dot11_auth_mode; | 2859 | p.dot11_auth_mode = vif->dot11_auth_mode; |
2794 | p.ch = cpu_to_le16(vif->next_chan); | 2860 | p.ch = cpu_to_le16(info->channel->center_freq); |
2795 | 2861 | ||
2796 | /* Enable uAPSD support by default */ | 2862 | /* Enable uAPSD support by default */ |
2797 | res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true); | 2863 | res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true); |
@@ -2815,8 +2881,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2815 | return res; | 2881 | return res; |
2816 | } | 2882 | } |
2817 | 2883 | ||
2818 | if (ath6kl_set_htcap(vif, vif->next_ch_band, | 2884 | if (ath6kl_set_htcap(vif, info->channel->band, |
2819 | vif->next_ch_type != NL80211_CHAN_NO_HT)) | 2885 | info->channel_type != NL80211_CHAN_NO_HT)) |
2820 | return -EIO; | 2886 | return -EIO; |
2821 | 2887 | ||
2822 | /* | 2888 | /* |
@@ -3160,10 +3226,24 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3160 | ath6kl_cfg80211_scan_complete_event(vif, true); | 3226 | ath6kl_cfg80211_scan_complete_event(vif, true); |
3161 | 3227 | ||
3162 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, | 3228 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
3163 | request->n_ssids); | 3229 | request->n_ssids, |
3230 | request->match_sets, | ||
3231 | request->n_match_sets); | ||
3164 | if (ret < 0) | 3232 | if (ret < 0) |
3165 | return ret; | 3233 | return ret; |
3166 | 3234 | ||
3235 | if (!request->n_match_sets) { | ||
3236 | ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, | ||
3237 | ALL_BSS_FILTER, 0); | ||
3238 | if (ret < 0) | ||
3239 | return ret; | ||
3240 | } else { | ||
3241 | ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, | ||
3242 | MATCHED_SSID_FILTER, 0); | ||
3243 | if (ret < 0) | ||
3244 | return ret; | ||
3245 | } | ||
3246 | |||
3167 | /* fw uses seconds, also make sure that it's >0 */ | 3247 | /* fw uses seconds, also make sure that it's >0 */ |
3168 | interval = max_t(u16, 1, request->interval / 1000); | 3248 | interval = max_t(u16, 1, request->interval / 1000); |
3169 | 3249 | ||
@@ -3185,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3185 | WMI_FRAME_PROBE_REQ, | 3265 | WMI_FRAME_PROBE_REQ, |
3186 | request->ie, request->ie_len); | 3266 | request->ie, request->ie_len); |
3187 | if (ret) { | 3267 | if (ret) { |
3188 | ath6kl_warn("Failed to set probe request IE for scheduled scan: %d", | 3268 | ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n", |
3189 | ret); | 3269 | ret); |
3190 | return ret; | 3270 | return ret; |
3191 | } | 3271 | } |
@@ -3217,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy, | |||
3217 | return 0; | 3297 | return 0; |
3218 | } | 3298 | } |
3219 | 3299 | ||
3300 | static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy, | ||
3301 | struct net_device *dev, | ||
3302 | const u8 *addr, | ||
3303 | const struct cfg80211_bitrate_mask *mask) | ||
3304 | { | ||
3305 | struct ath6kl *ar = ath6kl_priv(dev); | ||
3306 | struct ath6kl_vif *vif = netdev_priv(dev); | ||
3307 | |||
3308 | return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx, | ||
3309 | mask); | ||
3310 | } | ||
3311 | |||
3220 | static const struct ieee80211_txrx_stypes | 3312 | static const struct ieee80211_txrx_stypes |
3221 | ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { | 3313 | ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { |
3222 | [NL80211_IFTYPE_STATION] = { | 3314 | [NL80211_IFTYPE_STATION] = { |
@@ -3271,7 +3363,6 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { | |||
3271 | .suspend = __ath6kl_cfg80211_suspend, | 3363 | .suspend = __ath6kl_cfg80211_suspend, |
3272 | .resume = __ath6kl_cfg80211_resume, | 3364 | .resume = __ath6kl_cfg80211_resume, |
3273 | #endif | 3365 | #endif |
3274 | .set_channel = ath6kl_set_channel, | ||
3275 | .start_ap = ath6kl_start_ap, | 3366 | .start_ap = ath6kl_start_ap, |
3276 | .change_beacon = ath6kl_change_beacon, | 3367 | .change_beacon = ath6kl_change_beacon, |
3277 | .stop_ap = ath6kl_stop_ap, | 3368 | .stop_ap = ath6kl_stop_ap, |
@@ -3283,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { | |||
3283 | .mgmt_frame_register = ath6kl_mgmt_frame_register, | 3374 | .mgmt_frame_register = ath6kl_mgmt_frame_register, |
3284 | .sched_scan_start = ath6kl_cfg80211_sscan_start, | 3375 | .sched_scan_start = ath6kl_cfg80211_sscan_start, |
3285 | .sched_scan_stop = ath6kl_cfg80211_sscan_stop, | 3376 | .sched_scan_stop = ath6kl_cfg80211_sscan_stop, |
3377 | .set_bitrate_mask = ath6kl_cfg80211_set_bitrate, | ||
3286 | }; | 3378 | }; |
3287 | 3379 | ||
3288 | void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) | 3380 | void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) |
@@ -3410,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | |||
3410 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; | 3502 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; |
3411 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; | 3503 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; |
3412 | vif->bg_scan_period = 0; | 3504 | vif->bg_scan_period = 0; |
3413 | vif->htcap.ht_enable = true; | 3505 | vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true; |
3506 | vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true; | ||
3414 | 3507 | ||
3415 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); | 3508 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); |
3416 | if (fw_vif_idx != 0) | 3509 | if (fw_vif_idx != 0) |
@@ -3470,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3470 | } | 3563 | } |
3471 | 3564 | ||
3472 | /* max num of ssids that can be probed during scanning */ | 3565 | /* max num of ssids that can be probed during scanning */ |
3473 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; | 3566 | wiphy->max_scan_ssids = MAX_PROBED_SSIDS; |
3567 | |||
3568 | /* max num of ssids that can be matched after scan */ | ||
3569 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, | ||
3570 | ar->fw_capabilities)) | ||
3571 | wiphy->max_match_sets = MAX_PROBED_SSIDS; | ||
3572 | |||
3474 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ | 3573 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ |
3475 | switch (ar->hw.cap) { | 3574 | switch (ar->hw.cap) { |
3476 | case WMI_11AN_CAP: | 3575 | case WMI_11AN_CAP: |
@@ -3507,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3507 | ath6kl_band_5ghz.ht_cap.cap = 0; | 3606 | ath6kl_band_5ghz.ht_cap.cap = 0; |
3508 | ath6kl_band_5ghz.ht_cap.ht_supported = false; | 3607 | ath6kl_band_5ghz.ht_cap.ht_supported = false; |
3509 | } | 3608 | } |
3609 | |||
3610 | if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) { | ||
3611 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; | ||
3612 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; | ||
3613 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; | ||
3614 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; | ||
3615 | } else { | ||
3616 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; | ||
3617 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; | ||
3618 | } | ||
3619 | |||
3510 | if (band_2gig) | 3620 | if (band_2gig) |
3511 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | 3621 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; |
3512 | if (band_5gig) | 3622 | if (band_5gig) |
@@ -3527,7 +3637,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3527 | wiphy->wowlan.pattern_min_len = 1; | 3637 | wiphy->wowlan.pattern_min_len = 1; |
3528 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; | 3638 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; |
3529 | 3639 | ||
3530 | wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX; | 3640 | wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS; |
3531 | 3641 | ||
3532 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | 3642 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | |
3533 | WIPHY_FLAG_HAVE_AP_SME | | 3643 | WIPHY_FLAG_HAVE_AP_SME | |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index 5ea8cbb79f4..b992046a1b0 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h | |||
@@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar); | |||
62 | 62 | ||
63 | struct ath6kl *ath6kl_cfg80211_create(void); | 63 | struct ath6kl *ath6kl_cfg80211_create(void); |
64 | void ath6kl_cfg80211_destroy(struct ath6kl *ar); | 64 | void ath6kl_cfg80211_destroy(struct ath6kl *ar); |
65 | /* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */ | ||
66 | void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable); | ||
65 | 67 | ||
66 | #endif /* ATH6KL_CFG80211_H */ | 68 | #endif /* ATH6KL_CFG80211_H */ |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 4d9c6f14269..d38a31de344 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -100,6 +100,21 @@ enum ath6kl_fw_capability { | |||
100 | /* Firmware has support to override rsn cap of rsn ie */ | 100 | /* Firmware has support to override rsn cap of rsn ie */ |
101 | ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, | 101 | ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, |
102 | 102 | ||
103 | /* | ||
104 | * Multicast support in WOW and host awake mode. | ||
105 | * Allow all multicast in host awake mode. | ||
106 | * Apply multicast filter in WOW mode. | ||
107 | */ | ||
108 | ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, | ||
109 | |||
110 | /* Firmware supports enhanced bmiss detection */ | ||
111 | ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, | ||
112 | |||
113 | /* | ||
114 | * FW supports matching of ssid in schedule scan | ||
115 | */ | ||
116 | ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, | ||
117 | |||
103 | /* this needs to be last */ | 118 | /* this needs to be last */ |
104 | ATH6KL_FW_CAPABILITY_MAX, | 119 | ATH6KL_FW_CAPABILITY_MAX, |
105 | }; | 120 | }; |
@@ -112,6 +127,10 @@ struct ath6kl_fw_ie { | |||
112 | u8 data[0]; | 127 | u8 data[0]; |
113 | }; | 128 | }; |
114 | 129 | ||
130 | enum ath6kl_hw_flags { | ||
131 | ATH6KL_HW_FLAG_64BIT_RATES = BIT(0), | ||
132 | }; | ||
133 | |||
115 | #define ATH6KL_FW_API2_FILE "fw-2.bin" | 134 | #define ATH6KL_FW_API2_FILE "fw-2.bin" |
116 | #define ATH6KL_FW_API3_FILE "fw-3.bin" | 135 | #define ATH6KL_FW_API3_FILE "fw-3.bin" |
117 | 136 | ||
@@ -196,7 +215,7 @@ struct ath6kl_fw_ie { | |||
196 | 215 | ||
197 | #define AGGR_NUM_OF_FREE_NETBUFS 16 | 216 | #define AGGR_NUM_OF_FREE_NETBUFS 16 |
198 | 217 | ||
199 | #define AGGR_RX_TIMEOUT 400 /* in ms */ | 218 | #define AGGR_RX_TIMEOUT 100 /* in ms */ |
200 | 219 | ||
201 | #define WMI_TIMEOUT (2 * HZ) | 220 | #define WMI_TIMEOUT (2 * HZ) |
202 | 221 | ||
@@ -245,7 +264,6 @@ struct skb_hold_q { | |||
245 | 264 | ||
246 | struct rxtid { | 265 | struct rxtid { |
247 | bool aggr; | 266 | bool aggr; |
248 | bool progress; | ||
249 | bool timer_mon; | 267 | bool timer_mon; |
250 | u16 win_sz; | 268 | u16 win_sz; |
251 | u16 seq_next; | 269 | u16 seq_next; |
@@ -254,9 +272,15 @@ struct rxtid { | |||
254 | struct sk_buff_head q; | 272 | struct sk_buff_head q; |
255 | 273 | ||
256 | /* | 274 | /* |
257 | * FIXME: No clue what this should protect. Apparently it should | 275 | * lock mainly protects seq_next and hold_q. Movement of seq_next |
258 | * protect some of the fields above but they are also accessed | 276 | * needs to be protected between aggr_timeout() and |
259 | * without taking the lock. | 277 | * aggr_process_recv_frm(). hold_q will be holding the pending |
278 | * reorder frames and it's access should also be protected. | ||
279 | * Some of the other fields like hold_q_sz, win_sz and aggr are | ||
280 | * initialized/reset when receiving addba/delba req, also while | ||
281 | * deleting aggr state all the pending buffers are flushed before | ||
282 | * resetting these fields, so there should not be any race in accessing | ||
283 | * these fields. | ||
260 | */ | 284 | */ |
261 | spinlock_t lock; | 285 | spinlock_t lock; |
262 | }; | 286 | }; |
@@ -541,7 +565,7 @@ struct ath6kl_vif { | |||
541 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; | 565 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; |
542 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; | 566 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; |
543 | struct aggr_info *aggr_cntxt; | 567 | struct aggr_info *aggr_cntxt; |
544 | struct ath6kl_htcap htcap; | 568 | struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS]; |
545 | 569 | ||
546 | struct timer_list disconnect_timer; | 570 | struct timer_list disconnect_timer; |
547 | struct timer_list sched_scan_timer; | 571 | struct timer_list sched_scan_timer; |
@@ -553,9 +577,6 @@ struct ath6kl_vif { | |||
553 | u32 last_cancel_roc_id; | 577 | u32 last_cancel_roc_id; |
554 | u32 send_action_id; | 578 | u32 send_action_id; |
555 | bool probe_req_report; | 579 | bool probe_req_report; |
556 | u16 next_chan; | ||
557 | enum nl80211_channel_type next_ch_type; | ||
558 | enum ieee80211_band next_ch_band; | ||
559 | u16 assoc_bss_beacon_int; | 580 | u16 assoc_bss_beacon_int; |
560 | u16 listen_intvl_t; | 581 | u16 listen_intvl_t; |
561 | u16 bmiss_time_t; | 582 | u16 bmiss_time_t; |
@@ -687,6 +708,8 @@ struct ath6kl { | |||
687 | u32 testscript_addr; | 708 | u32 testscript_addr; |
688 | enum wmi_phy_cap cap; | 709 | enum wmi_phy_cap cap; |
689 | 710 | ||
711 | u32 flags; | ||
712 | |||
690 | struct ath6kl_hw_fw { | 713 | struct ath6kl_hw_fw { |
691 | const char *dir; | 714 | const char *dir; |
692 | const char *otp; | 715 | const char *otp; |
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index 2798624d3a9..cd0e1ba410d 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c | |||
@@ -1309,7 +1309,7 @@ static int ath6kl_htc_rx_packet(struct htc_target *target, | |||
1309 | } | 1309 | } |
1310 | 1310 | ||
1311 | ath6kl_dbg(ATH6KL_DBG_HTC, | 1311 | ath6kl_dbg(ATH6KL_DBG_HTC, |
1312 | "htc rx 0x%p hdr x%x len %d mbox 0x%x\n", | 1312 | "htc rx 0x%p hdr 0x%x len %d mbox 0x%x\n", |
1313 | packet, packet->info.rx.exp_hdr, | 1313 | packet, packet->info.rx.exp_hdr, |
1314 | padded_len, dev->ar->mbox_info.htc_addr); | 1314 | padded_len, dev->ar->mbox_info.htc_addr); |
1315 | 1315 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 7eb0515f458..f90b5db741c 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
42 | .reserved_ram_size = 6912, | 42 | .reserved_ram_size = 6912, |
43 | .refclk_hz = 26000000, | 43 | .refclk_hz = 26000000, |
44 | .uarttx_pin = 8, | 44 | .uarttx_pin = 8, |
45 | .flags = 0, | ||
45 | 46 | ||
46 | /* hw2.0 needs override address hardcoded */ | 47 | /* hw2.0 needs override address hardcoded */ |
47 | .app_start_override_addr = 0x944C00, | 48 | .app_start_override_addr = 0x944C00, |
@@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
67 | .refclk_hz = 26000000, | 68 | .refclk_hz = 26000000, |
68 | .uarttx_pin = 8, | 69 | .uarttx_pin = 8, |
69 | .testscript_addr = 0x57ef74, | 70 | .testscript_addr = 0x57ef74, |
71 | .flags = 0, | ||
70 | 72 | ||
71 | .fw = { | 73 | .fw = { |
72 | .dir = AR6003_HW_2_1_1_FW_DIR, | 74 | .dir = AR6003_HW_2_1_1_FW_DIR, |
@@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
91 | .board_addr = 0x433900, | 93 | .board_addr = 0x433900, |
92 | .refclk_hz = 26000000, | 94 | .refclk_hz = 26000000, |
93 | .uarttx_pin = 11, | 95 | .uarttx_pin = 11, |
96 | .flags = ATH6KL_HW_FLAG_64BIT_RATES, | ||
94 | 97 | ||
95 | .fw = { | 98 | .fw = { |
96 | .dir = AR6004_HW_1_0_FW_DIR, | 99 | .dir = AR6004_HW_1_0_FW_DIR, |
@@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
110 | .board_addr = 0x43d400, | 113 | .board_addr = 0x43d400, |
111 | .refclk_hz = 40000000, | 114 | .refclk_hz = 40000000, |
112 | .uarttx_pin = 11, | 115 | .uarttx_pin = 11, |
116 | .flags = ATH6KL_HW_FLAG_64BIT_RATES, | ||
113 | 117 | ||
114 | .fw = { | 118 | .fw = { |
115 | .dir = AR6004_HW_1_1_FW_DIR, | 119 | .dir = AR6004_HW_1_1_FW_DIR, |
@@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = { | |||
129 | .board_addr = 0x435c00, | 133 | .board_addr = 0x435c00, |
130 | .refclk_hz = 40000000, | 134 | .refclk_hz = 40000000, |
131 | .uarttx_pin = 11, | 135 | .uarttx_pin = 11, |
136 | .flags = ATH6KL_HW_FLAG_64BIT_RATES, | ||
132 | 137 | ||
133 | .fw = { | 138 | .fw = { |
134 | .dir = AR6004_HW_1_2_FW_DIR, | 139 | .dir = AR6004_HW_1_2_FW_DIR, |
@@ -938,6 +943,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
938 | } | 943 | } |
939 | 944 | ||
940 | switch (ie_id) { | 945 | switch (ie_id) { |
946 | case ATH6KL_FW_IE_FW_VERSION: | ||
947 | strlcpy(ar->wiphy->fw_version, data, | ||
948 | sizeof(ar->wiphy->fw_version)); | ||
949 | |||
950 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
951 | "found fw version %s\n", | ||
952 | ar->wiphy->fw_version); | ||
953 | break; | ||
941 | case ATH6KL_FW_IE_OTP_IMAGE: | 954 | case ATH6KL_FW_IE_OTP_IMAGE: |
942 | ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n", | 955 | ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n", |
943 | ie_len); | 956 | ie_len); |
@@ -991,9 +1004,6 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
991 | ar->hw.reserved_ram_size); | 1004 | ar->hw.reserved_ram_size); |
992 | break; | 1005 | break; |
993 | case ATH6KL_FW_IE_CAPABILITIES: | 1006 | case ATH6KL_FW_IE_CAPABILITIES: |
994 | if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8)) | ||
995 | break; | ||
996 | |||
997 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 1007 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
998 | "found firmware capabilities ie (%zd B)\n", | 1008 | "found firmware capabilities ie (%zd B)\n", |
999 | ie_len); | 1009 | ie_len); |
@@ -1002,6 +1012,9 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
1002 | index = i / 8; | 1012 | index = i / 8; |
1003 | bit = i % 8; | 1013 | bit = i % 8; |
1004 | 1014 | ||
1015 | if (index == ie_len) | ||
1016 | break; | ||
1017 | |||
1005 | if (data[index] & (1 << bit)) | 1018 | if (data[index] & (1 << bit)) |
1006 | __set_bit(i, ar->fw_capabilities); | 1019 | __set_bit(i, ar->fw_capabilities); |
1007 | } | 1020 | } |
@@ -1392,6 +1405,12 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
1392 | ar->version.target_ver == AR6003_HW_2_1_1_VERSION) { | 1405 | ar->version.target_ver == AR6003_HW_2_1_1_VERSION) { |
1393 | ath6kl_err("temporary war to avoid sdio crc error\n"); | 1406 | ath6kl_err("temporary war to avoid sdio crc error\n"); |
1394 | 1407 | ||
1408 | param = 0x28; | ||
1409 | address = GPIO_BASE_ADDRESS + GPIO_PIN9_ADDRESS; | ||
1410 | status = ath6kl_bmi_reg_write(ar, address, param); | ||
1411 | if (status) | ||
1412 | return status; | ||
1413 | |||
1395 | param = 0x20; | 1414 | param = 0x20; |
1396 | 1415 | ||
1397 | address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; | 1416 | address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; |
@@ -1659,6 +1678,9 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) | |||
1659 | cfg80211_scan_done(vif->scan_req, true); | 1678 | cfg80211_scan_done(vif->scan_req, true); |
1660 | vif->scan_req = NULL; | 1679 | vif->scan_req = NULL; |
1661 | } | 1680 | } |
1681 | |||
1682 | /* need to clean up enhanced bmiss detection fw state */ | ||
1683 | ath6kl_cfg80211_sta_bmiss_enhance(vif, false); | ||
1662 | } | 1684 | } |
1663 | 1685 | ||
1664 | void ath6kl_stop_txrx(struct ath6kl *ar) | 1686 | void ath6kl_stop_txrx(struct ath6kl *ar) |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index e5524470529..c189e28e86a 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -554,20 +554,24 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, | |||
554 | struct ath6kl *ar = devt; | 554 | struct ath6kl *ar = devt; |
555 | 555 | ||
556 | memcpy(ar->mac_addr, datap, ETH_ALEN); | 556 | memcpy(ar->mac_addr, datap, ETH_ALEN); |
557 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n", | 557 | |
558 | __func__, ar->mac_addr); | 558 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
559 | "ready event mac addr %pM sw_ver 0x%x abi_ver 0x%x cap 0x%x\n", | ||
560 | ar->mac_addr, sw_ver, abi_ver, cap); | ||
559 | 561 | ||
560 | ar->version.wlan_ver = sw_ver; | 562 | ar->version.wlan_ver = sw_ver; |
561 | ar->version.abi_ver = abi_ver; | 563 | ar->version.abi_ver = abi_ver; |
562 | ar->hw.cap = cap; | 564 | ar->hw.cap = cap; |
563 | 565 | ||
564 | snprintf(ar->wiphy->fw_version, | 566 | if (strlen(ar->wiphy->fw_version) == 0) { |
565 | sizeof(ar->wiphy->fw_version), | 567 | snprintf(ar->wiphy->fw_version, |
566 | "%u.%u.%u.%u", | 568 | sizeof(ar->wiphy->fw_version), |
567 | (ar->version.wlan_ver & 0xf0000000) >> 28, | 569 | "%u.%u.%u.%u", |
568 | (ar->version.wlan_ver & 0x0f000000) >> 24, | 570 | (ar->version.wlan_ver & 0xf0000000) >> 28, |
569 | (ar->version.wlan_ver & 0x00ff0000) >> 16, | 571 | (ar->version.wlan_ver & 0x0f000000) >> 24, |
570 | (ar->version.wlan_ver & 0x0000ffff)); | 572 | (ar->version.wlan_ver & 0x00ff0000) >> 16, |
573 | (ar->version.wlan_ver & 0x0000ffff)); | ||
574 | } | ||
571 | 575 | ||
572 | /* indicate to the waiting thread that the ready event was received */ | 576 | /* indicate to the waiting thread that the ready event was received */ |
573 | set_bit(WMI_READY, &ar->flag); | 577 | set_bit(WMI_READY, &ar->flag); |
@@ -598,7 +602,6 @@ static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel) | |||
598 | 602 | ||
599 | struct ath6kl *ar = vif->ar; | 603 | struct ath6kl *ar = vif->ar; |
600 | 604 | ||
601 | vif->next_chan = channel; | ||
602 | vif->profile.ch = cpu_to_le16(channel); | 605 | vif->profile.ch = cpu_to_le16(channel); |
603 | 606 | ||
604 | switch (vif->nw_type) { | 607 | switch (vif->nw_type) { |
@@ -1167,7 +1170,10 @@ static void ath6kl_set_multicast_list(struct net_device *ndev) | |||
1167 | else | 1170 | else |
1168 | clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags); | 1171 | clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags); |
1169 | 1172 | ||
1170 | mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON); | 1173 | if (test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, |
1174 | vif->ar->fw_capabilities)) { | ||
1175 | mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON); | ||
1176 | } | ||
1171 | 1177 | ||
1172 | if (!(ndev->flags & IFF_MULTICAST)) { | 1178 | if (!(ndev->flags & IFF_MULTICAST)) { |
1173 | mc_all_on = false; | 1179 | mc_all_on = false; |
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h index 78e0ef4567a..a98c12ba70c 100644 --- a/drivers/net/wireless/ath/ath6kl/target.h +++ b/drivers/net/wireless/ath/ath6kl/target.h | |||
@@ -45,6 +45,7 @@ | |||
45 | #define LPO_CAL_ENABLE_S 20 | 45 | #define LPO_CAL_ENABLE_S 20 |
46 | #define LPO_CAL_ENABLE 0x00100000 | 46 | #define LPO_CAL_ENABLE 0x00100000 |
47 | 47 | ||
48 | #define GPIO_PIN9_ADDRESS 0x0000004c | ||
48 | #define GPIO_PIN10_ADDRESS 0x00000050 | 49 | #define GPIO_PIN10_ADDRESS 0x00000050 |
49 | #define GPIO_PIN11_ADDRESS 0x00000054 | 50 | #define GPIO_PIN11_ADDRESS 0x00000054 |
50 | #define GPIO_PIN12_ADDRESS 0x00000058 | 51 | #define GPIO_PIN12_ADDRESS 0x00000058 |
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 67206aedea6..7dfa0fd86d7 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -1036,6 +1036,7 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, | |||
1036 | rxtid = &agg_conn->rx_tid[tid]; | 1036 | rxtid = &agg_conn->rx_tid[tid]; |
1037 | stats = &agg_conn->stat[tid]; | 1037 | stats = &agg_conn->stat[tid]; |
1038 | 1038 | ||
1039 | spin_lock_bh(&rxtid->lock); | ||
1039 | idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); | 1040 | idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); |
1040 | 1041 | ||
1041 | /* | 1042 | /* |
@@ -1054,8 +1055,6 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, | |||
1054 | seq_end = seq_no ? seq_no : rxtid->seq_next; | 1055 | seq_end = seq_no ? seq_no : rxtid->seq_next; |
1055 | idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz); | 1056 | idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz); |
1056 | 1057 | ||
1057 | spin_lock_bh(&rxtid->lock); | ||
1058 | |||
1059 | do { | 1058 | do { |
1060 | node = &rxtid->hold_q[idx]; | 1059 | node = &rxtid->hold_q[idx]; |
1061 | if ((order == 1) && (!node->skb)) | 1060 | if ((order == 1) && (!node->skb)) |
@@ -1127,11 +1126,13 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, | |||
1127 | ((end > extended_end) && (cur > extended_end) && | 1126 | ((end > extended_end) && (cur > extended_end) && |
1128 | (cur < end))) { | 1127 | (cur < end))) { |
1129 | aggr_deque_frms(agg_conn, tid, 0, 0); | 1128 | aggr_deque_frms(agg_conn, tid, 0, 0); |
1129 | spin_lock_bh(&rxtid->lock); | ||
1130 | if (cur >= rxtid->hold_q_sz - 1) | 1130 | if (cur >= rxtid->hold_q_sz - 1) |
1131 | rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); | 1131 | rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); |
1132 | else | 1132 | else |
1133 | rxtid->seq_next = ATH6KL_MAX_SEQ_NO - | 1133 | rxtid->seq_next = ATH6KL_MAX_SEQ_NO - |
1134 | (rxtid->hold_q_sz - 2 - cur); | 1134 | (rxtid->hold_q_sz - 2 - cur); |
1135 | spin_unlock_bh(&rxtid->lock); | ||
1135 | } else { | 1136 | } else { |
1136 | /* | 1137 | /* |
1137 | * Dequeue only those frames that are outside the | 1138 | * Dequeue only those frames that are outside the |
@@ -1185,25 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, | |||
1185 | aggr_deque_frms(agg_conn, tid, 0, 1); | 1186 | aggr_deque_frms(agg_conn, tid, 0, 1); |
1186 | 1187 | ||
1187 | if (agg_conn->timer_scheduled) | 1188 | if (agg_conn->timer_scheduled) |
1188 | rxtid->progress = true; | 1189 | return is_queued; |
1189 | else | 1190 | |
1190 | for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { | 1191 | spin_lock_bh(&rxtid->lock); |
1191 | if (rxtid->hold_q[idx].skb) { | 1192 | for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { |
1192 | /* | 1193 | if (rxtid->hold_q[idx].skb) { |
1193 | * There is a frame in the queue and no | 1194 | /* |
1194 | * timer so start a timer to ensure that | 1195 | * There is a frame in the queue and no |
1195 | * the frame doesn't remain stuck | 1196 | * timer so start a timer to ensure that |
1196 | * forever. | 1197 | * the frame doesn't remain stuck |
1197 | */ | 1198 | * forever. |
1198 | agg_conn->timer_scheduled = true; | 1199 | */ |
1199 | mod_timer(&agg_conn->timer, | 1200 | agg_conn->timer_scheduled = true; |
1200 | (jiffies + | 1201 | mod_timer(&agg_conn->timer, |
1201 | HZ * (AGGR_RX_TIMEOUT) / 1000)); | 1202 | (jiffies + (HZ * AGGR_RX_TIMEOUT) / 1000)); |
1202 | rxtid->progress = false; | 1203 | rxtid->timer_mon = true; |
1203 | rxtid->timer_mon = true; | 1204 | break; |
1204 | break; | ||
1205 | } | ||
1206 | } | 1205 | } |
1206 | } | ||
1207 | spin_unlock_bh(&rxtid->lock); | ||
1207 | 1208 | ||
1208 | return is_queued; | 1209 | return is_queued; |
1209 | } | 1210 | } |
@@ -1608,7 +1609,7 @@ static void aggr_timeout(unsigned long arg) | |||
1608 | rxtid = &aggr_conn->rx_tid[i]; | 1609 | rxtid = &aggr_conn->rx_tid[i]; |
1609 | stats = &aggr_conn->stat[i]; | 1610 | stats = &aggr_conn->stat[i]; |
1610 | 1611 | ||
1611 | if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) | 1612 | if (!rxtid->aggr || !rxtid->timer_mon) |
1612 | continue; | 1613 | continue; |
1613 | 1614 | ||
1614 | stats->num_timeouts++; | 1615 | stats->num_timeouts++; |
@@ -1626,14 +1627,15 @@ static void aggr_timeout(unsigned long arg) | |||
1626 | rxtid = &aggr_conn->rx_tid[i]; | 1627 | rxtid = &aggr_conn->rx_tid[i]; |
1627 | 1628 | ||
1628 | if (rxtid->aggr && rxtid->hold_q) { | 1629 | if (rxtid->aggr && rxtid->hold_q) { |
1630 | spin_lock_bh(&rxtid->lock); | ||
1629 | for (j = 0; j < rxtid->hold_q_sz; j++) { | 1631 | for (j = 0; j < rxtid->hold_q_sz; j++) { |
1630 | if (rxtid->hold_q[j].skb) { | 1632 | if (rxtid->hold_q[j].skb) { |
1631 | aggr_conn->timer_scheduled = true; | 1633 | aggr_conn->timer_scheduled = true; |
1632 | rxtid->timer_mon = true; | 1634 | rxtid->timer_mon = true; |
1633 | rxtid->progress = false; | ||
1634 | break; | 1635 | break; |
1635 | } | 1636 | } |
1636 | } | 1637 | } |
1638 | spin_unlock_bh(&rxtid->lock); | ||
1637 | 1639 | ||
1638 | if (j >= rxtid->hold_q_sz) | 1640 | if (j >= rxtid->hold_q_sz) |
1639 | rxtid->timer_mon = false; | 1641 | rxtid->timer_mon = false; |
@@ -1660,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) | |||
1660 | aggr_deque_frms(aggr_conn, tid, 0, 0); | 1662 | aggr_deque_frms(aggr_conn, tid, 0, 0); |
1661 | 1663 | ||
1662 | rxtid->aggr = false; | 1664 | rxtid->aggr = false; |
1663 | rxtid->progress = false; | ||
1664 | rxtid->timer_mon = false; | 1665 | rxtid->timer_mon = false; |
1665 | rxtid->win_sz = 0; | 1666 | rxtid->win_sz = 0; |
1666 | rxtid->seq_next = 0; | 1667 | rxtid->seq_next = 0; |
@@ -1739,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info, | |||
1739 | for (i = 0; i < NUM_OF_TIDS; i++) { | 1740 | for (i = 0; i < NUM_OF_TIDS; i++) { |
1740 | rxtid = &aggr_conn->rx_tid[i]; | 1741 | rxtid = &aggr_conn->rx_tid[i]; |
1741 | rxtid->aggr = false; | 1742 | rxtid->aggr = false; |
1742 | rxtid->progress = false; | ||
1743 | rxtid->timer_mon = false; | 1743 | rxtid->timer_mon = false; |
1744 | skb_queue_head_init(&rxtid->q); | 1744 | skb_queue_head_init(&rxtid->q); |
1745 | spin_lock_init(&rxtid->lock); | 1745 | spin_lock_init(&rxtid->lock); |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index ee8ec2394c2..a6caa673e8a 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -743,7 +743,6 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) | |||
743 | return -ENOMEM; | 743 | return -ENOMEM; |
744 | 744 | ||
745 | cmd = (struct roam_ctrl_cmd *) skb->data; | 745 | cmd = (struct roam_ctrl_cmd *) skb->data; |
746 | memset(cmd, 0, sizeof(*cmd)); | ||
747 | 746 | ||
748 | memcpy(cmd->info.bssid, bssid, ETH_ALEN); | 747 | memcpy(cmd->info.bssid, bssid, ETH_ALEN); |
749 | cmd->roam_ctrl = WMI_FORCE_ROAM; | 748 | cmd->roam_ctrl = WMI_FORCE_ROAM; |
@@ -753,6 +752,22 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) | |||
753 | NO_SYNC_WMIFLAG); | 752 | NO_SYNC_WMIFLAG); |
754 | } | 753 | } |
755 | 754 | ||
755 | int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period) | ||
756 | { | ||
757 | struct sk_buff *skb; | ||
758 | struct set_dtim_cmd *cmd; | ||
759 | |||
760 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
761 | if (!skb) | ||
762 | return -ENOMEM; | ||
763 | |||
764 | cmd = (struct set_dtim_cmd *) skb->data; | ||
765 | |||
766 | cmd->dtim_period = cpu_to_le32(dtim_period); | ||
767 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
768 | WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG); | ||
769 | } | ||
770 | |||
756 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) | 771 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) |
757 | { | 772 | { |
758 | struct sk_buff *skb; | 773 | struct sk_buff *skb; |
@@ -763,7 +778,6 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) | |||
763 | return -ENOMEM; | 778 | return -ENOMEM; |
764 | 779 | ||
765 | cmd = (struct roam_ctrl_cmd *) skb->data; | 780 | cmd = (struct roam_ctrl_cmd *) skb->data; |
766 | memset(cmd, 0, sizeof(*cmd)); | ||
767 | 781 | ||
768 | cmd->info.roam_mode = mode; | 782 | cmd->info.roam_mode = mode; |
769 | cmd->roam_ctrl = WMI_SET_ROAM_MODE; | 783 | cmd->roam_ctrl = WMI_SET_ROAM_MODE; |
@@ -1995,7 +2009,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag, | |||
1995 | struct wmi_probed_ssid_cmd *cmd; | 2009 | struct wmi_probed_ssid_cmd *cmd; |
1996 | int ret; | 2010 | int ret; |
1997 | 2011 | ||
1998 | if (index > MAX_PROBED_SSID_INDEX) | 2012 | if (index >= MAX_PROBED_SSIDS) |
1999 | return -EINVAL; | 2013 | return -EINVAL; |
2000 | 2014 | ||
2001 | if (ssid_len > sizeof(cmd->ssid)) | 2015 | if (ssid_len > sizeof(cmd->ssid)) |
@@ -2599,6 +2613,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi) | |||
2599 | spin_unlock_bh(&wmi->lock); | 2613 | spin_unlock_bh(&wmi->lock); |
2600 | } | 2614 | } |
2601 | 2615 | ||
2616 | static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx, | ||
2617 | const struct cfg80211_bitrate_mask *mask) | ||
2618 | { | ||
2619 | struct sk_buff *skb; | ||
2620 | int ret, mode, band; | ||
2621 | u64 mcsrate, ratemask[IEEE80211_NUM_BANDS]; | ||
2622 | struct wmi_set_tx_select_rates64_cmd *cmd; | ||
2623 | |||
2624 | memset(&ratemask, 0, sizeof(ratemask)); | ||
2625 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
2626 | /* copy legacy rate mask */ | ||
2627 | ratemask[band] = mask->control[band].legacy; | ||
2628 | if (band == IEEE80211_BAND_5GHZ) | ||
2629 | ratemask[band] = | ||
2630 | mask->control[band].legacy << 4; | ||
2631 | |||
2632 | /* copy mcs rate mask */ | ||
2633 | mcsrate = mask->control[band].mcs[1]; | ||
2634 | mcsrate <<= 8; | ||
2635 | mcsrate |= mask->control[band].mcs[0]; | ||
2636 | ratemask[band] |= mcsrate << 12; | ||
2637 | ratemask[band] |= mcsrate << 28; | ||
2638 | } | ||
2639 | |||
2640 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
2641 | "Ratemask 64 bit: 2.4:%llx 5:%llx\n", | ||
2642 | ratemask[0], ratemask[1]); | ||
2643 | |||
2644 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX); | ||
2645 | if (!skb) | ||
2646 | return -ENOMEM; | ||
2647 | |||
2648 | cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data; | ||
2649 | for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) { | ||
2650 | /* A mode operate in 5GHZ band */ | ||
2651 | if (mode == WMI_RATES_MODE_11A || | ||
2652 | mode == WMI_RATES_MODE_11A_HT20 || | ||
2653 | mode == WMI_RATES_MODE_11A_HT40) | ||
2654 | band = IEEE80211_BAND_5GHZ; | ||
2655 | else | ||
2656 | band = IEEE80211_BAND_2GHZ; | ||
2657 | cmd->ratemask[mode] = cpu_to_le64(ratemask[band]); | ||
2658 | } | ||
2659 | |||
2660 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
2661 | WMI_SET_TX_SELECT_RATES_CMDID, | ||
2662 | NO_SYNC_WMIFLAG); | ||
2663 | return ret; | ||
2664 | } | ||
2665 | |||
2666 | static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx, | ||
2667 | const struct cfg80211_bitrate_mask *mask) | ||
2668 | { | ||
2669 | struct sk_buff *skb; | ||
2670 | int ret, mode, band; | ||
2671 | u32 mcsrate, ratemask[IEEE80211_NUM_BANDS]; | ||
2672 | struct wmi_set_tx_select_rates32_cmd *cmd; | ||
2673 | |||
2674 | memset(&ratemask, 0, sizeof(ratemask)); | ||
2675 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
2676 | /* copy legacy rate mask */ | ||
2677 | ratemask[band] = mask->control[band].legacy; | ||
2678 | if (band == IEEE80211_BAND_5GHZ) | ||
2679 | ratemask[band] = | ||
2680 | mask->control[band].legacy << 4; | ||
2681 | |||
2682 | /* copy mcs rate mask */ | ||
2683 | mcsrate = mask->control[band].mcs[0]; | ||
2684 | ratemask[band] |= mcsrate << 12; | ||
2685 | ratemask[band] |= mcsrate << 20; | ||
2686 | } | ||
2687 | |||
2688 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
2689 | "Ratemask 32 bit: 2.4:%x 5:%x\n", | ||
2690 | ratemask[0], ratemask[1]); | ||
2691 | |||
2692 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX); | ||
2693 | if (!skb) | ||
2694 | return -ENOMEM; | ||
2695 | |||
2696 | cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data; | ||
2697 | for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) { | ||
2698 | /* A mode operate in 5GHZ band */ | ||
2699 | if (mode == WMI_RATES_MODE_11A || | ||
2700 | mode == WMI_RATES_MODE_11A_HT20 || | ||
2701 | mode == WMI_RATES_MODE_11A_HT40) | ||
2702 | band = IEEE80211_BAND_5GHZ; | ||
2703 | else | ||
2704 | band = IEEE80211_BAND_2GHZ; | ||
2705 | cmd->ratemask[mode] = cpu_to_le32(ratemask[band]); | ||
2706 | } | ||
2707 | |||
2708 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
2709 | WMI_SET_TX_SELECT_RATES_CMDID, | ||
2710 | NO_SYNC_WMIFLAG); | ||
2711 | return ret; | ||
2712 | } | ||
2713 | |||
2714 | int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx, | ||
2715 | const struct cfg80211_bitrate_mask *mask) | ||
2716 | { | ||
2717 | struct ath6kl *ar = wmi->parent_dev; | ||
2718 | |||
2719 | if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) | ||
2720 | return ath6kl_set_bitrate_mask64(wmi, if_idx, mask); | ||
2721 | else | ||
2722 | return ath6kl_set_bitrate_mask32(wmi, if_idx, mask); | ||
2723 | } | ||
2724 | |||
2602 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, | 2725 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, |
2603 | enum ath6kl_host_mode host_mode) | 2726 | enum ath6kl_host_mode host_mode) |
2604 | { | 2727 | { |
@@ -2997,6 +3120,25 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, | |||
2997 | return ret; | 3120 | return ret; |
2998 | } | 3121 | } |
2999 | 3122 | ||
3123 | int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance) | ||
3124 | { | ||
3125 | struct sk_buff *skb; | ||
3126 | struct wmi_sta_bmiss_enhance_cmd *cmd; | ||
3127 | int ret; | ||
3128 | |||
3129 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
3130 | if (!skb) | ||
3131 | return -ENOMEM; | ||
3132 | |||
3133 | cmd = (struct wmi_sta_bmiss_enhance_cmd *) skb->data; | ||
3134 | cmd->enable = enhance ? 1 : 0; | ||
3135 | |||
3136 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
3137 | WMI_STA_BMISS_ENHANCE_CMDID, | ||
3138 | NO_SYNC_WMIFLAG); | ||
3139 | return ret; | ||
3140 | } | ||
3141 | |||
3000 | s32 ath6kl_wmi_get_rate(s8 rate_index) | 3142 | s32 ath6kl_wmi_get_rate(s8 rate_index) |
3001 | { | 3143 | { |
3002 | if (rate_index == RATE_AUTO) | 3144 | if (rate_index == RATE_AUTO) |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 9076bec3a2b..43339aca585 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -624,6 +624,10 @@ enum wmi_cmd_id { | |||
624 | WMI_SEND_MGMT_CMDID, | 624 | WMI_SEND_MGMT_CMDID, |
625 | WMI_BEGIN_SCAN_CMDID, | 625 | WMI_BEGIN_SCAN_CMDID, |
626 | 626 | ||
627 | WMI_SET_BLACK_LIST, | ||
628 | WMI_SET_MCASTRATE, | ||
629 | |||
630 | WMI_STA_BMISS_ENHANCE_CMDID, | ||
627 | }; | 631 | }; |
628 | 632 | ||
629 | enum wmi_mgmt_frame_type { | 633 | enum wmi_mgmt_frame_type { |
@@ -960,6 +964,9 @@ enum wmi_bss_filter { | |||
960 | /* beacons matching probed ssid */ | 964 | /* beacons matching probed ssid */ |
961 | PROBED_SSID_FILTER, | 965 | PROBED_SSID_FILTER, |
962 | 966 | ||
967 | /* beacons matching matched ssid */ | ||
968 | MATCHED_SSID_FILTER, | ||
969 | |||
963 | /* marker only */ | 970 | /* marker only */ |
964 | LAST_BSS_FILTER, | 971 | LAST_BSS_FILTER, |
965 | }; | 972 | }; |
@@ -978,7 +985,7 @@ struct wmi_bss_filter_cmd { | |||
978 | } __packed; | 985 | } __packed; |
979 | 986 | ||
980 | /* WMI_SET_PROBED_SSID_CMDID */ | 987 | /* WMI_SET_PROBED_SSID_CMDID */ |
981 | #define MAX_PROBED_SSID_INDEX 9 | 988 | #define MAX_PROBED_SSIDS 16 |
982 | 989 | ||
983 | enum wmi_ssid_flag { | 990 | enum wmi_ssid_flag { |
984 | /* disables entry */ | 991 | /* disables entry */ |
@@ -989,10 +996,13 @@ enum wmi_ssid_flag { | |||
989 | 996 | ||
990 | /* probes for any ssid */ | 997 | /* probes for any ssid */ |
991 | ANY_SSID_FLAG = 0x02, | 998 | ANY_SSID_FLAG = 0x02, |
999 | |||
1000 | /* match for ssid */ | ||
1001 | MATCH_SSID_FLAG = 0x08, | ||
992 | }; | 1002 | }; |
993 | 1003 | ||
994 | struct wmi_probed_ssid_cmd { | 1004 | struct wmi_probed_ssid_cmd { |
995 | /* 0 to MAX_PROBED_SSID_INDEX */ | 1005 | /* 0 to MAX_PROBED_SSIDS - 1 */ |
996 | u8 entry_index; | 1006 | u8 entry_index; |
997 | 1007 | ||
998 | /* see, enum wmi_ssid_flg */ | 1008 | /* see, enum wmi_ssid_flg */ |
@@ -1017,6 +1027,11 @@ struct wmi_bmiss_time_cmd { | |||
1017 | __le16 num_beacons; | 1027 | __le16 num_beacons; |
1018 | }; | 1028 | }; |
1019 | 1029 | ||
1030 | /* WMI_STA_ENHANCE_BMISS_CMDID */ | ||
1031 | struct wmi_sta_bmiss_enhance_cmd { | ||
1032 | u8 enable; | ||
1033 | } __packed; | ||
1034 | |||
1020 | /* WMI_SET_POWER_MODE_CMDID */ | 1035 | /* WMI_SET_POWER_MODE_CMDID */ |
1021 | enum wmi_power_mode { | 1036 | enum wmi_power_mode { |
1022 | REC_POWER = 0x01, | 1037 | REC_POWER = 0x01, |
@@ -1048,6 +1063,36 @@ struct wmi_power_params_cmd { | |||
1048 | __le16 ps_fail_event_policy; | 1063 | __le16 ps_fail_event_policy; |
1049 | } __packed; | 1064 | } __packed; |
1050 | 1065 | ||
1066 | /* | ||
1067 | * Ratemask for below modes should be passed | ||
1068 | * to WMI_SET_TX_SELECT_RATES_CMDID. | ||
1069 | * AR6003 has 32 bit mask for each modes. | ||
1070 | * First 12 bits for legacy rates, 13 to 20 | ||
1071 | * bits for HT 20 rates and 21 to 28 bits for | ||
1072 | * HT 40 rates | ||
1073 | */ | ||
1074 | enum wmi_mode_phy { | ||
1075 | WMI_RATES_MODE_11A = 0, | ||
1076 | WMI_RATES_MODE_11G, | ||
1077 | WMI_RATES_MODE_11B, | ||
1078 | WMI_RATES_MODE_11GONLY, | ||
1079 | WMI_RATES_MODE_11A_HT20, | ||
1080 | WMI_RATES_MODE_11G_HT20, | ||
1081 | WMI_RATES_MODE_11A_HT40, | ||
1082 | WMI_RATES_MODE_11G_HT40, | ||
1083 | WMI_RATES_MODE_MAX | ||
1084 | }; | ||
1085 | |||
1086 | /* WMI_SET_TX_SELECT_RATES_CMDID */ | ||
1087 | struct wmi_set_tx_select_rates32_cmd { | ||
1088 | __le32 ratemask[WMI_RATES_MODE_MAX]; | ||
1089 | } __packed; | ||
1090 | |||
1091 | /* WMI_SET_TX_SELECT_RATES_CMDID */ | ||
1092 | struct wmi_set_tx_select_rates64_cmd { | ||
1093 | __le64 ratemask[WMI_RATES_MODE_MAX]; | ||
1094 | } __packed; | ||
1095 | |||
1051 | /* WMI_SET_DISC_TIMEOUT_CMDID */ | 1096 | /* WMI_SET_DISC_TIMEOUT_CMDID */ |
1052 | struct wmi_disc_timeout_cmd { | 1097 | struct wmi_disc_timeout_cmd { |
1053 | /* seconds */ | 1098 | /* seconds */ |
@@ -1572,6 +1617,10 @@ struct roam_ctrl_cmd { | |||
1572 | u8 roam_ctrl; | 1617 | u8 roam_ctrl; |
1573 | } __packed; | 1618 | } __packed; |
1574 | 1619 | ||
1620 | struct set_dtim_cmd { | ||
1621 | __le32 dtim_period; | ||
1622 | } __packed; | ||
1623 | |||
1575 | /* BSS INFO HDR version 2.0 */ | 1624 | /* BSS INFO HDR version 2.0 */ |
1576 | struct wmi_bss_info_hdr2 { | 1625 | struct wmi_bss_info_hdr2 { |
1577 | __le16 ch; /* frequency in MHz */ | 1626 | __le16 ch; /* frequency in MHz */ |
@@ -2532,6 +2581,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, | |||
2532 | __be32 ips0, __be32 ips1); | 2581 | __be32 ips0, __be32 ips1); |
2533 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, | 2582 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, |
2534 | enum ath6kl_host_mode host_mode); | 2583 | enum ath6kl_host_mode host_mode); |
2584 | int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx, | ||
2585 | const struct cfg80211_bitrate_mask *mask); | ||
2535 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, | 2586 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, |
2536 | enum ath6kl_wow_mode wow_mode, | 2587 | enum ath6kl_wow_mode wow_mode, |
2537 | u32 filter, u16 host_req_delay); | 2588 | u32 filter, u16 host_req_delay); |
@@ -2542,11 +2593,14 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, | |||
2542 | int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, | 2593 | int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, |
2543 | u16 list_id, u16 filter_id); | 2594 | u16 list_id, u16 filter_id); |
2544 | int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); | 2595 | int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); |
2596 | int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period); | ||
2545 | int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); | 2597 | int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); |
2546 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); | 2598 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); |
2547 | int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); | 2599 | int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); |
2548 | int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, | 2600 | int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, |
2549 | u8 *filter, bool add_filter); | 2601 | u8 *filter, bool add_filter); |
2602 | int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable); | ||
2603 | |||
2550 | /* AP mode uAPSD */ | 2604 | /* AP mode uAPSD */ |
2551 | int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); | 2605 | int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); |
2552 | 2606 | ||