Browse Source

qcacmn: Setting up filters and destination ring for CBF logging

This change will set up monitor mode status and destination ring
filters for enbale CBF logging and will enable destination ring to
capture CBF frame. This change will get the CBF frame from the
destination ring and send it to the pktlog module for post processing
through WDI event. CBF is a compressed beamforming report.

Change-Id: I4cc419440ba8d60446dd1f01747340a89f023171
Vijay Krishnan 4 years ago
parent
commit
4427314322

+ 1 - 0
dp/inc/cdp_txrx_stats_struct.h

@@ -366,6 +366,7 @@ enum WDI_EVENT {
 	WDI_EVENT_PKT_CAPTURE_TX_DATA,
 	WDI_EVENT_PKT_CAPTURE_RX_DATA,
 	WDI_EVENT_PKT_CAPTURE_OFFLOAD_TX_DATA,
+	WDI_EVENT_RX_CBF,
 	/* End of new event items */
 	WDI_EVENT_LAST
 };

+ 61 - 0
dp/wifi3.0/dp_htt.c

@@ -466,6 +466,67 @@ dp_tx_stats_update(struct dp_pdev *pdev, struct dp_peer *peer,
 }
 #endif
 
+QDF_STATUS dp_rx_populate_cbf_hdr(struct dp_soc *soc,
+				  uint32_t mac_id,
+				  uint32_t event,
+				  qdf_nbuf_t mpdu,
+				  uint32_t msdu_timestamp)
+{
+	uint32_t data_size, hdr_size, ppdu_id;
+	struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id);
+	uint32_t *msg_word;
+
+	if (!pdev)
+		return QDF_STATUS_E_INVAL;
+
+	ppdu_id = pdev->ppdu_info.com_info.ppdu_id;
+
+	hdr_size = HTT_T2H_PPDU_STATS_IND_HDR_SIZE
+		+ sizeof(htt_ppdu_stats_tx_mgmtctrl_payload_tlv);
+
+	data_size = qdf_nbuf_len(mpdu);
+
+	qdf_nbuf_push_head(mpdu, hdr_size);
+
+	msg_word = (uint32_t *)qdf_nbuf_data(mpdu);
+	/*
+	 * Populate the PPDU Stats Indication header
+	 */
+	HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_T2H_MSG_TYPE_PPDU_STATS_IND);
+	HTT_T2H_PPDU_STATS_MAC_ID_SET(*msg_word, mac_id);
+	HTT_T2H_PPDU_STATS_PDEV_ID_SET(*msg_word, pdev->pdev_id);
+	HTT_T2H_PPDU_STATS_PAYLOAD_SIZE_SET(*msg_word, data_size +
+		qdf_offsetof(htt_ppdu_stats_tx_mgmtctrl_payload_tlv, payload));
+	msg_word++;
+	HTT_T2H_PPDU_STATS_PPDU_ID_SET(*msg_word, ppdu_id);
+	msg_word++;
+
+	*msg_word = msdu_timestamp;
+	msg_word++;
+	/*
+	 * Populate MGMT_CTRL Payload TLV first
+	 */
+	HTT_STATS_TLV_TAG_SET(*msg_word,
+			      HTT_PPDU_STATS_TX_MGMTCTRL_PAYLOAD_TLV);
+	HTT_STATS_TLV_LENGTH_SET(*msg_word,
+				 data_size - sizeof(htt_tlv_hdr_t) +
+				 qdf_offsetof(
+				 htt_ppdu_stats_tx_mgmtctrl_payload_tlv,
+				 payload));
+	msg_word++;
+
+	HTT_PPDU_STATS_TX_MGMTCTRL_TLV_FRAME_LENGTH_SET(
+		*msg_word, data_size);
+	msg_word++;
+
+	dp_wdi_event_handler(event, soc, (void *)mpdu,
+			     HTT_INVALID_PEER, WDI_NO_VAL, pdev->pdev_id);
+
+	qdf_nbuf_pull_head(mpdu, hdr_size);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 #ifdef WLAN_TX_PKT_CAPTURE_ENH
 #include "dp_tx_capture.h"
 #else

+ 88 - 36
dp/wifi3.0/dp_main.c

@@ -7546,6 +7546,59 @@ fail0:
 	return QDF_STATUS_E_FAILURE;
 }
 
+/**
+ * dp_vdev_set_monitor_mode_buf_rings () - set monitor mode buf rings
+ *
+ * Allocate SW descriptor pool, buffers, link descriptor memory
+ * Initialize monitor related SRNGs
+ *
+ * @pdev: DP pdev object
+ *
+ * Return: void
+ */
+static void dp_vdev_set_monitor_mode_buf_rings(struct dp_pdev *pdev)
+{
+	uint32_t mac_id;
+	uint32_t mac_for_pdev;
+	struct dp_srng *mon_buf_ring;
+	uint32_t num_entries;
+	struct dp_soc *soc = pdev->soc;
+
+	dp_soc_config_full_mon_mode(pdev, DP_FULL_MON_ENABLE);
+
+	/* If delay monitor replenish is disabled, allocate link descriptor
+	 * monitor ring buffers of ring size.
+	 */
+	if (!wlan_cfg_is_delay_mon_replenish(soc->wlan_cfg_ctx)) {
+		dp_vdev_set_monitor_mode_rings(pdev, false);
+	} else {
+		for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) {
+			mac_for_pdev =
+				dp_get_lmac_id_for_pdev_id(pdev->soc,
+							   mac_id,
+							   pdev->pdev_id);
+
+			dp_rx_pdev_mon_buf_buffers_alloc(pdev, mac_for_pdev,
+							 FALSE);
+			mon_buf_ring =
+				&pdev->soc->rxdma_mon_buf_ring[mac_for_pdev];
+			/*
+			 * Configure low interrupt threshld when monitor mode is
+			 * configured.
+			 */
+			if (mon_buf_ring->hal_srng) {
+				num_entries = mon_buf_ring->num_entries;
+				hal_set_low_threshold(mon_buf_ring->hal_srng,
+						      num_entries >> 3);
+				htt_srng_setup(pdev->soc->htt_handle,
+					       pdev->pdev_id,
+					       mon_buf_ring->hal_srng,
+					       RXDMA_MONITOR_BUF);
+			}
+		}
+	}
+}
+
 /**
  * dp_vdev_set_monitor_mode() - Set DP VDEV to monitor mode
  * @vdev_handle: Datapath VDEV handle
@@ -7558,11 +7611,7 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *dp_soc,
 					   uint8_t special_monitor)
 {
 	struct dp_soc *soc = (struct dp_soc *)dp_soc;
-	uint32_t mac_id;
-	uint32_t mac_for_pdev;
 	struct dp_pdev *pdev;
-	uint32_t num_entries;
-	struct dp_srng *mon_buf_ring;
 	struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id,
 						     DP_MOD_ID_CDP);
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -7597,38 +7646,7 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *dp_soc,
 	}
 
 	pdev->monitor_configured = true;
-
-	dp_soc_config_full_mon_mode(pdev, DP_FULL_MON_ENABLE);
-
-	/* If delay monitor replenish is disabled, allocate link descriptor
-	 * monitor ring buffers of ring size.
-	 */
-	if (!wlan_cfg_is_delay_mon_replenish(soc->wlan_cfg_ctx)) {
-		dp_vdev_set_monitor_mode_rings(pdev, false);
-	} else {
-		for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) {
-			mac_for_pdev = dp_get_lmac_id_for_pdev_id(pdev->soc,
-								  mac_id,
-								  pdev->pdev_id);
-
-			dp_rx_pdev_mon_buf_buffers_alloc(pdev, mac_for_pdev,
-							 FALSE);
-			mon_buf_ring = &pdev->soc->rxdma_mon_buf_ring[mac_for_pdev];
-			/*
-			 * Configure low interrupt threshld when monitor mode is
-			 * configured.
-			 */
-			if (mon_buf_ring->hal_srng) {
-				num_entries = mon_buf_ring->num_entries;
-				hal_set_low_threshold(mon_buf_ring->hal_srng,
-						      num_entries >> 3);
-				htt_srng_setup(pdev->soc->htt_handle,
-					       pdev->pdev_id,
-					       mon_buf_ring->hal_srng,
-					       RXDMA_MONITOR_BUF);
-			}
-		}
-	}
+	dp_vdev_set_monitor_mode_buf_rings(pdev);
 
 	dp_mon_filter_setup_mon_mode(pdev);
 	status = dp_mon_filter_update(pdev);
@@ -12925,6 +12943,40 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event,
 			}
 			break;
 
+		case WDI_EVENT_RX_CBF:
+			if (pdev->monitor_vdev) {
+				/* Nothing needs to be done if monitor mode is
+				 * enabled
+				 */
+				dp_info("Monitor mode, CBF setting filters");
+				pdev->rx_pktlog_cbf = true;
+				return 0;
+			}
+			if (!pdev->rx_pktlog_cbf) {
+				pdev->rx_pktlog_cbf = true;
+
+				dp_vdev_set_monitor_mode_buf_rings(pdev);
+				/*
+				 * Set the packet log lite mode filter.
+				 */
+				qdf_info("Non monitor mode: Enable destination ring");
+				dp_mon_filter_setup_rx_pkt_log_cbf(pdev);
+				if (dp_mon_filter_update(pdev) !=
+				    QDF_STATUS_SUCCESS) {
+					dp_err("Pktlog set CBF filters failed");
+					dp_mon_filter_reset_rx_pktlog_cbf(pdev);
+					pdev->rx_pktlog_mode =
+						DP_RX_PKTLOG_DISABLED;
+					return 0;
+				}
+
+				if (soc->reap_timer_init &&
+				    !dp_is_enable_reap_timer_non_pkt(pdev))
+					qdf_timer_mod(&soc->mon_reap_timer,
+						      DP_INTR_POLL_TIMER_MS);
+			}
+			break;
+
 		default:
 			/* Nothing needs to be done for other pktlog types */
 			break;

+ 130 - 0
dp/wifi3.0/dp_mon_filter.c

@@ -501,6 +501,64 @@ static void dp_mon_filter_set_status_cmn(struct dp_pdev *pdev,
 	}
 }
 
+/**
+ * dp_mon_filter_set_status_cbf() - Set the cbf status filters
+ * @pdev: DP pdev handle
+ * @filter: Dp mon filters
+ *
+ * Return: void
+ */
+static void dp_mon_filter_set_status_cbf(struct dp_pdev *pdev,
+					 struct dp_mon_filter *filter)
+{
+	filter->tlv_filter.mpdu_start = 1;
+	filter->tlv_filter.msdu_start = 0;
+	filter->tlv_filter.packet = 0;
+	filter->tlv_filter.msdu_end = 0;
+	filter->tlv_filter.mpdu_end = 0;
+	filter->tlv_filter.attention = 0;
+	filter->tlv_filter.ppdu_start = 1;
+	filter->tlv_filter.ppdu_end = 1;
+	filter->tlv_filter.ppdu_end_user_stats = 1;
+	filter->tlv_filter.ppdu_end_user_stats_ext = 1;
+	filter->tlv_filter.ppdu_end_status_done = 1;
+	filter->tlv_filter.enable_fp = 1;
+	filter->tlv_filter.enable_md = 0;
+	filter->tlv_filter.fp_mgmt_filter = FILTER_MGMT_ACT_NO_ACK;
+	filter->tlv_filter.fp_ctrl_filter = 0;
+	filter->tlv_filter.fp_data_filter = 0;
+	filter->tlv_filter.offset_valid = false;
+	filter->tlv_filter.enable_mo = 0;
+}
+
+/**
+ * dp_mon_filter_set_cbf_cmn() - Set the common cbf mode filters
+ * @pdev: DP pdev handle
+ * @filter: Dp mon filters
+ *
+ * Return: void
+ */
+static void dp_mon_filter_set_cbf_cmn(struct dp_pdev *pdev,
+				      struct dp_mon_filter *filter)
+{
+	filter->tlv_filter.mpdu_start = 1;
+	filter->tlv_filter.msdu_start = 1;
+	filter->tlv_filter.packet = 1;
+	filter->tlv_filter.msdu_end = 1;
+	filter->tlv_filter.mpdu_end = 1;
+	filter->tlv_filter.attention = 1;
+	filter->tlv_filter.ppdu_start = 0;
+	filter->tlv_filter.ppdu_end =  0;
+	filter->tlv_filter.ppdu_end_user_stats = 0;
+	filter->tlv_filter.ppdu_end_user_stats_ext = 0;
+	filter->tlv_filter.ppdu_end_status_done = 0;
+	filter->tlv_filter.enable_fp = 1;
+	filter->tlv_filter.enable_md = 0;
+	filter->tlv_filter.fp_mgmt_filter = FILTER_MGMT_ACT_NO_ACK;
+	filter->tlv_filter.offset_valid = false;
+	filter->tlv_filter.enable_mo = 0;
+}
+
 #ifdef FEATURE_PERPKT_INFO
 /**
  * dp_mon_filter_setup_enhanced_stats() - Setup the enhanced stats filter
@@ -967,6 +1025,78 @@ void dp_mon_filter_reset_rx_pkt_log_lite(struct dp_pdev *pdev)
 
 	pdev->filter[mode][srng_type] = filter;
 }
+
+/**
+ * dp_mon_filter_setup_rx_pkt_log_cbf() - Setup the Rx pktlog CBF mode filter
+ * @pdev: DP pdev handle
+ */
+void dp_mon_filter_setup_rx_pkt_log_cbf(struct dp_pdev *pdev)
+{
+	struct dp_mon_filter filter = {0};
+	struct dp_soc *soc = NULL;
+	enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_CBF_MODE;
+	enum dp_mon_filter_srng_type srng_type =
+				DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS;
+
+	if (!pdev) {
+		dp_mon_filter_err("pdev Context is null");
+		return;
+	}
+
+	soc = pdev->soc;
+	if (!soc) {
+		dp_mon_filter_err("Soc Context is null");
+		return;
+	}
+
+	/* Enabled the filter */
+	filter.valid = true;
+	dp_mon_filter_set_status_cbf(pdev, &filter);
+	dp_mon_filter_show_filter(pdev, mode, &filter);
+	pdev->filter[mode][srng_type] = filter;
+
+	filter.valid = true;
+	dp_mon_filter_set_cbf_cmn(pdev, &filter);
+	dp_mon_filter_show_filter(pdev, mode, &filter);
+
+	srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ?
+			DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF :
+			DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF);
+	pdev->filter[mode][srng_type] = filter;
+}
+
+/**
+ * dp_mon_filter_reset_rx_pktlog_cbf() - Reset the Rx pktlog CBF mode filter
+ * @pdev: DP pdev handle
+ */
+void dp_mon_filter_reset_rx_pktlog_cbf(struct dp_pdev *pdev)
+{
+	struct dp_mon_filter filter = {0};
+	struct dp_soc *soc = NULL;
+	enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_CBF_MODE;
+	enum dp_mon_filter_srng_type srng_type =
+				DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF;
+	if (!pdev) {
+		QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR,
+			  FL("pdev Context is null"));
+		return;
+	}
+
+	soc = pdev->soc;
+	if (!soc) {
+		QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR,
+			  FL("Soc Context is null"));
+		return;
+	}
+
+	srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ?
+			DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF :
+			DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF);
+	pdev->filter[mode][srng_type] = filter;
+
+	srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS;
+	pdev->filter[mode][srng_type] = filter;
+}
 #endif /* WDI_EVENT_ENABLE */
 
 #ifdef WLAN_DP_RESET_MON_BUF_RING_FILTER

+ 15 - 1
dp/wifi3.0/dp_mon_filter.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -121,6 +121,7 @@ enum dp_mon_filter_mode {
 #ifdef WDI_EVENT_ENABLE
 	DP_MON_FILTER_PKT_LOG_FULL_MODE,
 	DP_MON_FILTER_PKT_LOG_LITE_MODE,
+	DP_MON_FILTER_PKT_LOG_CBF_MODE,
 #endif /* WDI_EVENT_ENABLE */
 	DP_MON_FILTER_MAX_MODE
 };
@@ -242,6 +243,19 @@ void dp_mon_filter_setup_rx_pkt_log_lite(struct dp_pdev *pdev);
  * @pdev: DP pdev handle
  */
 void dp_mon_filter_reset_rx_pkt_log_lite(struct dp_pdev *pdev);
+
+/**
+ * dp_mon_filter_setup_rx_pkt_log_cbf() - Setup the Rx pktlog cbf mode filter
+ * in the radio object.
+ * @pdev: DP pdev handle
+ */
+void dp_mon_filter_setup_rx_pkt_log_cbf(struct dp_pdev *pdev);
+
+/**
+ * dp_mon_filter_reset_rx_pktlog_cbf() - Reset the Rx pktlog cbf mode filter
+ * @pdev: DP pdev handle
+ */
+void dp_mon_filter_reset_rx_pktlog_cbf(struct dp_pdev *pdev);
 #endif /* WDI_EVENT_ENABLE */
 
 /**

+ 15 - 1
dp/wifi3.0/dp_rx_mon.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -142,6 +142,20 @@ dp_rx_pdev_mon_buf_desc_pool_alloc(struct dp_pdev *pdev, uint32_t mac_id);
 void
 dp_rx_pdev_mon_buf_desc_pool_init(struct dp_pdev *pdev, uint32_t mac_id);
 
+/*
+ * dp_rx_populate_cbf_hdr - Send CBF frame with htt header
+ * @soc: Datapath soc handle
+ * @mac_id: Datapath mac id
+ * @event: WDI event
+ * @mpdu: mpdu buffer
+ * @msdu_timesstamp: time stamp
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS dp_rx_populate_cbf_hdr(struct dp_soc *soc,
+				  uint32_t mac_id, uint32_t event,
+				  qdf_nbuf_t data, uint32_t msdu_timestamp);
+
 /**
  * dp_rx_mon_handle_status_buf_done () - Handle DMA not done case for
  * monitor status ring

+ 63 - 0
dp/wifi3.0/dp_rx_mon_dest.c

@@ -29,6 +29,11 @@
 #include "wlan_cfg.h"
 #include "dp_internal.h"
 #include "dp_rx_buffer_pool.h"
+
+#ifndef IEEE80211_FCO_SUBTYPE_ACTION_NO_ACK
+#define IEEE80211_FCO_SUBTYPE_ACTION_NO_ACK 0xe0
+#endif
+
 #ifdef WLAN_TX_PKT_CAPTURE_ENH
 #include "dp_rx_mon_feature.h"
 
@@ -1411,6 +1416,62 @@ void dp_rx_mon_rssi_convert(struct mon_rx_status *rx_status)
 }
 #endif
 
+/*
+ * dp_rx_mon_process_dest_pktlog(): function to log packet contents to
+ * pktlog buffer and send to pktlog module
+ * @soc: DP soc
+ * @mac_id: MAC ID
+ * @mpdu: MPDU buf
+ * Return: status: 0 - Success, non-zero: Failure
+ */
+static QDF_STATUS dp_rx_mon_process_dest_pktlog(struct dp_soc *soc,
+						uint32_t mac_id,
+						qdf_nbuf_t mpdu)
+{
+	uint32_t event, msdu_timestamp;
+	struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id);
+	void *data;
+	struct ieee80211_frame *wh;
+	uint8_t type, subtype;
+#ifdef NO_RX_PKT_HDR_TLV
+	struct rx_mon_pkt_tlvs *rx_tlv;
+#else
+	struct rx_pkt_tlvs *rx_tlv;
+#endif
+	struct rx_msdu_start_tlv *msdu_start_tlv;
+
+	if (!pdev)
+		return QDF_STATUS_E_INVAL;
+
+	if (pdev->rx_pktlog_cbf) {
+		data = qdf_nbuf_data(mpdu);
+		rx_tlv = data - SIZE_OF_MONITOR_TLV;
+
+		/* CBF logging required, doesn't matter if it is a full mode
+		 * or lite mode.
+		 * Need to look for mpdu with:
+		 * TYPE = ACTION, SUBTYPE = NO ACK in the header
+		 */
+		event = WDI_EVENT_RX_CBF;
+
+		msdu_start_tlv = &rx_tlv->msdu_start_tlv;
+		msdu_timestamp =
+			msdu_start_tlv->rx_msdu_start.ppdu_start_timestamp;
+
+		wh = (struct ieee80211_frame *)data;
+
+		type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+		subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+		if (type == IEEE80211_FC0_TYPE_MGT &&
+		    subtype == IEEE80211_FCO_SUBTYPE_ACTION_NO_ACK)
+			dp_rx_populate_cbf_hdr(soc,
+					       mac_id, event,
+					       mpdu,
+					       msdu_timestamp);
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
 /*
  * dp_rx_mon_deliver(): function to deliver packets to stack
  * @soc: DP soc
@@ -1441,6 +1502,8 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id,
 		goto mon_deliver_fail;
 	}
 
+	dp_rx_mon_process_dest_pktlog(soc, mac_id, mon_mpdu);
+
 	/* monitor vap cannot be present when mcopy is enabled
 	 * hence same skb can be consumed
 	 */

+ 2 - 0
dp/wifi3.0/dp_types.h

@@ -2163,6 +2163,8 @@ struct dp_pdev {
 
 	/* Packet log mode */
 	uint8_t rx_pktlog_mode;
+	/* Enable pktlog logging cbf */
+	bool rx_pktlog_cbf;
 
 	/* WDI event handlers */
 	struct wdi_event_subscribe_t **wdi_event_list;

+ 16 - 1
umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main_i.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -37,6 +37,21 @@
 #define IEEE80211_FC0_SUBTYPE_MASK          0xf0
 #define IEEE80211_FC0_TYPE_MGT              0x00
 
+/* for TYPE_MGT */
+#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ     0x00
+#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP    0x10
+#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ   0x20
+#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP  0x30
+#define IEEE80211_FC0_SUBTYPE_PROBE_REQ     0x40
+#define IEEE80211_FC0_SUBTYPE_PROBE_RESP    0x50
+#define IEEE80211_FC0_SUBTYPE_BEACON        0x80
+#define IEEE80211_FC0_SUBTYPE_ATIM          0x90
+#define IEEE80211_FC0_SUBTYPE_DISASSOC      0xa0
+#define IEEE80211_FC0_SUBTYPE_AUTH          0xb0
+#define IEEE80211_FC0_SUBTYPE_DEAUTH        0xc0
+#define IEEE80211_FC0_SUBTYPE_ACTION        0xd0
+#define IEEE80211_FCO_SUBTYPE_ACTION_NO_ACK 0xe0
+
 /**
  * mgmt_wakelock_reason - reasons mgmt_txrx might hold a wakelock
  * @MGMT_TXRX_WAKELOCK_REASON_TX_CMP - wait for mgmt_tx_complete event