|
@@ -182,6 +182,67 @@ 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)
|
|
|
+{
|
|
|
+ struct mwifiex_ie_types_header *tlv;
|
|
|
+ struct mwifiex_tx_pause_tlv *tp_tlv;
|
|
|
+ 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;
|
|
|
+
|
|
|
+ if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
|
|
|
+ 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) {
|
|
|
+ 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 (status == TDLS_SETUP_COMPLETE) {
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
|
|
|
+ tlv_len;
|
|
|
+ tlv = (void *)((u8 *)tlv + tlv_len +
|
|
|
+ sizeof(struct mwifiex_ie_types_header));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* This function handles coex events generated by firmware
|
|
|
*/
|
|
@@ -573,6 +634,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
|
|
|
ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
|
|
|
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");
|
|
|
+ break;
|
|
|
+
|
|
|
case EVENT_TX_STATUS_REPORT:
|
|
|
mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
|
|
|
mwifiex_parse_tx_status_event(priv, adapter->event_body);
|