|
@@ -185,6 +185,48 @@ static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, u8 *mac,
|
|
|
+ u8 vht_enabled, struct sk_buff *skb)
|
|
|
+{
|
|
|
+ struct ieee80211_ht_operation *ht_oper;
|
|
|
+ struct mwifiex_sta_node *sta_ptr;
|
|
|
+ struct mwifiex_bssdescriptor *bss_desc =
|
|
|
+ &priv->curr_bss_params.bss_descriptor;
|
|
|
+ u8 *pos;
|
|
|
+
|
|
|
+ sta_ptr = mwifiex_get_sta_entry(priv, mac);
|
|
|
+ if (unlikely(!sta_ptr)) {
|
|
|
+ dev_warn(priv->adapter->dev,
|
|
|
+ "TDLS peer station not found in list\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);
|
|
|
+ *pos++ = WLAN_EID_HT_OPERATION;
|
|
|
+ *pos++ = sizeof(struct ieee80211_ht_operation);
|
|
|
+ ht_oper = (void *)pos;
|
|
|
+
|
|
|
+ ht_oper->primary_chan = bss_desc->channel;
|
|
|
+
|
|
|
+ /* follow AP's channel bandwidth */
|
|
|
+ if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&
|
|
|
+ bss_desc->bcn_ht_cap &&
|
|
|
+ ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param))
|
|
|
+ ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param;
|
|
|
+
|
|
|
+ if (vht_enabled) {
|
|
|
+ ht_oper->ht_param =
|
|
|
+ mwifiex_get_sec_chan_offset(bss_desc->channel);
|
|
|
+ ht_oper->ht_param |= BIT(2);
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&sta_ptr->tdls_cap.ht_oper, ht_oper,
|
|
|
+ sizeof(struct ieee80211_ht_operation));
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
|
|
|
u8 *mac, struct sk_buff *skb)
|
|
|
{
|
|
@@ -428,6 +470,17 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
|
|
|
dev_kfree_skb_any(skb);
|
|
|
return ret;
|
|
|
}
|
|
|
+ ret = mwifiex_tdls_add_ht_oper(priv, peer, 1, skb);
|
|
|
+ if (ret) {
|
|
|
+ dev_kfree_skb_any(skb);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ ret = mwifiex_tdls_add_ht_oper(priv, peer, 0, skb);
|
|
|
+ if (ret) {
|
|
|
+ dev_kfree_skb_any(skb);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
}
|
|
|
break;
|
|
|
|