mwifiex: update AP WMM settings from BSS_START event
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / mwifiex / uap_event.c
index 06ce3fe660f138d51873838eda532207d9665004..fee05f5f9343c63db1a6be026a79723def0804ac 100644 (file)
 #include "main.h"
 #include "11n.h"
 
+#define MWIFIEX_BSS_START_EVT_FIX_SIZE    12
 
+static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv,
+                                        struct sk_buff *event)
+{
+       int evt_len;
+       u8 *curr;
+       u16 tlv_len;
+       struct mwifiex_ie_types_data *tlv_hdr;
+       struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
+       int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
+
+       priv->wmm_enabled = false;
+       skb_pull(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
+       evt_len = event->len;
+       curr = event->data;
+
+       mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilties:",
+                        event->data, event->len);
+
+       while ((evt_len >= sizeof(tlv_hdr->header))) {
+               tlv_hdr = (struct mwifiex_ie_types_data *)curr;
+               tlv_len = le16_to_cpu(tlv_hdr->header.len);
+
+               if (evt_len < tlv_len + sizeof(tlv_hdr->header))
+                       break;
+
+               switch (le16_to_cpu(tlv_hdr->header.type)) {
+               case WLAN_EID_HT_CAPABILITY:
+                       priv->ap_11n_enabled = true;
+                       break;
+
+               case WLAN_EID_VHT_CAPABILITY:
+                       priv->ap_11ac_enabled = true;
+                       break;
 
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       /* Point the regular IEEE IE 2 bytes into the Marvell IE
+                        * and setup the IEEE IE type and length byte fields
+                        */
+                       wmm_param_ie = (void *)(curr + 2);
+                       wmm_param_ie->vend_hdr.len = (u8)tlv_len;
+                       wmm_param_ie->vend_hdr.element_id =
+                                               WLAN_EID_VENDOR_SPECIFIC;
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "info: check uap capabilities:\t"
+                                   "wmm parameter set count: %d\n",
+                                   wmm_param_ie->qos_info_bitmap & mask);
+
+                       mwifiex_wmm_setup_ac_downgrade(priv);
+                       priv->wmm_enabled = true;
+                       mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
+                       break;
+
+               default:
+                       break;
+               }
+
+               curr += (tlv_len + sizeof(tlv_hdr->header));
+               evt_len -= (tlv_len + sizeof(tlv_hdr->header));
+       }
+
+       return 0;
+}
 
 /*
  * This function handles AP interface specific events generated by firmware.
@@ -134,6 +196,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                       ETH_ALEN);
                if (priv->hist_data)
                        mwifiex_hist_data_reset(priv);
+               mwifiex_check_uap_capabilties(priv, adapter->event_skb);
                break;
        case EVENT_UAP_MIC_COUNTERMEASURES:
                /* For future development */