These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / mwifiex / uap_event.c
index f4794cd..86ff542 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);
+
+       skb_push(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
+
+       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.
@@ -80,8 +144,8 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 
                node = mwifiex_add_sta_entry(priv, event->sta_addr);
                if (!node) {
-                       dev_warn(adapter->dev,
-                                "could not create station entry!\n");
+                       mwifiex_dbg(adapter, ERROR,
+                                   "could not create station entry!\n");
                        return -1;
                }
 
@@ -114,72 +178,73 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                break;
        case EVENT_UAP_BSS_IDLE:
                priv->media_connected = false;
-               if (netif_carrier_ok(priv->netdev))
-                       netif_carrier_off(priv->netdev);
-               mwifiex_stop_net_dev_queue(priv->netdev, adapter);
-
+               priv->port_open = false;
                mwifiex_clean_txrx(priv);
                mwifiex_del_all_sta_list(priv);
                break;
        case EVENT_UAP_BSS_ACTIVE:
                priv->media_connected = true;
-               if (!netif_carrier_ok(priv->netdev))
-                       netif_carrier_on(priv->netdev);
-               mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
+               priv->port_open = true;
                break;
        case EVENT_UAP_BSS_START:
-               dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
+               mwifiex_dbg(adapter, EVENT,
+                           "AP EVENT: event id: %#x\n", eventcause);
+               priv->port_open = false;
                memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
                       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 */
-               dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
+               mwifiex_dbg(adapter, EVENT,
+                           "AP EVENT: event id: %#x\n", eventcause);
                break;
        case EVENT_AMSDU_AGGR_CTRL:
                ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
-               dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl);
+               mwifiex_dbg(adapter, EVENT,
+                           "event: AMSDU_AGGR_CTRL %d\n", ctrl);
 
                if (priv->media_connected) {
                        adapter->tx_buf_size =
                                min_t(u16, adapter->curr_tx_buf_size, ctrl);
-                       dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
-                               adapter->tx_buf_size);
+                       mwifiex_dbg(adapter, EVENT,
+                                   "event: tx_buf_size %d\n",
+                                   adapter->tx_buf_size);
                }
                break;
        case EVENT_ADDBA:
-               dev_dbg(adapter->dev, "event: ADDBA Request\n");
+               mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
                if (priv->media_connected)
                        mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
                                         HostCmd_ACT_GEN_SET, 0,
                                         adapter->event_body, false);
                break;
        case EVENT_DELBA:
-               dev_dbg(adapter->dev, "event: DELBA Request\n");
+               mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
                if (priv->media_connected)
                        mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
                break;
        case EVENT_BA_STREAM_TIEMOUT:
-               dev_dbg(adapter->dev, "event:  BA Stream timeout\n");
+               mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
                if (priv->media_connected) {
                        ba_timeout = (void *)adapter->event_body;
                        mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
                }
                break;
        case EVENT_EXT_SCAN_REPORT:
-               dev_dbg(adapter->dev, "event: EXT_SCAN Report\n");
+               mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
                if (adapter->ext_scan)
                        return mwifiex_handle_event_ext_scan_report(priv,
                                                adapter->event_skb->data);
                break;
        case EVENT_TX_STATUS_REPORT:
-               dev_dbg(adapter->dev, "event: TX_STATUS Report\n");
+               mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
                mwifiex_parse_tx_status_event(priv, adapter->event_body);
                break;
        case EVENT_PS_SLEEP:
-               dev_dbg(adapter->dev, "info: EVENT: SLEEP\n");
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
 
                adapter->ps_state = PS_STATE_PRE_SLEEP;
 
@@ -187,17 +252,19 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_PS_AWAKE:
-               dev_dbg(adapter->dev, "info: EVENT: AWAKE\n");
+               mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
                if (!adapter->pps_uapsd_mode &&
                    priv->media_connected && adapter->sleep_period.period) {
                                adapter->pps_uapsd_mode = true;
-                               dev_dbg(adapter->dev,
-                                       "event: PPS/UAPSD mode activated\n");
+                               mwifiex_dbg(adapter, EVENT,
+                                           "event: PPS/UAPSD mode activated\n");
                }
                adapter->tx_lock_flag = false;
                if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
                        if (mwifiex_check_last_packet_indication(priv)) {
-                               if (adapter->data_sent) {
+                               if (adapter->data_sent ||
+                                   (adapter->if_ops.is_port_ready &&
+                                    !adapter->if_ops.is_port_ready(priv))) {
                                        adapter->ps_state = PS_STATE_AWAKE;
                                        adapter->pm_wakeup_card_req = false;
                                        adapter->pm_wakeup_fw_try = false;
@@ -218,16 +285,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_CHANNEL_REPORT_RDY:
-               dev_dbg(adapter->dev, "event: Channel Report\n");
+               mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
                mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
                break;
        case EVENT_RADAR_DETECTED:
-               dev_dbg(adapter->dev, "event: Radar detected\n");
+               mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
                mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
                break;
+       case EVENT_BT_COEX_WLAN_PARA_CHANGE:
+               dev_err(adapter->dev, "EVENT: BT coex wlan param update\n");
+               mwifiex_bt_coex_wlan_param_update_event(priv,
+                                                       adapter->event_skb);
+               break;
+       case EVENT_TX_DATA_PAUSE:
+               mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
+               mwifiex_process_tx_pause_event(priv, adapter->event_skb);
+               break;
+
+       case EVENT_MULTI_CHAN_INFO:
+               mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
+               mwifiex_process_multi_chan_event(priv, adapter->event_skb);
+               break;
+
        default:
-               dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
-                       eventcause);
+               mwifiex_dbg(adapter, EVENT,
+                           "event: unknown event id: %#x\n", eventcause);
                break;
        }