mwifiex: extend tx_data pause to AP interface as well
authorAvinash Patil <patila@marvell.com>
Mon, 22 Jun 2015 13:36:19 +0000 (19:06 +0530)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 21 Jul 2015 13:40:36 +0000 (16:40 +0300)
This patch adds support to extend TX Data pause for AP intefaces.
Also for station role, support for pausing/unpausing all traffic
when mac address parameter is BSSID is added.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/mwifiex/uap_event.c

index 6f98d7ea93382094d7e7e6ff72393a7e37eb05fe..6e82058c0eab11459189261bb9607d76bc1e709c 100644 (file)
@@ -1554,6 +1554,8 @@ void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
 void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter);
 void mwifiex_11n_delba(struct mwifiex_private *priv, int tid);
 int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy);
+void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
+                                   struct sk_buff *event);
 
 #ifdef CONFIG_DEBUG_FS
 void mwifiex_debugfs_init(void);
index 72be16eca75843b5ab5b440c5ccf293ec172f94c..a2777d16c98ff1fa2e1b0a43c1d468e7a15c7bac 100644 (file)
@@ -237,58 +237,110 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
        return ret;
 }
 
-static void
-mwifiex_process_sta_tx_pause_event(struct mwifiex_private *priv,
-                                  struct sk_buff *event_skb)
+static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv,
+                                        struct mwifiex_ie_types_header *tlv)
 {
-       struct mwifiex_ie_types_header *tlv;
-       struct mwifiex_tx_pause_tlv *tp_tlv;
+       struct mwifiex_tx_pause_tlv *tp;
        struct mwifiex_sta_node *sta_ptr;
        unsigned long flags;
-       u16 tlv_type, tlv_len;
-       int tlv_buf_left, status;
 
-       if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
-               return;
+       tp = (void *)tlv;
+       mwifiex_dbg(priv->adapter, EVENT,
+                   "uap tx_pause: %pM pause=%d, pkts=%d\n",
+                   tp->peermac, tp->tx_pause,
+                   tp->pkt_cnt);
+
+       if (ether_addr_equal(tp->peermac, priv->netdev->dev_addr)) {
+               if (tp->tx_pause)
+                       priv->port_open = false;
+               else
+                       priv->port_open = true;
+       } else if (is_multicast_ether_addr(tp->peermac)) {
+               mwifiex_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause);
+       } else {
+               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+               sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
+               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+               if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
+                       sta_ptr->tx_pause = tp->tx_pause;
+                       mwifiex_update_ralist_tx_pause(priv, tp->peermac,
+                                                      tp->tx_pause);
+               }
+       }
+}
+
+static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv,
+                                        struct mwifiex_ie_types_header *tlv)
+{
+       struct mwifiex_tx_pause_tlv *tp;
+       struct mwifiex_sta_node *sta_ptr;
+       int status;
+       unsigned long flags;
+
+       tp = (void *)tlv;
+       mwifiex_dbg(priv->adapter, EVENT,
+                   "sta tx_pause: %pM pause=%d, pkts=%d\n",
+                   tp->peermac, tp->tx_pause,
+                   tp->pkt_cnt);
+
+       if (ether_addr_equal(tp->peermac, priv->cfg_bssid)) {
+               if (tp->tx_pause)
+                       priv->port_open = false;
+               else
+                       priv->port_open = true;
+       } else {
+               if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+                       return;
+
+               status = mwifiex_get_tdls_link_status(priv, tp->peermac);
+               if (mwifiex_is_tdls_link_setup(status)) {
+                       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+                       sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
+                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+                       if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
+                               sta_ptr->tx_pause = tp->tx_pause;
+                               mwifiex_update_ralist_tx_pause(priv,
+                                                              tp->peermac,
+                                                              tp->tx_pause);
+                       }
+               }
+       }
+}
+
+void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
+                                   struct sk_buff *event_skb)
+{
+       struct mwifiex_ie_types_header *tlv;
+       u16 tlv_type, tlv_len;
+       int tlv_buf_left;
 
-       if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
+       if (!priv->media_connected) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tx_pause event while disconnected; bss_role=%d\n",
+                           priv->bss_role);
                return;
+       }
 
        tlv_buf_left = event_skb->len - sizeof(u32);
        tlv = (void *)event_skb->data + sizeof(u32);
+
        while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
                tlv_type = le16_to_cpu(tlv->type);
                tlv_len  = le16_to_cpu(tlv->len);
                if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
-                  tlv_buf_left) {
+                   tlv_buf_left) {
                        mwifiex_dbg(priv->adapter, ERROR,
                                    "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
                                    tlv_len, tlv_buf_left);
                        break;
                }
                if (tlv_type == TLV_TYPE_TX_PAUSE) {
-                       tp_tlv = (void *)tlv;
-                       mwifiex_dbg(priv->adapter, ERROR,
-                                   "TxPause: %pM pause=%d, pkts=%d\n",
-                                   tp_tlv->peermac, tp_tlv->tx_pause,
-                                   tp_tlv->pkt_cnt);
-                       status = mwifiex_get_tdls_link_status
-                                       (priv,  tp_tlv->peermac);
-                       if (mwifiex_is_tdls_link_setup(status)) {
-                               spin_lock_irqsave(&priv->sta_list_spinlock,
-                                                 flags);
-                               sta_ptr = mwifiex_get_sta_entry
-                                               (priv, tp_tlv->peermac);
-                               spin_unlock_irqrestore(&priv->sta_list_spinlock,
-                                                      flags);
-                               if (sta_ptr && sta_ptr->tx_pause !=
-                                                            tp_tlv->tx_pause) {
-                                       sta_ptr->tx_pause = tp_tlv->tx_pause;
-                                       mwifiex_update_ralist_tx_pause
-                                               (priv, tp_tlv->peermac,
-                                                tp_tlv->tx_pause);
-                               }
-                       }
+                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
+                               mwifiex_process_sta_tx_pause(priv, tlv);
+                       else
+                               mwifiex_process_uap_tx_pause(priv, tlv);
                }
 
                tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
@@ -296,6 +348,7 @@ mwifiex_process_sta_tx_pause_event(struct mwifiex_private *priv,
                tlv = (void *)((u8 *)tlv + tlv_len +
                               sizeof(struct mwifiex_ie_types_header));
        }
+
 }
 
 /*
@@ -691,8 +744,8 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
 
        case EVENT_TX_DATA_PAUSE:
-               mwifiex_process_sta_tx_pause_event(priv, adapter->event_skb);
                mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
+               mwifiex_process_tx_pause_event(priv, adapter->event_skb);
                break;
 
        case EVENT_TX_STATUS_REPORT:
index a412c3d4c365296cf534cba0c2b34d486a9ab20e..a9d34c619181354bbe0b01a1567291e6178a33a6 100644 (file)
@@ -300,6 +300,10 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                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;
        default:
                mwifiex_dbg(adapter, EVENT,
                            "event: unknown event id: %#x\n", eventcause);