浏览代码

qca-wifi: Add support for noAck frames for TX capture

noACK action frames are generated in response to NDPA
frames.

Change-Id: Ib441041353050e7a4736e1e5830dbfd5d08e0f50
CRs-Fixed: 2622583
Amit Shukla 5 年之前
父节点
当前提交
bc3ff96089
共有 2 个文件被更改,包括 200 次插入1 次删除
  1. 187 1
      dp/wifi3.0/dp_tx_capture.c
  2. 13 0
      dp/wifi3.0/dp_tx_capture.h

+ 187 - 1
dp/wifi3.0/dp_tx_capture.c

@@ -36,6 +36,7 @@
 #define DP_BA_ACK_FRAME_SIZE (sizeof(struct ieee80211_ctlframe_addr2) + 36)
 #define DP_ACK_FRAME_SIZE (sizeof(struct ieee80211_frame_min_one))
 #define DP_CTS_FRAME_SIZE (sizeof(struct ieee80211_frame_min_one))
+#define DP_ACKNOACK_FRAME_SIZE (sizeof(struct ieee80211_frame) + 16)
 #define DP_MAX_MPDU_64 64
 #define DP_NUM_WORDS_PER_PPDU_BITMAP_64 (DP_MAX_MPDU_64 >> 5)
 #define DP_NUM_BYTES_PER_PPDU_BITMAP_64 (DP_MAX_MPDU_64 >> 3)
@@ -47,6 +48,11 @@
 #define INVALID_PPDU_ID 0xFFFF
 #define MAX_END_TSF 0xFFFFFFFF
 
+#define DP_IEEE80211_CATEGORY_VHT (21)
+#define DP_NOACK_SOUNDING_TOKEN_POS (4)
+#define DP_NOACK_STOKEN_POS_SHIFT (2)
+#define DP_NDPA_TOKEN_POS (16)
+
 /* Macros to handle sequence number bitmaps */
 
 /* HW generated rts frame flag */
@@ -3651,7 +3657,9 @@ QDF_STATUS dp_send_ack_frame_to_stack(struct dp_soc *soc,
 		return QDF_STATUS_SUCCESS;
 
 	if (ppdu_info->sw_frame_group_id ==
-	    HAL_MPDU_SW_FRAME_GROUP_MGMT_BEACON)
+	    HAL_MPDU_SW_FRAME_GROUP_MGMT_BEACON ||
+	    ppdu_info->sw_frame_group_id ==
+	    HAL_MPDU_SW_FRAME_GROUP_CTRL_NDPA)
 		return QDF_STATUS_SUCCESS;
 
 	if (ppdu_info->sw_frame_group_id == HAL_MPDU_SW_FRAME_GROUP_MGMT_PROBE_REQ &&
@@ -3771,6 +3779,184 @@ QDF_STATUS dp_send_ack_frame_to_stack(struct dp_soc *soc,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * dp_gen_noack_frame: generate noack Action frame by using parameters
+ *					from received NDPA frame
+ * @ppdu_info: pointer to ppdu_info
+ * @peer: pointer to peer structure
+ * @mpdu_nbuf: buffer for the generated noack frame
+ * @mon_mpdu: mpdu from monitor destination path
+ *
+ * Return: QDF_STATUS
+ */
+static void dp_gen_noack_frame(struct hal_rx_ppdu_info *ppdu_info,
+			       struct dp_peer *peer, qdf_nbuf_t mpdu_nbuf,
+			       qdf_nbuf_t mon_mpdu)
+{
+	struct ieee80211_frame *wh;
+	uint16_t duration;
+	struct dp_vdev *vdev = NULL;
+	char *ndpa_buf = qdf_nbuf_data(mon_mpdu);
+	uint8_t token = 0;
+	uint8_t *frm;
+
+	wh = (struct ieee80211_frame *)qdf_nbuf_data(mpdu_nbuf);
+
+	qdf_mem_zero(((char *)wh), DP_ACKNOACK_FRAME_SIZE);
+
+	wh->i_fc[0] = IEEE80211_FC0_VERSION_0 |
+			IEEE80211_FC0_TYPE_MGT |
+			IEEE80211_FCO_SUBTYPE_ACTION_NO_ACK;
+
+	qdf_mem_copy(wh->i_addr1, &peer->mac_addr.raw[0], QDF_MAC_ADDR_SIZE);
+
+	vdev = peer->vdev;
+	if (vdev) {
+		qdf_mem_copy(wh->i_addr2,
+			     vdev->mac_addr.raw,
+			     QDF_MAC_ADDR_SIZE);
+
+		qdf_mem_copy(wh->i_addr3,
+			     vdev->mac_addr.raw,
+			     QDF_MAC_ADDR_SIZE);
+	}
+
+	duration = (ppdu_info->rx_status.duration > SIFS_INTERVAL) ?
+		    ppdu_info->rx_status.duration - SIFS_INTERVAL : 0;
+	wh->i_dur[0] = duration & 0xff;
+	wh->i_dur[1] = (duration >> 8) & 0xff;
+
+	frm = (uint8_t *)&wh[1];
+	/*
+	 * Update category field
+	 */
+	*frm = DP_IEEE80211_CATEGORY_VHT;
+
+	/*
+	 * Update sounding token obtained from NDPA,
+	 * shift to get upper six bits
+	 */
+	frm += DP_NOACK_SOUNDING_TOKEN_POS;
+
+	token = ndpa_buf[DP_NDPA_TOKEN_POS] >> DP_NOACK_STOKEN_POS_SHIFT;
+
+	*frm = (token) << DP_NOACK_STOKEN_POS_SHIFT;
+
+	qdf_nbuf_set_pktlen(mpdu_nbuf, DP_ACKNOACK_FRAME_SIZE);
+}
+
+/**
+ * dp_send_noack_frame_to_stack: Sends noack Action frame to upper stack
+ *					in response to received NDPA frame.
+ * @soc: SoC handle
+ * @pdev: PDEV pointer
+ * @mon_mpdu: mpdu from monitor destination path
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS dp_send_noack_frame_to_stack(struct dp_soc *soc,
+					struct dp_pdev *pdev,
+					qdf_nbuf_t mon_mpdu)
+{
+	struct hal_rx_ppdu_info *ppdu_info = &pdev->ppdu_info;
+	struct mon_rx_user_status *rx_user_status =
+				&ppdu_info->rx_user_status[0];
+	struct dp_ast_entry *ast_entry;
+	uint32_t peer_id;
+	struct dp_peer *peer;
+	struct cdp_tx_indication_info tx_capture_info;
+
+	if (rx_user_status->ast_index >=
+		wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)) {
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	qdf_spin_lock_bh(&soc->ast_lock);
+	ast_entry = soc->ast_table[rx_user_status->ast_index];
+	if (!ast_entry) {
+		qdf_spin_unlock_bh(&soc->ast_lock);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	peer = ast_entry->peer;
+	if (!peer || peer->peer_ids[0] == HTT_INVALID_PEER) {
+		qdf_spin_unlock_bh(&soc->ast_lock);
+		return QDF_STATUS_E_FAILURE;
+	}
+	peer_id = peer->peer_ids[0];
+	qdf_spin_unlock_bh(&soc->ast_lock);
+
+	peer = dp_peer_find_by_id(soc, peer_id);
+	if (!peer) {
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!dp_peer_or_pdev_tx_cap_enabled(pdev, peer, peer->mac_addr.raw)) {
+		dp_peer_unref_del_find_by_id(peer);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	set_mpdu_info(&tx_capture_info,
+		      &ppdu_info->rx_status, rx_user_status);
+
+	tx_capture_info.mpdu_info.mcs = rx_user_status->mcs;
+	/*
+	 *ppdu_desc is not required for legacy frames
+	 */
+	tx_capture_info.ppdu_desc = NULL;
+
+	tx_capture_info.mpdu_nbuf =
+		qdf_nbuf_alloc(pdev->soc->osdev,
+			       MAX_MONITOR_HEADER +
+			       DP_ACKNOACK_FRAME_SIZE,
+			       MAX_MONITOR_HEADER,
+			       4, FALSE);
+
+	if (!tx_capture_info.mpdu_nbuf) {
+		dp_peer_unref_del_find_by_id(peer);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	dp_gen_noack_frame(ppdu_info, peer,
+			   tx_capture_info.mpdu_nbuf, mon_mpdu);
+
+	dp_peer_unref_del_find_by_id(peer);
+	dp_wdi_event_handler(WDI_EVENT_TX_DATA, pdev->soc,
+			     &tx_capture_info, HTT_INVALID_PEER,
+			     WDI_NO_VAL, pdev->pdev_id);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * dp_handle_tx_capture_from_dest: Handle any TX capture frames from
+ *			monitor destination path.
+ * @soc: SoC handle
+ * @pdev: PDEV pointer
+ * @mon_mpdu: mpdu from monitor destination path
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS dp_handle_tx_capture_from_dest(struct dp_soc *soc,
+					  struct dp_pdev *pdev,
+					  qdf_nbuf_t mon_mpdu)
+{
+	struct hal_rx_ppdu_info *ppdu_info = &pdev->ppdu_info;
+
+	/*
+	 * The below switch case can be extended to
+	 * add more frame types as needed
+	 */
+	switch (ppdu_info->sw_frame_group_id) {
+	case HAL_MPDU_SW_FRAME_GROUP_CTRL_NDPA:
+		return dp_send_noack_frame_to_stack(soc, pdev, mon_mpdu);
+
+	default:
+		break;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * dp_peer_set_tx_capture_enabled: Set tx_cap_enabled bit in peer
  * @pdev: DP PDEV handle

+ 13 - 0
dp/wifi3.0/dp_tx_capture.h

@@ -270,6 +270,19 @@ QDF_STATUS dp_send_ack_frame_to_stack(struct dp_soc *soc,
 				      struct dp_pdev *pdev,
 				      struct hal_rx_ppdu_info *ppdu_info);
 
+/**
+ * dp_handle_tx_capture_from_dest: Handle any TX capture frames from
+ * monitor destination path.
+ * @soc: SoC handle
+ * @pdev: PDEV pointer
+ * @mon_mpdu: mpdu from monitor destination path
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+dp_handle_tx_capture_from_dest(struct dp_soc *soc, struct dp_pdev *pdev,
+			       qdf_nbuf_t mon_mpdu);
+
 /**
  * dp_peer_set_tx_capture_enabled: Set tx_cap_enabled bit in peer
  * @pdev: DP PDEV handle