aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2015-01-13 09:30:12 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2015-01-15 05:30:41 -0500
commitfbb8f1b729b82f2b48350ffc096f107d1a6ea12d (patch)
treeca95cf6db75e8d4cb17fb2a0af00dbac80d3d980
parent369242b4e3f9d29ddead61895f97a3118484f2f1 (diff)
ath10k: implement support for ap beacon offloading
New firmware revisions support beacon and probe response templates instead. This means SWBA events are no longer delivered for these firmware revisions. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b403cba0afc1..36dde244b95f 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -967,6 +967,143 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
967 return ret; 967 return ret;
968} 968}
969 969
970static int ath10k_mac_setup_bcn_p2p_ie(struct ath10k_vif *arvif,
971 struct sk_buff *bcn)
972{
973 struct ath10k *ar = arvif->ar;
974 struct ieee80211_mgmt *mgmt;
975 const u8 *p2p_ie;
976 int ret;
977
978 if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
979 return 0;
980
981 if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO)
982 return 0;
983
984 mgmt = (void *)bcn->data;
985 p2p_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,
986 mgmt->u.beacon.variable,
987 bcn->len - (mgmt->u.beacon.variable -
988 bcn->data));
989 if (!p2p_ie)
990 return -ENOENT;
991
992 ret = ath10k_wmi_p2p_go_bcn_ie(ar, arvif->vdev_id, p2p_ie);
993 if (ret) {
994 ath10k_warn(ar, "failed to submit p2p go bcn ie for vdev %i: %d\n",
995 arvif->vdev_id, ret);
996 return ret;
997 }
998
999 return 0;
1000}
1001
1002static int ath10k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,
1003 u8 oui_type, size_t ie_offset)
1004{
1005 size_t len;
1006 const u8 *next;
1007 const u8 *end;
1008 u8 *ie;
1009
1010 if (WARN_ON(skb->len < ie_offset))
1011 return -EINVAL;
1012
1013 ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type,
1014 skb->data + ie_offset,
1015 skb->len - ie_offset);
1016 if (!ie)
1017 return -ENOENT;
1018
1019 len = ie[1] + 2;
1020 end = skb->data + skb->len;
1021 next = ie + len;
1022
1023 if (WARN_ON(next > end))
1024 return -EINVAL;
1025
1026 memmove(ie, next, end - next);
1027 skb_trim(skb, skb->len - len);
1028
1029 return 0;
1030}
1031
1032static int ath10k_mac_setup_bcn_tmpl(struct ath10k_vif *arvif)
1033{
1034 struct ath10k *ar = arvif->ar;
1035 struct ieee80211_hw *hw = ar->hw;
1036 struct ieee80211_vif *vif = arvif->vif;
1037 struct ieee80211_mutable_offsets offs = {};
1038 struct sk_buff *bcn;
1039 int ret;
1040
1041 if (!test_bit(WMI_SERVICE_BEACON_OFFLOAD, ar->wmi.svc_map))
1042 return 0;
1043
1044 bcn = ieee80211_beacon_get_template(hw, vif, &offs);
1045 if (!bcn) {
1046 ath10k_warn(ar, "failed to get beacon template from mac80211\n");
1047 return -EPERM;
1048 }
1049
1050 ret = ath10k_mac_setup_bcn_p2p_ie(arvif, bcn);
1051 if (ret) {
1052 ath10k_warn(ar, "failed to setup p2p go bcn ie: %d\n", ret);
1053 kfree_skb(bcn);
1054 return ret;
1055 }
1056
1057 /* P2P IE is inserted by firmware automatically (as configured above)
1058 * so remove it from the base beacon template to avoid duplicate P2P
1059 * IEs in beacon frames.
1060 */
1061 ath10k_mac_remove_vendor_ie(bcn, WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,
1062 offsetof(struct ieee80211_mgmt,
1063 u.beacon.variable));
1064
1065 ret = ath10k_wmi_bcn_tmpl(ar, arvif->vdev_id, offs.tim_offset, bcn, 0,
1066 0, NULL, 0);
1067 kfree_skb(bcn);
1068
1069 if (ret) {
1070 ath10k_warn(ar, "failed to submit beacon template command: %d\n",
1071 ret);
1072 return ret;
1073 }
1074
1075 return 0;
1076}
1077
1078static int ath10k_mac_setup_prb_tmpl(struct ath10k_vif *arvif)
1079{
1080 struct ath10k *ar = arvif->ar;
1081 struct ieee80211_hw *hw = ar->hw;
1082 struct ieee80211_vif *vif = arvif->vif;
1083 struct sk_buff *prb;
1084 int ret;
1085
1086 if (!test_bit(WMI_SERVICE_BEACON_OFFLOAD, ar->wmi.svc_map))
1087 return 0;
1088
1089 prb = ieee80211_proberesp_get(hw, vif);
1090 if (!prb) {
1091 ath10k_warn(ar, "failed to get probe resp template from mac80211\n");
1092 return -EPERM;
1093 }
1094
1095 ret = ath10k_wmi_prb_tmpl(ar, arvif->vdev_id, prb);
1096 kfree_skb(prb);
1097
1098 if (ret) {
1099 ath10k_warn(ar, "failed to submit probe resp template command: %d\n",
1100 ret);
1101 return ret;
1102 }
1103
1104 return 0;
1105}
1106
970static void ath10k_control_beaconing(struct ath10k_vif *arvif, 1107static void ath10k_control_beaconing(struct ath10k_vif *arvif,
971 struct ieee80211_bss_conf *info) 1108 struct ieee80211_bss_conf *info)
972{ 1109{
@@ -3283,6 +3420,18 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
3283 if (ret) 3420 if (ret)
3284 ath10k_warn(ar, "failed to set beacon mode for vdev %d: %i\n", 3421 ath10k_warn(ar, "failed to set beacon mode for vdev %d: %i\n",
3285 arvif->vdev_id, ret); 3422 arvif->vdev_id, ret);
3423
3424 ret = ath10k_mac_setup_bcn_tmpl(arvif);
3425 if (ret)
3426 ath10k_warn(ar, "failed to update beacon template: %d\n",
3427 ret);
3428 }
3429
3430 if (changed & BSS_CHANGED_AP_PROBE_RESP) {
3431 ret = ath10k_mac_setup_prb_tmpl(arvif);
3432 if (ret)
3433 ath10k_warn(ar, "failed to setup probe resp template on vdev %i: %d\n",
3434 arvif->vdev_id, ret);
3286 } 3435 }
3287 3436
3288 if (changed & BSS_CHANGED_BEACON_INFO) { 3437 if (changed & BSS_CHANGED_BEACON_INFO) {
@@ -5130,6 +5279,19 @@ int ath10k_mac_register(struct ath10k *ar)
5130 5279
5131 ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; 5280 ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
5132 5281
5282 if (test_bit(WMI_SERVICE_BEACON_OFFLOAD, ar->wmi.svc_map)) {
5283 ar->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
5284
5285 /* Firmware delivers WPS/P2P Probe Requests frames to driver so
5286 * that userspace (e.g. wpa_supplicant/hostapd) can generate
5287 * correct Probe Responses. This is more of a hack advert..
5288 */
5289 ar->hw->wiphy->probe_resp_offload |=
5290 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
5291 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
5292 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
5293 }
5294
5133 ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; 5295 ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
5134 ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; 5296 ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
5135 ar->hw->wiphy->max_remain_on_channel_duration = 5000; 5297 ar->hw->wiphy->max_remain_on_channel_duration = 5000;