All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/6] ath11k: add monitor mode support
@ 2019-04-16  0:12 Miles Hu
  2019-04-16  0:12 ` [PATCH v5 1/6] ath11k: init/deinit monitor rings Miles Hu
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Miles Hu @ 2019-04-16  0:12 UTC (permalink / raw)
  To: ath11k; +Cc: Miles Hu

Adding monitor mode in ath11k. It can be enabled
 by commands below:

  ifconfig wlan0 down
  iw wlan0 set type monitor
  ifconfig wlan0 up

change channel:
  iw wlan0 set freq 5805 80 5775

Change summary:
1. create monitor status/destination/buffer/link descriptor rings.
2. enable these rings and push ring filters to buffer/status rings.
3. add napi entry point for monitor status and destination rings process.
4. implement monitor status/buffer rings replenish.
5. process entries from the status ring to get ppdu id and tlv status.
6. process entries from the destination ring by comparing ppdu id to build
    msdu list.
7. merge msdu list to mpdu and copy rx status to cb.
8. deliver mpdu to upper layer.

Known issues:
 - Coexist with other interface type (AP/STA) not fully supported.
 - higher data rates (11ax) not supported. radiotap needs proper info.
 - signal strength and rate idx not accurate in some packets.

-Miles Hu

Miles Hu (6):
  ath11k: init/deinit monitor rings
  ath11k: monitor filter set function
  ath11k: htt setup monitor rings
  ath11k: monitor mode attach/detach
  ath11k: enable/disable monitor mode and destination ring entry process
  ath11k: merge msdu tlv process and status/destination ring process

V2:
 - correct wrong indent and style.
 - change function return value to bool.
 - remove redundent code.
 - correct warn message style and remove __func__ and __LINE__.
 - remove likely and unlikely functions.

V3:
 - create common ring reap function for peer-stats and monitor mode.

V4:
 - change bool to atomic_t to add protection
 - remove unnecessary print

V5:
 - replace atomic_t by atomic bitmask

 drivers/net/wireless/ath/ath11k/core.h     |   8 +-
 drivers/net/wireless/ath/ath11k/dp.c       | 110 ++--
 drivers/net/wireless/ath/ath11k/dp.h       | 189 +++++-
 drivers/net/wireless/ath/ath11k/dp_rx.c    | 917 ++++++++++++++++++++++++++---
 drivers/net/wireless/ath/ath11k/dp_rx.h    |  61 +-
 drivers/net/wireless/ath/ath11k/dp_tx.c    | 193 +++---
 drivers/net/wireless/ath/ath11k/dp_tx.h    |   1 +
 drivers/net/wireless/ath/ath11k/hal.c      |   2 +-
 drivers/net/wireless/ath/ath11k/hal_desc.h |   3 +
 drivers/net/wireless/ath/ath11k/hal_rx.c   |  28 +
 drivers/net/wireless/ath/ath11k/hal_rx.h   |  17 +
 drivers/net/wireless/ath/ath11k/mac.c      |  40 +-
 drivers/net/wireless/ath/ath11k/rx_desc.h  |   1 +
 13 files changed, 1360 insertions(+), 210 deletions(-)

-- 
2.7.4


_______________________________________________
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v5 1/6] ath11k: init/deinit monitor rings
  2019-04-16  0:12 [PATCH v5 0/6] ath11k: add monitor mode support Miles Hu
@ 2019-04-16  0:12 ` Miles Hu
  2019-04-16  0:12 ` [PATCH v5 2/6] ath11k: monitor filter set function Miles Hu
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Miles Hu @ 2019-04-16  0:12 UTC (permalink / raw)
  To: ath11k; +Cc: Miles Hu

extend ring setup/cleanup to generic functions.
init/deinit monitor status/buffer/destination/link rings.
more htt filters for monitor mode.

Signed-off-by: Miles Hu <milehu@codeaurora.org>
---
V2:
 - correct wrong indent and style.

V4:
 - change bool to atomic_t to add protection

V5:
 - replace atomic_t by atomic bitmask

 drivers/net/wireless/ath/ath11k/core.h     |   8 +-
 drivers/net/wireless/ath/ath11k/dp.c       | 110 +++++++++--------
 drivers/net/wireless/ath/ath11k/dp.h       | 189 ++++++++++++++++++++++++++---
 drivers/net/wireless/ath/ath11k/dp_tx.h    |   1 +
 drivers/net/wireless/ath/ath11k/hal_desc.h |   3 +
 drivers/net/wireless/ath/ath11k/hal_rx.h   |  17 +++
 drivers/net/wireless/ath/ath11k/rx_desc.h  |   1 +
 7 files changed, 261 insertions(+), 68 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index f6fecd8..cd362a2 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -70,6 +70,7 @@ struct ath11k_skb_rxcb {
 	u8 err_rel_src;
 	u8 err_code;
 	u8 mac_id;
+	u8 unmapped;
 };
 
 enum ath11k_hw_rev {
@@ -165,6 +166,10 @@ enum ath11k_dev_flags {
 	ATH11K_FLAG_REGISTERED,
 };
 
+enum ath11k_monitor_flags {
+	ATH11K_FLAG_MONITOR_ENABLED,
+};
+
 struct ath11k_vif {
 	u32 vdev_id;
 	enum wmi_vdev_type vdev_type;
@@ -434,8 +439,8 @@ struct ath11k {
 	struct {
 		struct ieee80211_supported_band sbands[NUM_NL80211_BANDS];
 	} mac;
-	unsigned long dev_flags;
 	unsigned int filter_flags;
+	unsigned long monitor_flags;
 	u32 min_tx_power;
 	u32 max_tx_power;
 	u32 txpower_limit_2g;
@@ -444,7 +449,6 @@ struct ath11k {
 	u32 power_scale;
 	u32 chan_tx_pwr;
 	u32 max_num_stations;
-	bool monitor_enabled;
 	bool monitor_present;
 	struct mutex conf_mutex;
 	spinlock_t data_lock;
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index 127eb56..5fa01c1 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -405,10 +405,10 @@ static int ath11k_dp_scatter_idle_link_desc_setup(struct ath11k_base *ab,
 	return ret;
 }
 
-static void ath11k_dp_link_desc_bank_free(struct ath11k_base *ab)
+static void
+ath11k_dp_link_desc_bank_free(struct ath11k_base *ab,
+			      struct dp_link_desc_bank *link_desc_banks)
 {
-	struct ath11k_dp *dp = &ab->dp;
-	struct dp_link_desc_bank *link_desc_banks = dp->link_desc_banks;
 	int i;
 
 	for (i = 0; i < DP_LINK_DESC_BANKS_MAX; i++) {
@@ -427,6 +427,7 @@ static int ath11k_dp_link_desc_bank_alloc(struct ath11k_base *ab,
 					  int n_link_desc_bank,
 					  int last_bank_sz)
 {
+	struct ath11k_dp *dp = &ab->dp;
 	int i;
 	int ret = 0;
 	int desc_sz = DP_LINK_DESC_ALLOC_SIZE_THRESH;
@@ -455,34 +456,29 @@ static int ath11k_dp_link_desc_bank_alloc(struct ath11k_base *ab,
 	return 0;
 
 err:
-	ath11k_dp_link_desc_bank_free(ab);
+	ath11k_dp_link_desc_bank_free(ab, dp->link_desc_banks);
 
 	return ret;
 }
 
-static void ath11k_dp_link_desc_cleanup(struct ath11k_base *ab)
+void ath11k_dp_link_desc_cleanup(struct ath11k_base *ab,
+				 struct dp_link_desc_bank *desc_bank,
+				 u32 ring_type, struct dp_srng *ring)
 {
-	struct ath11k_dp *dp = &ab->dp;
-
-	ath11k_dp_srng_cleanup(ab, &dp->wbm_idle_ring);
-
-	ath11k_dp_link_desc_bank_free(ab);
+	ath11k_dp_link_desc_bank_free(ab, desc_bank);
 
-	ath11k_dp_scatter_idle_link_desc_cleanup(ab);
+	if (ring_type != HAL_RXDMA_MONITOR_DESC) {
+		ath11k_dp_srng_cleanup(ab, ring);
+		ath11k_dp_scatter_idle_link_desc_cleanup(ab);
+	}
 }
 
-static int ath11k_dp_link_desc_setup(struct ath11k_base *ab)
+static int ath11k_wbm_idle_ring_setup(struct ath11k_base *ab, u32 *n_link_desc)
 {
 	struct ath11k_dp *dp = &ab->dp;
-	struct hal_srng *srng;
-	struct dp_link_desc_bank *link_desc_banks = dp->link_desc_banks;
-	u32 n_mpdu_link_desc, n_mpdu_queue_desc, n_tx_msdu_link_desc;
-	u32 n_rx_msdu_link_desc, n_link_desc, tot_mem_sz;
-	u32 n_link_desc_bank, last_bank_sz;
-	u32 entry_sz, align_bytes, n_entries;
-	dma_addr_t paddr;
-	u32 *desc;
-	int i, ret;
+	u32 n_mpdu_link_desc, n_mpdu_queue_desc;
+	u32 n_tx_msdu_link_desc, n_rx_msdu_link_desc;
+	int ret = 0;
 
 	n_mpdu_link_desc = (DP_NUM_TIDS_MAX * DP_AVG_MPDUS_PER_TID_MAX) /
 			   HAL_NUM_MPDUS_PER_LINK_DESC;
@@ -498,9 +494,30 @@ static int ath11k_dp_link_desc_setup(struct ath11k_base *ab)
 			       DP_AVG_MSDUS_PER_MPDU) /
 			      HAL_NUM_RX_MSDUS_PER_LINK_DESC;
 
-	n_link_desc = n_mpdu_link_desc + n_mpdu_queue_desc +
+	*n_link_desc = n_mpdu_link_desc + n_mpdu_queue_desc +
 		      n_tx_msdu_link_desc + n_rx_msdu_link_desc;
 
+	ret = ath11k_dp_srng_setup(ab, &dp->wbm_idle_ring,
+				   HAL_WBM_IDLE_LINK, 0, 0, *n_link_desc);
+	if (ret) {
+		ath11k_warn(ab, "failed to setup wbm_idle_ring: %d\n", ret);
+		return ret;
+	}
+	return ret;
+}
+
+int ath11k_dp_link_desc_setup(struct ath11k_base *ab,
+			      struct dp_link_desc_bank *link_desc_banks,
+			      u32 ring_type, struct hal_srng *srng,
+			      u32 n_link_desc)
+{
+	u32 tot_mem_sz;
+	u32 n_link_desc_bank, last_bank_sz;
+	u32 entry_sz, align_bytes, n_entries;
+	u32 paddr;
+	u32 *desc;
+	int i, ret;
+
 	if (n_link_desc & (n_link_desc - 1))
 		n_link_desc = 1 << fls(n_link_desc);
 
@@ -531,11 +548,12 @@ static int ath11k_dp_link_desc_setup(struct ath11k_base *ab)
 		return ret;
 
 	/* Setup link desc idle list for HW internal usage */
-	entry_sz = ath11k_hal_srng_get_entrysize(HAL_WBM_IDLE_LINK);
+	entry_sz = ath11k_hal_srng_get_entrysize(ring_type);
 	tot_mem_sz = entry_sz * n_link_desc;
 
 	/* Setup scatter desc list when the total memory requirement is more */
-	if (tot_mem_sz > DP_LINK_DESC_ALLOC_SIZE_THRESH) {
+	if (tot_mem_sz > DP_LINK_DESC_ALLOC_SIZE_THRESH &&
+	    ring_type != HAL_RXDMA_MONITOR_DESC) {
 		ret = ath11k_dp_scatter_idle_link_desc_setup(ab, tot_mem_sz,
 							     n_link_desc_bank,
 							     n_link_desc,
@@ -549,13 +567,6 @@ static int ath11k_dp_link_desc_setup(struct ath11k_base *ab)
 		return 0;
 	}
 
-	ret = ath11k_dp_srng_setup(ab, &dp->wbm_idle_ring,
-				   HAL_WBM_IDLE_LINK, 0, 0, n_link_desc);
-	if (ret)
-		goto fail_desc_bank_free;
-
-	srng = &ab->hal.srng_list[dp->wbm_idle_ring.ring_id];
-
 	spin_lock_bh(&srng->lock);
 
 	ath11k_hal_srng_access_begin(ab, srng);
@@ -583,7 +594,7 @@ static int ath11k_dp_link_desc_setup(struct ath11k_base *ab)
 	return 0;
 
 fail_desc_bank_free:
-	ath11k_dp_link_desc_bank_free(ab);
+	ath11k_dp_link_desc_bank_free(ab, link_desc_banks);
 
 	return ret;
 }
@@ -637,19 +648,6 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
 		}
 	}
 
-	if (rx_mon_status_ring_mask[grp_id]) {
-		for (i = 0; i <  ab->num_radios; i++) {
-			if (rx_mon_status_ring_mask[grp_id] & BIT(i)) {
-				work_done = ath11k_dp_rx_process_mon_status(ab, i, napi,
-									    budget);
-				budget -= work_done;
-				tot_work_done += work_done;
-			}
-			if (budget <= 0)
-				goto done;
-		}
-	}
-
 	if (ath11k_reo_status_ring_mask[grp_id])
 		ath11k_dp_process_reo_status(ab);
 
@@ -707,6 +705,8 @@ int ath11k_dp_pdev_alloc(struct ath11k_base *ab)
 		init_waitqueue_head(&dp->tx_empty_waitq);
 		idr_init(&dp->rx_mon_status_refill_ring.bufs_idr);
 		spin_lock_init(&dp->rx_mon_status_refill_ring.idr_lock);
+		idr_init(&dp->rxdma_mon_buf_ring.bufs_idr);
+		spin_lock_init(&dp->rxdma_mon_buf_ring.idr_lock);
 	}
 
 	/* TODO:Per-pdev rx ring unlike tx ring which is mapped to different AC's */
@@ -808,7 +808,8 @@ void ath11k_dp_free(struct ath11k_base *sc)
 	struct ath11k_dp *dp = &sc->dp;
 	int i;
 
-	ath11k_dp_link_desc_cleanup(sc);
+	ath11k_dp_link_desc_cleanup(sc, dp->link_desc_banks,
+				    HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring);
 
 	ath11k_dp_srng_common_cleanup(sc);
 
@@ -830,7 +831,8 @@ void ath11k_dp_free(struct ath11k_base *sc)
 int ath11k_dp_alloc(struct ath11k_base *sc)
 {
 	struct ath11k_dp *dp = &sc->dp;
-	size_t size;
+	struct hal_srng *srng = NULL;
+	size_t size = 0, n_link_desc = 0;
 	int ret;
 	int i;
 
@@ -840,7 +842,16 @@ int ath11k_dp_alloc(struct ath11k_base *sc)
 	INIT_LIST_HEAD(&dp->reo_cmd_cache_flush_list);
 	spin_lock_init(&dp->reo_cmd_lock);
 
-	ret = ath11k_dp_link_desc_setup(sc);
+	ret = ath11k_wbm_idle_ring_setup(sc, &n_link_desc);
+	if (ret) {
+		ath11k_warn(sc, "failed to setup wbm_idle_ring: %d\n", ret);
+		return ret;
+	}
+
+	srng = &sc->hal.srng_list[dp->wbm_idle_ring.ring_id];
+
+	ret = ath11k_dp_link_desc_setup(sc, dp->link_desc_banks,
+					HAL_WBM_IDLE_LINK, srng, n_link_desc);
 	if (ret) {
 		ath11k_warn(sc, "failed to setup link desc: %d\n", ret);
 		return ret;
@@ -875,7 +886,8 @@ int ath11k_dp_alloc(struct ath11k_base *sc)
 	ath11k_dp_srng_common_cleanup(sc);
 
 fail_link_desc_cleanup:
-	ath11k_dp_link_desc_cleanup(sc);
+	ath11k_dp_link_desc_cleanup(sc, dp->link_desc_banks,
+				    HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring);
 
 	return ret;
 }
diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
index fb880df..2dc133b 100644
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -7,6 +7,7 @@
 #define ATH11K_DP_H
 
 #include <linux/kfifo.h>
+#include "hal_rx.h"
 
 struct ath11k_base;
 struct ath11k_peer;
@@ -67,6 +68,59 @@ struct dp_tx_ring {
 	spinlock_t tx_idr_lock;
 };
 
+struct ath11k_pdev_mon_stats {
+	u32 status_ppdu_state;
+	u32 status_ppdu_start;
+	u32 status_ppdu_end;
+	u32 status_ppdu_compl;
+	u32 status_ppdu_start_mis;
+	u32 status_ppdu_end_mis;
+	u32 status_ppdu_done;
+	u32 dest_ppdu_done;
+	u32 dest_mpdu_done;
+	u32 dest_mpdu_drop;
+	u32 dup_mon_linkdesc_cnt;
+	u32 dup_mon_buf_cnt;
+};
+
+struct dp_link_desc_bank {
+	void *vaddr_unaligned;
+	void *vaddr;
+	dma_addr_t paddr_unaligned;
+	dma_addr_t paddr;
+	u32 size;
+};
+
+/* Size to enforce scatter idle list mode */
+#define DP_LINK_DESC_ALLOC_SIZE_THRESH 0x200000
+#define DP_LINK_DESC_BANKS_MAX 8
+
+#define DP_RX_DESC_COOKIE_INDEX_MAX		0x3ffff
+#define DP_RX_DESC_COOKIE_POOL_ID_MAX		0x1c0000
+#define DP_RX_DESC_COOKIE_MAX	\
+	(DP_RX_DESC_COOKIE_INDEX_MAX | DP_RX_DESC_COOKIE_POOL_ID_MAX)
+#define DP_NOT_PPDU_ID_WRAP_AROUND 20000
+
+enum ath11k_dp_ppdu_state {
+	DP_PPDU_STATUS_START,
+	DP_PPDU_STATUS_DONE,
+};
+
+struct ath11k_mon_data {
+	struct dp_link_desc_bank link_desc_banks[DP_LINK_DESC_BANKS_MAX];
+	struct hal_rx_mon_ppdu_info mon_ppdu_info;
+
+	u32 mon_ppdu_status;
+	u32 mon_last_buf_cookie;
+	u64 mon_last_linkdesc_paddr;
+	u16 chan_noise_floor;
+
+	struct ath11k_pdev_mon_stats rx_mon_stats;
+	/* lock for monitor data */
+	spinlock_t mon_lock;
+	struct sk_buff_head rx_status_q;
+};
+
 struct ath11k_pdev_dp {
 	u32 mac_id;
 	atomic_t num_tx_pending;
@@ -74,8 +128,13 @@ struct ath11k_pdev_dp {
 	struct dp_srng reo_dst_ring;
 	struct dp_rxdma_ring rx_refill_buf_ring;
 	struct dp_srng rxdma_err_dst_ring;
+	struct dp_srng rxdma_mon_dst_ring;
+	struct dp_srng rxdma_mon_desc_ring;
+
+	struct dp_rxdma_ring rxdma_mon_buf_ring;
 	struct dp_rxdma_ring rx_mon_status_refill_ring;
 	struct ieee80211_rx_status rx_status;
+	struct ath11k_mon_data mon_data;
 };
 
 #define DP_NUM_CLIENTS_MAX 64
@@ -90,18 +149,6 @@ struct ath11k_pdev_dp {
 
 #define DP_BA_WIN_SZ_MAX	256
 
-/* Size to enforce scatter idle list mode */
-#define DP_LINK_DESC_ALLOC_SIZE_THRESH 0x200000
-#define DP_LINK_DESC_BANKS_MAX 8
-
-struct dp_link_desc_bank {
-	void *vaddr_unaligned;
-	void *vaddr;
-	dma_addr_t paddr_unaligned;
-	dma_addr_t paddr;
-	u32 size;
-};
-
 #define DP_TCL_NUM_RING_MAX	3
 
 #define DP_IDLE_SCATTER_BUFS_MAX 16
@@ -122,6 +169,9 @@ struct dp_link_desc_bank {
 #define DP_RXDMA_REFILL_RING_SIZE	2048
 #define DP_RXDMA_ERR_DST_RING_SIZE	1024
 #define DP_RXDMA_MON_STATUS_RING_SIZE	1024
+#define DP_RXDMA_MONITOR_BUF_RING_SIZE	4096
+#define DP_RXDMA_MONITOR_DST_RING_SIZE	2048
+#define DP_RXDMA_MONITOR_DESC_RING_SIZE	4096
 
 #define DP_RX_BUFFER_SIZE	2048
 #define DP_RX_BUFFER_ALIGN_SIZE	128
@@ -574,6 +624,9 @@ enum htt_rx_mgmt_pkt_filter_tlv_flags0 {
 	HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV	= BIT(18),
 	HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV	= BIT(19),
 	HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_PROBE_TIMING_ADV	= BIT(20),
+	HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7		= BIT(21),
+	HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7		= BIT(22),
+	HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7		= BIT(23),
 	HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON		= BIT(24),
 	HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON		= BIT(25),
 	HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_BEACON		= BIT(26),
@@ -598,9 +651,33 @@ enum htt_rx_mgmt_pkt_filter_tlv_flags1 {
 	HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK	= BIT(12),
 	HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK	= BIT(13),
 	HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_ACTION_NOACK	= BIT(14),
+	HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15	= BIT(15),
+	HTT_RX_MD_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15	= BIT(16),
+	HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15	= BIT(17),
 };
 
 enum htt_rx_ctrl_pkt_filter_tlv_flags2 {
+	HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1	= BIT(0),
+	HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1	= BIT(1),
+	HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1	= BIT(2),
+	HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2	= BIT(3),
+	HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2	= BIT(4),
+	HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2	= BIT(5),
+	HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER	= BIT(6),
+	HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER	= BIT(7),
+	HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER	= BIT(8),
+	HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4	= BIT(9),
+	HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4	= BIT(10),
+	HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4	= BIT(11),
+	HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL	= BIT(12),
+	HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL	= BIT(13),
+	HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL	= BIT(14),
+	HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP	= BIT(15),
+	HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP	= BIT(16),
+	HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP	= BIT(17),
+	HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT	= BIT(18),
+	HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT	= BIT(19),
+	HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT	= BIT(20),
 	HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER	= BIT(21),
 	HTT_RX_MD_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER	= BIT(22),
 	HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_WRAPPER	= BIT(23),
@@ -636,13 +713,13 @@ enum htt_rx_ctrl_pkt_filter_tlv_flags3 {
 enum htt_rx_data_pkt_filter_tlv_flasg3 {
 	HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST	= BIT(18),
 	HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_MCAST	= BIT(19),
-	HTT_RX_M0_DATA_PKT_FILTER_TLV_FLASG3_MCAST	= BIT(20),
+	HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_MCAST	= BIT(20),
 	HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST	= BIT(21),
 	HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_UCAST	= BIT(22),
-	HTT_RX_M0_DATA_PKT_FILTER_TLV_FLASG3_UCAST	= BIT(23),
-	HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA	= BIT(21),
-	HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA	= BIT(22),
-	HTT_RX_M0_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA	= BIT(23),
+	HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_UCAST	= BIT(23),
+	HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA	= BIT(24),
+	HTT_RX_MD_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA	= BIT(25),
+	HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA	= BIT(26),
 };
 
 #define HTT_RX_FP_MGMT_FILTER_FLAGS0 (HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_ASSOC_REQ \
@@ -738,6 +815,76 @@ enum htt_rx_data_pkt_filter_tlv_flasg3 {
 				     | HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_UCAST \
 				     | HTT_RX_MO_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA)
 
+#define HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 \
+		(HTT_RX_FP_MGMT_FILTER_FLAGS0 | \
+		HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7)
+
+#define HTT_RX_MON_MO_MGMT_FILTER_FLAGS0 \
+		(HTT_RX_MO_MGMT_FILTER_FLAGS0 | \
+		HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS0_RESERVED_7)
+
+#define HTT_RX_MON_FP_MGMT_FILTER_FLAGS1 \
+		(HTT_RX_FP_MGMT_FILTER_FLAGS1 | \
+		HTT_RX_FP_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15)
+
+#define HTT_RX_MON_MO_MGMT_FILTER_FLAGS1 \
+		(HTT_RX_MO_MGMT_FILTER_FLAGS1 | \
+		HTT_RX_MO_MGMT_PKT_FILTER_TLV_FLAGS1_RESERVED_15)
+
+#define HTT_RX_MON_FP_CTRL_FILTER_FLASG2 \
+		(HTT_RX_FP_CTRL_FILTER_FLASG2 | \
+		HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 | \
+		HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 | \
+		HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER | \
+		HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 | \
+		HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL | \
+		HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP | \
+		HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT)
+
+#define HTT_RX_MON_MO_CTRL_FILTER_FLASG2 \
+		(HTT_RX_MO_CTRL_FILTER_FLASG2 | \
+		HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_1 | \
+		HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_2 | \
+		HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_TRIGGER | \
+		HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_RESERVED_4 | \
+		HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_BF_REP_POLL | \
+		HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_VHT_NDP | \
+		HTT_RX_MO_CTRL_PKT_FILTER_TLV_FLAGS2_CTRL_FRAME_EXT)
+
+#define HTT_RX_MON_FP_CTRL_FILTER_FLASG3 HTT_RX_FP_CTRL_FILTER_FLASG3
+
+#define HTT_RX_MON_MO_CTRL_FILTER_FLASG3 HTT_RX_MO_CTRL_FILTER_FLASG3
+
+#define HTT_RX_MON_FP_DATA_FILTER_FLASG3 HTT_RX_FP_DATA_FILTER_FLASG3
+
+#define HTT_RX_MON_MO_DATA_FILTER_FLASG3 HTT_RX_MO_DATA_FILTER_FLASG3
+
+#define HTT_RX_MON_FILTER_TLV_FLAGS \
+		(HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE)
+
+#define HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING \
+		(HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
+		HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE)
+
+#define HTT_RX_MON_FILTER_TLV_FLAGS_MON_BUF_RING \
+		(HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \
+		HTT_RX_FILTER_TLV_FLAGS_MSDU_START | \
+		HTT_RX_FILTER_TLV_FLAGS_RX_PACKET | \
+		HTT_RX_FILTER_TLV_FLAGS_MSDU_END | \
+		HTT_RX_FILTER_TLV_FLAGS_MPDU_END | \
+		HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER | \
+		HTT_RX_FILTER_TLV_FLAGS_PER_MSDU_HEADER | \
+		HTT_RX_FILTER_TLV_FLAGS_ATTENTION)
+
 struct htt_rx_ring_selection_cfg_cmd {
 	u32 info0;
 	u32 info1;
@@ -1284,4 +1431,12 @@ void ath11k_dp_srng_cleanup(struct ath11k_base *ab, struct dp_srng *ring);
 int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
 			 enum hal_ring_type type, int ring_num,
 			 int mac_id, int num_entries);
+void ath11k_dp_link_desc_cleanup(struct ath11k_base *ab,
+				 struct dp_link_desc_bank *desc_bank,
+				 u32 ring_type, struct dp_srng *ring);
+int ath11k_dp_link_desc_setup(struct ath11k_base *ab,
+			      struct dp_link_desc_bank *link_desc_banks,
+			      u32 ring_type, struct hal_srng *srng,
+			      u32 n_link_desc);
+
 #endif
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.h b/drivers/net/wireless/ath/ath11k/dp_tx.h
index b14fdfa..9e85a4d 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.h
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.h
@@ -29,4 +29,5 @@ int ath11k_dp_htt_h2t_ppdu_stats_req(struct ath11k *ar, u32 mask);
 int ath11k_dp_htt_h2t_ext_stats_req(struct ath11k *ar, u8 type,
 				    u32 cfg0, u32 cfg1, u32 cfg2, u32 cfg3,
 				    u64 cookie);
+int ath11k_dp_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset);
 #endif
diff --git a/drivers/net/wireless/ath/ath11k/hal_desc.h b/drivers/net/wireless/ath/ath11k/hal_desc.h
index 8085f5f..99ab6f6 100644
--- a/drivers/net/wireless/ath/ath11k/hal_desc.h
+++ b/drivers/net/wireless/ath/ath11k/hal_desc.h
@@ -577,6 +577,9 @@ enum hal_rx_msdu_desc_reo_dest_ind {
 #define RX_MSDU_DESC_INFO0_DA_MCBC		BIT(26)
 #define RX_MSDU_DESC_INFO0_DA_IDX_TIMEOUT	BIT(27)
 
+#define HAL_RX_MSDU_PKT_LENGTH_GET(val)		\
+	(FIELD_GET(RX_MSDU_DESC_INFO0_MSDU_LENGTH, (val)))
+
 struct rx_msdu_desc {
 	u32 info0;
 	u32 rsvd0;
diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.h b/drivers/net/wireless/ath/ath11k/hal_rx.h
index 2ccc800..439a36f 100644
--- a/drivers/net/wireless/ath/ath11k/hal_rx.h
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.h
@@ -93,6 +93,7 @@ enum hal_rx_reception_type {
 #define HAL_TLV_STATUS_PPDU_DONE                1
 #define HAL_TLV_STATUS_BUF_DONE                 2
 #define HAL_TLV_STATUS_PPDU_NON_STD_DONE        3
+#define HAL_RX_FCS_LEN                          4
 
 enum hal_rx_mon_status {
 	HAL_RX_MON_STATUS_PPDU_NOT_DONE,
@@ -278,6 +279,18 @@ struct hal_rx_rxpcu_classification_overview {
 	u32 rsvd0;
 } __packed;
 
+struct hal_rx_msdu_desc_info {
+	u32 msdu_flags;
+	u16 msdu_len; /* 14 bits for length */
+};
+
+#define HAL_RX_NUM_MSDU_DESC 6
+struct hal_rx_msdu_list {
+	struct hal_rx_msdu_desc_info msdu_info[HAL_RX_NUM_MSDU_DESC];
+	u32 sw_cookie[HAL_RX_NUM_MSDU_DESC];
+	u8 rbm[HAL_RX_NUM_MSDU_DESC];
+};
+
 void ath11k_hal_reo_status_queue_stats(struct ath11k_base *ab, u32 *reo_desc,
 				       struct hal_reo_status *status);
 void ath11k_hal_reo_flush_queue_status(struct ath11k_base *ab, u32 *reo_desc,
@@ -316,6 +329,10 @@ int ath11k_hal_wbm_desc_parse_err(struct ath11k_base *ab, void *desc,
 				  struct hal_rx_wbm_rel_info *rel_info);
 void ath11k_hal_rx_reo_ent_paddr_get(struct ath11k_base *ab, void *desc,
 				     dma_addr_t *paddr, u32 *desc_bank);
+void ath11k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc,
+					 dma_addr_t *paddr, u32 *sw_cookie,
+					 void **pp_buf_addr_info,
+					 u32 *msdu_cnt);
 enum hal_rx_mon_status
 ath11k_hal_rx_parse_mon_status(struct ath11k_base *ab,
 			       struct hal_rx_mon_ppdu_info *ppdu_info,
diff --git a/drivers/net/wireless/ath/ath11k/rx_desc.h b/drivers/net/wireless/ath/ath11k/rx_desc.h
index 11924c6..57518a0 100644
--- a/drivers/net/wireless/ath/ath11k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath11k/rx_desc.h
@@ -662,6 +662,7 @@ enum rx_msdu_start_reception_type {
 #define RX_MSDU_START_INFO2_MESH_CTRL_PRESENT		BIT(22)
 #define RX_MSDU_START_INFO2_LDPC			BIT(23)
 #define RX_MSDU_START_INFO2_IP4_IP6_NXT_HDR		GENMASK(31, 24)
+#define RX_MSDU_START_INFO2_DECAP_FORMAT		GENMASK(9, 8)
 
 #define RX_MSDU_START_INFO3_USER_RSSI		GENMASK(7, 0)
 #define RX_MSDU_START_INFO3_PKT_TYPE		GENMASK(11, 8)
-- 
2.7.4


_______________________________________________
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 2/6] ath11k: monitor filter set function
  2019-04-16  0:12 [PATCH v5 0/6] ath11k: add monitor mode support Miles Hu
  2019-04-16  0:12 ` [PATCH v5 1/6] ath11k: init/deinit monitor rings Miles Hu
@ 2019-04-16  0:12 ` Miles Hu
  2019-04-16  0:12 ` [PATCH v5 3/6] ath11k: htt setup monitor rings Miles Hu
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Miles Hu @ 2019-04-16  0:12 UTC (permalink / raw)
  To: ath11k; +Cc: Miles Hu

create monitor mode filter.
implement htt filter set function.
create common function to get htt ring id and type.

Signed-off-by: Miles Hu <milehu@codeaurora.org>
---
V2:
 - correct wrong indent and style.
 - remove redundant code.

 drivers/net/wireless/ath/ath11k/dp_tx.c | 193 +++++++++++++++++++-------------
 1 file changed, 115 insertions(+), 78 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index ef724ec..2cba343 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -335,9 +335,14 @@ static void ath11k_dp_cache_peer_stats(struct ath11k *ar,
 {
 	struct ath11k_per_peer_tx_stats *peer_stats = &ar->cached_stats;
 
-	if (ts->try_cnt > 1) {
-		peer_stats->retry_pkts += ts->try_cnt - 1;
-		peer_stats->retry_bytes += (ts->try_cnt - 1) * msdu->len;
+	if (ts->try_cnt >= 1) {
+		if (ts->try_cnt == 1) {
+			peer_stats->retry_pkts += 1;
+			peer_stats->retry_bytes += msdu->len;
+		} else {
+			peer_stats->retry_pkts += ts->try_cnt - 1;
+			peer_stats->retry_bytes += (ts->try_cnt - 1) * msdu->len;
+		}
 
 		if (ts->status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) {
 			peer_stats->failed_pkts += 1;
@@ -378,9 +383,6 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
 	info = IEEE80211_SKB_CB(msdu);
 	memset(&info->status, 0, sizeof(info->status));
 
-	/* skip tx rate update from ieee80211_status*/
-	 info->status.rates[0].idx = -1;
-
 	if (ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED &&
 	    !(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
 		info->flags |= IEEE80211_TX_STAT_ACK;
@@ -551,30 +553,15 @@ int ath11k_dp_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid,
 	return 0;
 }
 
-int ath11k_dp_htt_srng_setup(struct ath11k_base *ab, u32 ring_id,
-			     int mac_id, enum hal_ring_type ring_type)
+static int
+ath11k_dp_get_ring_id_type(struct ath11k_base *ab,
+			   int mac_id, u32 ring_id,
+			   enum hal_ring_type ring_type,
+			   enum htt_srng_ring_type *htt_ring_type,
+			   enum htt_srng_ring_id *htt_ring_id)
 {
-	struct htt_srng_setup_cmd *cmd;
-	struct hal_srng *srng = &ab->hal.srng_list[ring_id];
-	struct hal_srng_params params;
-	struct sk_buff *skb;
-	int ring_entry_sz;
-	int len = sizeof(*cmd);
-	dma_addr_t hp_addr, tp_addr;
-	int lmac_ring_id_offset;
-	enum htt_srng_ring_type htt_ring_type;
-	enum htt_srng_ring_id htt_ring_id;
-	int ret;
-
-	skb = ath11k_htc_alloc_skb(ab, len);
-	if (!skb)
-		return -ENOMEM;
-
-	memset(&params, 0, sizeof(params));
-	ath11k_hal_srng_get_params(ab, srng, &params);
-
-	hp_addr = ath11k_hal_srng_get_hp_addr(ab, srng);
-	tp_addr = ath11k_hal_srng_get_tp_addr(ab, srng);
+	int lmac_ring_id_offset = 0;
+	int ret = 0;
 
 	switch (ring_type) {
 	case HAL_RXDMA_BUF:
@@ -584,37 +571,66 @@ int ath11k_dp_htt_srng_setup(struct ath11k_base *ab, u32 ring_id,
 		    ring_id == (HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_BUF +
 				lmac_ring_id_offset))) {
 			ret = -EINVAL;
-			goto err_free;
 		}
-
-		htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
-		htt_ring_type = HTT_SW_TO_HW_RING;
+		*htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
+		*htt_ring_type = HTT_SW_TO_HW_RING;
 		break;
 	case HAL_RXDMA_DST:
-		htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
-		htt_ring_type = HTT_HW_TO_SW_RING;
+		*htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
+		*htt_ring_type = HTT_HW_TO_SW_RING;
 		break;
 	case HAL_RXDMA_MONITOR_BUF:
-		htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING;
-		htt_ring_type = HTT_SW_TO_HW_RING;
+		*htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING;
+		*htt_ring_type = HTT_SW_TO_HW_RING;
 		break;
 	case HAL_RXDMA_MONITOR_STATUS:
-		htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
-		htt_ring_type = HTT_SW_TO_HW_RING;
+		*htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
+		*htt_ring_type = HTT_SW_TO_HW_RING;
 		break;
 	case HAL_RXDMA_MONITOR_DST:
-		htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING;
-		htt_ring_type = HTT_HW_TO_SW_RING;
+		*htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING;
+		*htt_ring_type = HTT_HW_TO_SW_RING;
 		break;
 	case HAL_RXDMA_MONITOR_DESC:
-		htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
-		htt_ring_type = HTT_SW_TO_HW_RING;
+		*htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
+		*htt_ring_type = HTT_SW_TO_HW_RING;
 		break;
 	default:
 		ath11k_warn(ab, "Unsupported ring type in DP :%d\n", ring_type);
 		ret = -EINVAL;
-		goto err_free;
 	}
+	return ret;
+}
+
+int ath11k_dp_htt_srng_setup(struct ath11k_base *ab, u32 ring_id,
+			     int mac_id, enum hal_ring_type ring_type)
+{
+	struct htt_srng_setup_cmd *cmd;
+	struct hal_srng *srng = &ab->hal.srng_list[ring_id];
+	struct hal_srng_params params;
+	struct sk_buff *skb;
+	u32 ring_entry_sz;
+	int len = sizeof(*cmd);
+	dma_addr_t hp_addr, tp_addr;
+	int lmac_ring_id_offset;
+	enum htt_srng_ring_type htt_ring_type;
+	enum htt_srng_ring_id htt_ring_id;
+	int ret;
+
+	skb = ath11k_htc_alloc_skb(ab, len);
+	if (!skb)
+		return -ENOMEM;
+
+	memset(&params, 0, sizeof(params));
+	ath11k_hal_srng_get_params(ab, srng, &params);
+
+	hp_addr = ath11k_hal_srng_get_hp_addr(ab, srng);
+	tp_addr = ath11k_hal_srng_get_tp_addr(ab, srng);
+
+	if (ath11k_dp_get_ring_id_type(ab, mac_id, ring_id,
+				       ring_type, &htt_ring_type,
+				       &htt_ring_id))
+		goto err_free;
 
 	skb_put(skb, len);
 	cmd = (struct htt_srng_setup_cmd *)skb->data;
@@ -757,7 +773,7 @@ int ath11k_dp_htt_h2t_ppdu_stats_req(struct ath11k *ar, u32 mask)
 	cmd->msg = FIELD_PREP(HTT_PPDU_STATS_CFG_MSG_TYPE,
 			      HTT_H2T_MSG_TYPE_PPDU_STATS_CFG);
 
-	pdev_mask = 1 << (ar->pdev_idx);
+	pdev_mask = DP_SW2HW_MACID(ar->pdev_idx);
 	cmd->msg |= FIELD_PREP(HTT_PPDU_STATS_CFG_PDEV_ID, pdev_mask);
 	cmd->msg |= FIELD_PREP(HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK, mask);
 
@@ -791,36 +807,10 @@ int ath11k_dp_htt_rx_filter_setup(struct ath11k_base *ab, u32 ring_id,
 	memset(&params, 0, sizeof(params));
 	ath11k_hal_srng_get_params(ab, srng, &params);
 
-	switch (ring_type) {
-	case HAL_RXDMA_BUF:
-		htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
-		htt_ring_type = HTT_SW_TO_HW_RING;
-		break;
-	case HAL_RXDMA_DST:
-		htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
-		htt_ring_type = HTT_HW_TO_SW_RING;
-		break;
-	case HAL_RXDMA_MONITOR_BUF:
-		htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING;
-		htt_ring_type = HTT_SW_TO_HW_RING;
-		break;
-	case HAL_RXDMA_MONITOR_STATUS:
-		htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
-		htt_ring_type = HTT_SW_TO_HW_RING;
-		break;
-	case HAL_RXDMA_MONITOR_DST:
-		htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING;
-		htt_ring_type = HTT_HW_TO_SW_RING;
-		break;
-	case HAL_RXDMA_MONITOR_DESC:
-		htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
-		htt_ring_type = HTT_SW_TO_HW_RING;
-		break;
-	default:
-		ath11k_warn(ab, "Unsupported ring type in DP :%d\n", ring_type);
-		ret = -EINVAL;
+	if (ath11k_dp_get_ring_id_type(ab, mac_id, ring_id,
+				       ring_type, &htt_ring_type,
+				       &htt_ring_id))
 		goto err_free;
-	}
 
 	skb_put(skb, len);
 	cmd = (struct htt_rx_ring_selection_cfg_cmd *)skb->data;
@@ -828,11 +818,13 @@ int ath11k_dp_htt_rx_filter_setup(struct ath11k_base *ab, u32 ring_id,
 				HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG);
 	if (htt_ring_type == HTT_SW_TO_HW_RING ||
 	    htt_ring_type == HTT_HW_TO_SW_RING)
-		cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID,
-					 DP_SW2HW_MACID(mac_id));
+		cmd->info0 |=
+			FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID,
+				   DP_SW2HW_MACID(mac_id));
 	else
-		cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID,
-					 mac_id);
+		cmd->info0 |=
+			FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID,
+				   mac_id);
 	cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID,
 				 htt_ring_id);
 	cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS,
@@ -901,3 +893,48 @@ int ath11k_dp_htt_h2t_ext_stats_req(struct ath11k *ar, u8 type,
 
 	return 0;
 }
+
+int ath11k_dp_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct htt_rx_ring_tlv_filter tlv_filter = {0};
+	int ret = 0, ring_id = 0;
+
+	ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id;
+
+	if (!reset) {
+		tlv_filter.rx_filter = HTT_RX_MON_FILTER_TLV_FLAGS_MON_BUF_RING;
+		tlv_filter.pkt_filter_flags0 =
+					HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 |
+					HTT_RX_MON_MO_MGMT_FILTER_FLAGS0;
+		tlv_filter.pkt_filter_flags1 =
+					HTT_RX_MON_FP_MGMT_FILTER_FLAGS1 |
+					HTT_RX_MON_MO_MGMT_FILTER_FLAGS1;
+		tlv_filter.pkt_filter_flags2 =
+					HTT_RX_MON_FP_CTRL_FILTER_FLASG2 |
+					HTT_RX_MON_MO_CTRL_FILTER_FLASG2;
+		tlv_filter.pkt_filter_flags3 =
+					HTT_RX_MON_FP_CTRL_FILTER_FLASG3 |
+					HTT_RX_MON_MO_CTRL_FILTER_FLASG3 |
+					HTT_RX_MON_FP_DATA_FILTER_FLASG3 |
+					HTT_RX_MON_MO_DATA_FILTER_FLASG3;
+	}
+
+	ret = ath11k_dp_htt_rx_filter_setup(ar->ab, ring_id, dp->mac_id,
+					    HAL_RXDMA_MONITOR_BUF,
+					    DP_RXDMA_REFILL_RING_SIZE,
+					    &tlv_filter);
+	if (ret)
+		return ret;
+
+	ring_id = dp->rx_mon_status_refill_ring.refill_buf_ring.ring_id;
+	if (!reset)
+		tlv_filter.rx_filter =
+				HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING;
+
+	ret = ath11k_dp_htt_rx_filter_setup(ar->ab, ring_id, dp->mac_id,
+					    HAL_RXDMA_MONITOR_STATUS,
+					    DP_RXDMA_REFILL_RING_SIZE,
+					    &tlv_filter);
+	return ret;
+}
-- 
2.7.4


_______________________________________________
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 3/6] ath11k: htt setup monitor rings
  2019-04-16  0:12 [PATCH v5 0/6] ath11k: add monitor mode support Miles Hu
  2019-04-16  0:12 ` [PATCH v5 1/6] ath11k: init/deinit monitor rings Miles Hu
  2019-04-16  0:12 ` [PATCH v5 2/6] ath11k: monitor filter set function Miles Hu
@ 2019-04-16  0:12 ` Miles Hu
  2019-04-16  0:12 ` [PATCH v5 4/6] ath11k: monitor mode attach/detach Miles Hu
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Miles Hu @ 2019-04-16  0:12 UTC (permalink / raw)
  To: ath11k; +Cc: Miles Hu

add setup functions for monitor rings.
some inline rxdesc decode and packet length functions.

Signed-off-by: Miles Hu <milehu@codeaurora.org>
---
V2:
 - fix wrong indent and style code.
 - change return value from int to bool.
 - fix warn message style and remove __func__, __LINE__.

V3:
 - create common ring reap function for peer-stats and monitor mode.

 drivers/net/wireless/ath/ath11k/dp_rx.c | 289 ++++++++++++++++++++++++--------
 drivers/net/wireless/ath/ath11k/dp_rx.h |  61 ++++++-
 2 files changed, 277 insertions(+), 73 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 5d4d0ed..2605b2b 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
  */
 
+#include <linux/ieee80211.h>
 #include "core.h"
 #include "debug.h"
 #include "hal_desc.h"
@@ -105,15 +106,13 @@ int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id,
 	return req_entries - num_remain;
 }
 
-static int ath11k_dp_rxdma_pdev_buf_free(struct ath11k *ar)
+static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
+					 struct dp_rxdma_ring *rx_ring)
 {
 	struct ath11k_pdev_dp *dp = &ar->dp;
-	struct dp_rxdma_ring *rx_ring;
 	struct sk_buff *skb;
 	int buf_id;
 
-	rx_ring = &dp->rx_refill_buf_ring;
-
 	spin_lock_bh(&rx_ring->idr_lock);
 	idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) {
 		idr_remove(&rx_ring->bufs_idr, buf_id);
@@ -137,7 +136,7 @@ static int ath11k_dp_rxdma_pdev_buf_free(struct ath11k *ar)
 		 * of rxdma_buffer.
 		 */
 		dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
-				 skb->len + skb_tailroom(skb), DMA_BIDIRECTIONAL);
+			skb->len + skb_tailroom(skb), DMA_BIDIRECTIONAL);
 		dev_kfree_skb_any(skb);
 	}
 
@@ -146,29 +145,50 @@ static int ath11k_dp_rxdma_pdev_buf_free(struct ath11k *ar)
 	return 0;
 }
 
-static int ath11k_dp_rxdma_pdev_buf_setup(struct ath11k *ar)
+static int ath11k_dp_rxdma_pdev_buf_free(struct ath11k *ar)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
+
+	ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
+
+	rx_ring = &dp->rxdma_mon_buf_ring;
+	ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
+
+	rx_ring = &dp->rx_mon_status_refill_ring;
+	ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
+	return 0;
+}
+
+static int ath11k_dp_rxdma_ring_buf_setup(struct ath11k *ar,
+					  struct dp_rxdma_ring *rx_ring,
+					  u32 ringtype)
 {
 	struct ath11k_pdev_dp *dp = &ar->dp;
-	struct dp_rxdma_ring *rx_ring;
 	int num_entries;
 
-	rx_ring = &dp->rx_refill_buf_ring;
 	num_entries = rx_ring->refill_buf_ring.size /
-		      ath11k_hal_srng_get_entrysize(HAL_RXDMA_BUF);
+		      ath11k_hal_srng_get_entrysize(ringtype);
 
 	rx_ring->bufs_max = num_entries;
 	ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id, rx_ring, num_entries,
 				   HAL_RX_BUF_RBM_SW3_BM, GFP_KERNEL);
+	return 0;
+}
+
+static int ath11k_dp_rxdma_pdev_buf_setup(struct ath11k *ar)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
+
+	ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_BUF);
+
+	rx_ring = &dp->rxdma_mon_buf_ring;
+	ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_BUF);
 
 	rx_ring = &dp->rx_mon_status_refill_ring;
-	num_entries = rx_ring->refill_buf_ring.size /
-		      ath11k_hal_srng_get_entrysize(HAL_RXDMA_MONITOR_STATUS);
+	ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_STATUS);
 
-	rx_ring->bufs_max = num_entries;
-	ath11k_dp_rx_mon_status_bufs_replenish(ar->ab, dp->mac_id, rx_ring,
-					       num_entries,
-					       HAL_RX_BUF_RBM_SW3_BM,
-					       GFP_KERNEL);
 	return 0;
 }
 
@@ -180,11 +200,13 @@ static void ath11k_dp_rx_pdev_srng_free(struct ath11k *ar)
 	ath11k_dp_srng_cleanup(ar->ab, &dp->reo_dst_ring);
 	ath11k_dp_srng_cleanup(ar->ab, &dp->rxdma_err_dst_ring);
 	ath11k_dp_srng_cleanup(ar->ab, &dp->rx_mon_status_refill_ring.refill_buf_ring);
+	ath11k_dp_srng_cleanup(ar->ab, &dp->rxdma_mon_buf_ring.refill_buf_ring);
 }
 
 static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar)
 {
 	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct dp_srng *srng = NULL;
 	int ret;
 
 	ret = ath11k_dp_srng_setup(ar->ab,
@@ -212,13 +234,44 @@ static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar)
 		return ret;
 	}
 
-	ret = ath11k_dp_srng_setup(ar->ab, &dp->rx_mon_status_refill_ring.refill_buf_ring,
+	srng = &dp->rx_mon_status_refill_ring.refill_buf_ring;
+	ret = ath11k_dp_srng_setup(ar->ab,
+				   srng,
 				   HAL_RXDMA_MONITOR_STATUS, 0, dp->mac_id,
 				   DP_RXDMA_MON_STATUS_RING_SIZE);
 	if (ret) {
-		ath11k_warn(ar->ab, "failed to setup rx_mon_status_refill_ring\n");
+		ath11k_warn(ar->ab,
+			    "failed to setup rx_mon_status_refill_ring\n");
+		return ret;
+	}
+	ret = ath11k_dp_srng_setup(ar->ab,
+				   &dp->rxdma_mon_buf_ring.refill_buf_ring,
+				   HAL_RXDMA_MONITOR_BUF, 0, dp->mac_id,
+				   DP_RXDMA_MONITOR_BUF_RING_SIZE);
+	if (ret) {
+		ath11k_warn(ar->ab,
+			    "failed to setup HAL_RXDMA_MONITOR_BUF\n");
+		return ret;
+	}
+
+	ret = ath11k_dp_srng_setup(ar->ab, &dp->rxdma_mon_dst_ring,
+				   HAL_RXDMA_MONITOR_DST, 0, dp->mac_id,
+				   DP_RXDMA_MONITOR_DST_RING_SIZE);
+	if (ret) {
+		ath11k_warn(ar->ab,
+			    "failed to setup HAL_RXDMA_MONITOR_DST\n");
+		return ret;
+	}
+
+	ret = ath11k_dp_srng_setup(ar->ab, &dp->rxdma_mon_desc_ring,
+				   HAL_RXDMA_MONITOR_DESC, 0, dp->mac_id,
+				   DP_RXDMA_MONITOR_DESC_RING_SIZE);
+	if (ret) {
+		ath11k_warn(ar->ab,
+			    "failed to setup HAL_RXDMA_MONITOR_DESC\n");
 		return ret;
 	}
+
 	return 0;
 }
 
@@ -710,7 +763,7 @@ int ath11k_dp_htt_tlv_iter(struct ath11k_base *ab, const void *ptr, size_t len,
 	u16 tlv_tag, tlv_len;
 	int ret = -EINVAL;
 
-	while(len > 0) {
+	while (len > 0) {
 		if (len < sizeof(*tlv)) {
 			ath11k_err(ab, "htt tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
 				   ptr - begin, len, sizeof(*tlv));
@@ -792,7 +845,7 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar,
 	int ret;
 	u8 flags, mcs, nss, bw, sgi, rate_idx = 0;
 	u32 succ_bytes = 0;
-	u16 rate = 0, succ_pkts = 0;
+	u16 succ_mpdus = 0, rate = 0, succ_pkts = 0;
 	bool is_ampdu = false;
 
 	if (!usr_stats)
@@ -802,6 +855,9 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar,
 		return;
 
 	if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON))
+		succ_mpdus = usr_stats->cmpltn_cmn.mpdu_success;
+
+	if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON))
 		is_ampdu =
 			HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags);
 
@@ -819,10 +875,10 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar,
 	mcs = HTT_USR_RATE_MCS(user_rate->rate_flags);
 	sgi = HTT_USR_RATE_GI(user_rate->rate_flags);
 
-        /* Note: If host configured fixed rates and in some other special
+	/* Note: If host configured fixed rates and in some other special
 	 * cases, the broadcast/management frames are sent in different rates.
 	 * Firmare rate's control to be skipped for this?
-         */
+	*/
 
 	if (flags == WMI_RATE_PREAMBLE_VHT && mcs > 9) {
 		ath11k_warn(ab, "Invalid VHT mcs %hhd peer stats",  mcs);
@@ -858,7 +914,6 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar,
 	arsta = (struct ath11k_sta *)sta->drv_priv;
 
 	memset(&arsta->txrate, 0, sizeof(arsta->txrate));
-	memset(&arsta->tx_info.status, 0, sizeof(arsta->tx_info.status));
 
 	switch (flags) {
 	case WMI_RATE_PREAMBLE_OFDM:
@@ -906,7 +961,7 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar,
 
 	memcpy(&arsta->last_txrate, &arsta->txrate, sizeof(struct rate_info));
 
-	if (succ_pkts) {
+	if (succ_mpdus) {
 		arsta->tx_info.flags = IEEE80211_TX_STAT_ACK;
 		arsta->tx_info.status.rates[0].count = 1;
 		ieee80211_tx_rate_update(ar->hw, sta, &arsta->tx_info);
@@ -974,7 +1029,8 @@ struct htt_ppdu_stats_info *ath11k_dp_htt_get_ppdu_desc(struct ath11k *ar,
 }
 
 static int ath11k_htt_pull_ppdu_stats(struct ath11k_base *ab,
-					 struct sk_buff *skb) {
+					struct sk_buff *skb)
+{
 	u8 *data = (u8 *)skb->data;
 	struct htt_ppdu_stats_info *ppdu_info;
 	struct ath11k *ar;
@@ -986,11 +1042,8 @@ static int ath11k_htt_pull_ppdu_stats(struct ath11k_base *ab,
 	pdev_id = FIELD_GET(HTT_T2H_PPDU_STATS_PDEV_ID_M, *(u32 *)data);
 	pdev_id = DP_HW2SW_MACID(pdev_id);
 	ppdu_id = *((u32 *)data + 1);
-	ar = ab->pdevs[pdev_id].ar;
 
-	if (!ar->debug.pktlog_mode == ATH11K_PKTLOG_MODE_LITE) {
-		/* TODO update the pktlog tracing */
-	}
+	ar = ab->pdevs[pdev_id].ar;
 
 	/* TLV info starts after 16bytes of header */
 	data = (u8 *)data + 16;
@@ -1011,22 +1064,6 @@ static int ath11k_htt_pull_ppdu_stats(struct ath11k_base *ab,
 	return 0;
 }
 
-static void ath11k_htt_pktlog(struct ath11k_base *ab,
-				     struct sk_buff *skb)
-{
-	u32 *data = (u32 *)skb->data;
-	struct ath11k *ar;
-	u8 pdev_id;
-	u32 len;
-
-	len = FIELD_GET(HTT_T2H_PPDU_STATS_PAYLOAD_SIZE_M, *data);
-	pdev_id = FIELD_GET(HTT_T2H_PPDU_STATS_PDEV_ID_M, *data);
-	pdev_id = DP_HW2SW_MACID(pdev_id);
-	ar = ab->pdevs[pdev_id].ar;
-	++data;
-
-	/* TODO add pktlog tracing */
-}
 
 void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab,
 				       struct sk_buff *skb)
@@ -1074,9 +1111,6 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab,
 	case HTT_T2H_MSG_TYPE_EXT_STATS_CONF:
 		ath11k_dbg_htt_ext_stats_handler(ab, skb);
 		break;
-	case HTT_T2H_MSG_TYPE_PKTLOG:
-		ath11k_htt_pktlog(ab, skb);
-		break;
 	default:
 		ath11k_warn(ab, "htt event %d not handled\n", type);
 		break;
@@ -2175,21 +2209,16 @@ int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id,
 	return req_entries - num_remain;
 }
 
-int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
-				    struct napi_struct *napi, int budget)
+int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
+				      int *budget, struct sk_buff_head *skb_list)
 {
 	struct ath11k *ar = ab->pdevs[mac_id].ar;
 	struct ath11k_pdev_dp *dp = &ar->dp;
 	struct dp_rxdma_ring *rx_ring = &dp->rx_mon_status_refill_ring;
-	enum hal_rx_mon_status hal_status;
 	struct hal_srng *srng;
 	void *rx_mon_status_desc;
 	struct sk_buff *skb;
-	struct sk_buff_head skb_list;
 	struct ath11k_skb_rxcb *rxcb;
-	struct hal_rx_mon_ppdu_info ppdu_info;
-	struct ath11k_peer *peer;
-	struct ath11k_sta *arsta;
 	struct hal_tlv_hdr *tlv;
 	u32 cookie;
 	int buf_id;
@@ -2197,13 +2226,13 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
 	u8 rbm;
 	int num_buffs_reaped = 0;
 
-	__skb_queue_head_init(&skb_list);
 	srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id];
 
 	spin_lock_bh(&srng->lock);
 
 	ath11k_hal_srng_access_begin(ab, srng);
-	while (budget--) {
+	while (*budget) {
+		*budget -= 1;
 		rx_mon_status_desc =
 			ath11k_hal_srng_src_peek(ab, srng);
 		if (!rx_mon_status_desc)
@@ -2220,7 +2249,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
 				ath11k_warn(ab, "rx monitor status with invalid buf_id %d\n",
 					    buf_id);
 				spin_unlock_bh(&rx_ring->idr_lock);
-				continue;
+				break;
 			}
 
 			idr_remove(&rx_ring->bufs_idr, buf_id);
@@ -2243,7 +2272,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
 				continue;
 			}
 
-			__skb_queue_tail(&skb_list, skb);
+			__skb_queue_tail(skb_list, skb);
 		}
 
 		skb = ath11k_dp_rx_alloc_mon_status_buf(ab, rx_ring,
@@ -2268,6 +2297,24 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
 	ath11k_hal_srng_access_end(ab, srng);
 	spin_unlock_bh(&srng->lock);
 
+	return num_buffs_reaped;
+}
+
+int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
+				    struct napi_struct *napi, int budget)
+{
+	enum hal_rx_mon_status hal_status;
+	struct sk_buff *skb;
+	struct sk_buff_head skb_list;
+	struct hal_rx_mon_ppdu_info ppdu_info;
+	struct ath11k_peer *peer;
+	struct ath11k_sta *arsta;
+	int num_buffs_reaped = 0;
+
+	__skb_queue_head_init(&skb_list);
+
+	num_buffs_reaped = ath11k_dp_rx_reap_mon_status_ring(ab, mac_id, &budget,
+							     &skb_list);
 	if (!num_buffs_reaped)
 		goto exit;
 
@@ -2275,10 +2322,6 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
 		memset(&ppdu_info, 0, sizeof(ppdu_info));
 		ppdu_info.peer_id = HAL_INVALID_PEERID;
 
-		if (!ar->debug.pktlog_peer_valid) {
-			/* TODO update the pktlog tracing */
-		}
-
 		hal_status = ath11k_hal_rx_parse_mon_status(ab, &ppdu_info,
 							    (u8 *)skb->data);
 
@@ -2303,11 +2346,6 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
 
 		arsta = (struct ath11k_sta *)peer->sta->drv_priv;
 		ath11k_dp_rx_update_peer_stats(arsta, &ppdu_info);
-
-		if (ar->debug.pktlog_peer_valid &&
-		    ether_addr_equal(peer->addr, ar->debug.pktlog_peer_addr)) {
-			/* TODO update the pktlog tracing for one peer*/
-		}
 		spin_unlock_bh(&ab->data_lock);
 		rcu_read_unlock();
 
@@ -3079,14 +3117,127 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id)
 		return ret;
 	}
 
+	ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id;
+	ret = ath11k_dp_htt_srng_setup(ab, ring_id,
+				       mac_id, HAL_RXDMA_MONITOR_BUF);
+	if (ret) {
+		ath11k_warn(ab, "failed to configure rxdma_mon_buf_ring %d\n",
+			    ret);
+		return ret;
+	}
+	ret = ath11k_dp_htt_srng_setup(ab,
+				       dp->rxdma_mon_dst_ring.ring_id,
+				       mac_id, HAL_RXDMA_MONITOR_DST);
+	if (ret) {
+		ath11k_warn(ab, "failed to configure rxdma_mon_dst_ring %d\n",
+			    ret);
+		return ret;
+	}
+	ret = ath11k_dp_htt_srng_setup(ab,
+				       dp->rxdma_mon_desc_ring.ring_id,
+				       mac_id, HAL_RXDMA_MONITOR_DESC);
+	if (ret) {
+		ath11k_warn(ab, "failed to configure rxdma_mon_dst_ring %d\n",
+			    ret);
+		return ret;
+	}
 	ring_id = dp->rx_mon_status_refill_ring.refill_buf_ring.ring_id;
 	ret = ath11k_dp_htt_srng_setup(ab, ring_id, mac_id,
 				       HAL_RXDMA_MONITOR_STATUS);
 	if (ret) {
-		ath11k_warn(ab, "failed to configure rx_mon_status_refill_ring %d\n",
+		ath11k_warn(ab,
+			    "failed to configure mon_status_refill_ring %d\n",
 			    ret);
 		return ret;
 	}
+	return 0;
+}
+
+static inline bool ath11k_get_rx_status_done(u8 *rx_tlv)
+{
+	struct hal_tlv_hdr *thdr = (struct hal_tlv_hdr *)rx_tlv;
+	u32 tlv_tag;
+
+	tlv_tag = FIELD_GET(HAL_TLV_HDR_TAG, thdr->tl);
+
+	return (tlv_tag == HAL_RX_STATUS_BUFFER_DONE);
+}
+
+static inline void ath11k_dp_mon_set_frag_len(u32 *total_len, u32 *frag_len)
+{
+	if (*total_len >= (DP_RX_BUFFER_SIZE - sizeof(struct hal_rx_desc))) {
+		*frag_len = DP_RX_BUFFER_SIZE - sizeof(struct hal_rx_desc);
+		*total_len -= *frag_len;
+	} else {
+		*frag_len = *total_len;
+		*total_len = 0;
+	}
+}
 
+static inline
+int ath11k_dp_rx_monitor_link_desc_return(struct ath11k *ar,
+					  void *p_last_buf_addr_info,
+					  u8 mac_id)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct dp_srng *dp_srng;
+	void *hal_srng;
+	void *src_srng_desc;
+	int ret = 0;
+
+	dp_srng = &dp->rxdma_mon_desc_ring;
+	hal_srng = &ar->ab->hal.srng_list[dp_srng->ring_id];
+
+	ath11k_hal_srng_access_begin(ar->ab, hal_srng);
+
+	src_srng_desc = ath11k_hal_srng_src_get_next_entry(ar->ab, hal_srng);
+
+	if (src_srng_desc) {
+		struct buffer_addr *src_desc =
+				(struct buffer_addr *)src_srng_desc;
+
+		*src_desc = *((struct buffer_addr *)p_last_buf_addr_info);
+	} else {
+		ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+			   "Monitor Link Desc Ring %d Full", mac_id);
+		ret = -ENOMEM;
+	}
+
+	ath11k_hal_srng_access_end(ar->ab, hal_srng);
+	return ret;
+}
+
+static inline
+void ath11k_dp_rx_mon_next_link_desc_get(void *rx_msdu_link_desc,
+					 dma_addr_t *paddr, u32 *sw_cookie,
+					 void **pp_buf_addr_info)
+{
+	struct hal_rx_msdu_link *msdu_link =
+			(struct hal_rx_msdu_link *)rx_msdu_link_desc;
+	struct buffer_addr *buf_addr_info;
+	u8 rbm = 0;
+
+	buf_addr_info = (struct buffer_addr *)&msdu_link->buf_addr_info;
+
+	ath11k_hal_rx_buf_addr_info_get(buf_addr_info, paddr, sw_cookie, &rbm);
+
+	*pp_buf_addr_info = (void *)buf_addr_info;
+}
+
+static inline int ath11k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len)
+{
+	if (skb->len > len) {
+		skb_trim(skb, len);
+	} else {
+		if (skb_tailroom(skb) < len - skb->len) {
+			if ((pskb_expand_head(skb, 0,
+					      len - skb->len - skb_tailroom(skb),
+					      GFP_ATOMIC))) {
+				dev_kfree_skb_any(skb);
+				return -ENOMEM;
+			}
+		}
+		skb_put(skb, (len - skb->len));
+	}
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.h b/drivers/net/wireless/ath/ath11k/dp_rx.h
index a8fb57f..cc66bc9 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.h
@@ -296,6 +296,54 @@ static inline void ath11k_dp_rx_desc_end_tlv_copy(u8 *first, u8 *last)
 	       sizeof(struct rx_mpdu_end));
 }
 
+static inline u32 ath11k_dp_rxdesc_get_mpdulen_err(void *hw_desc_addr)
+{
+	struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)hw_desc_addr;
+	struct rx_attention *rx_attn;
+
+	rx_attn = &rx_desc->attention;
+
+	return FIELD_GET(RX_ATTENTION_INFO1_MPDU_LEN_ERR, rx_attn->info1);
+}
+
+static inline u32 ath11k_dp_rxdesc_get_decap_format(void *hw_desc_addr)
+{
+	struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)hw_desc_addr;
+	struct rx_msdu_start *rx_msdu_start;
+
+	rx_msdu_start = &rx_desc->msdu_start;
+
+	return FIELD_GET(RX_MSDU_START_INFO2_DECAP_FORMAT,
+			rx_msdu_start->info2);
+}
+
+static inline u8 *ath11k_dp_rxdesc_get_80211hdr(void *hw_desc_addr)
+{
+	struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)hw_desc_addr;
+	u8 *rx_pkt_hdr;
+
+	rx_pkt_hdr = &rx_desc->msdu_payload[0];
+
+	return rx_pkt_hdr;
+}
+
+static inline bool ath11k_dp_rxdesc_mpdu_valid(void *hw_desc_addr)
+{
+	struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)hw_desc_addr;
+	u32 tlv_tag;
+
+	tlv_tag = FIELD_GET(HAL_TLV_HDR_TAG, rx_desc->mpdu_start_tag);
+
+	return tlv_tag == HAL_RX_MPDU_START ? true : false;
+}
+
+static inline u32 ath11k_dp_rxdesc_get_ppduid(void *hw_desc_addr)
+{
+	struct hal_rx_desc *rx_desc = (struct hal_rx_desc *)hw_desc_addr;
+
+	return rx_desc->mpdu_start.phy_ppdu_id;
+}
+
 int ath11k_dp_rx_ampdu_start(struct ath11k *ar,
 			     struct ieee80211_ampdu_params *params);
 int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
@@ -330,11 +378,16 @@ int ath11k_dp_htt_rx_filter_setup(struct ath11k_base *ab, u32 ring_id,
 				  int mac_id, enum hal_ring_type ring_type,
 				  int rx_buf_size,
 				  struct htt_rx_ring_tlv_filter *tlv_filter);
+int ath11k_dp_rx_process_mon_rings(struct ath11k_base *ab, int mac_id,
+				   struct napi_struct *napi, int budget);
 int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
 				    struct napi_struct *napi, int budget);
 int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id,
-					   struct dp_rxdma_ring *rx_ring,
-					   int req_entries,
-					   enum hal_rx_buf_return_buf_manager mgr,
-					   gfp_t gfp);
+					struct dp_rxdma_ring *rx_ring,
+					int req_entries,
+					enum hal_rx_buf_return_buf_manager mgr,
+					gfp_t gfp);
+int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar);
+int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar);
+
 #endif /* ATH11K_DP_RX_H */
-- 
2.7.4


_______________________________________________
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 4/6] ath11k: monitor mode attach/detach
  2019-04-16  0:12 [PATCH v5 0/6] ath11k: add monitor mode support Miles Hu
                   ` (2 preceding siblings ...)
  2019-04-16  0:12 ` [PATCH v5 3/6] ath11k: htt setup monitor rings Miles Hu
@ 2019-04-16  0:12 ` Miles Hu
  2019-04-16  0:12 ` [PATCH v5 5/6] ath11k: enable/disable monitor mode and destination ring entry process Miles Hu
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Miles Hu @ 2019-04-16  0:12 UTC (permalink / raw)
  To: ath11k; +Cc: Miles Hu

create monitor mode attach/detach function.
call attach/detach functions in pdev alloc/free.
add monitor napi function.

Signed-off-by: Miles Hu <milehu@codeaurora.org>
---
V2:
 - fix warn message style and remove __func__, __LINE__.

 drivers/net/wireless/ath/ath11k/dp.c    |  22 +++++
 drivers/net/wireless/ath/ath11k/dp_rx.c | 153 ++++++++++++++++++++++++++++++++
 2 files changed, 175 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index 5fa01c1..15bb27c 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -648,6 +648,21 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
 		}
 	}
 
+	if (rx_mon_status_ring_mask[grp_id]) {
+		for (i = 0; i <  ab->num_radios; i++) {
+			if (rx_mon_status_ring_mask[grp_id] & BIT(i)) {
+				work_done =
+				ath11k_dp_rx_process_mon_rings(ab,
+							       i, napi,
+							       budget);
+				budget -= work_done;
+				tot_work_done += work_done;
+			}
+			if (budget <= 0)
+				goto done;
+		}
+	}
+
 	if (ath11k_reo_status_ring_mask[grp_id])
 		ath11k_dp_process_reo_status(ab);
 
@@ -685,6 +700,7 @@ void ath11k_dp_pdev_free(struct ath11k_base *ab)
 		ar = ab->pdevs[i].ar;
 		ath11k_dp_rx_pdev_free(ab, i);
 		ath11k_debug_unregister(ar);
+		ath11k_dp_rx_pdev_mon_detach(ar);
 	}
 }
 
@@ -718,6 +734,12 @@ int ath11k_dp_pdev_alloc(struct ath11k_base *ab)
 				    i);
 			goto err;
 		}
+		ret = ath11k_dp_rx_pdev_mon_attach(ar);
+		if (ret) {
+			ath11k_warn(ab, "failed to initialize mon pdev %d\n",
+				    i);
+			goto err;
+		}
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 2605b2b..c0c21a8 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -3241,3 +3241,156 @@ static inline int ath11k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len)
 	}
 	return 0;
 }
+
+static inline void
+ath11k_hal_rx_msdu_list_get(struct ath11k *ar,
+			    void *msdu_link_desc,
+			    struct hal_rx_msdu_list *msdu_list,
+			    u16 *num_msdus)
+{
+	struct hal_rx_msdu_details *msdu_details = NULL;
+	struct rx_msdu_desc *msdu_desc_info = NULL;
+	struct hal_rx_msdu_link *msdu_link = NULL;
+	int i;
+	u32 last = FIELD_PREP(RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU, 1);
+	u32 first = FIELD_PREP(RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU, 1);
+	u8  tmp  = 0;
+
+	msdu_link = (struct hal_rx_msdu_link *)msdu_link_desc;
+	msdu_details = &msdu_link->msdu_link[0];
+
+	for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) {
+		if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR,
+			      msdu_details[i].buf_addr_info.info0) == 0) {
+			msdu_desc_info = &msdu_details[i - 1].rx_msdu_info;
+			msdu_desc_info->info0 |= last;
+			;
+			break;
+		}
+		msdu_desc_info = &msdu_details[i].rx_msdu_info;
+
+		if (!i)
+			msdu_desc_info->info0 |= first;
+		else if (i == (HAL_RX_NUM_MSDU_DESC - 1))
+			msdu_desc_info->info0 |= last;
+		msdu_list->msdu_info[i].msdu_flags = msdu_desc_info->info0;
+		msdu_list->msdu_info[i].msdu_len =
+			 HAL_RX_MSDU_PKT_LENGTH_GET(msdu_desc_info->info0);
+		msdu_list->sw_cookie[i] =
+			FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE,
+				  msdu_details[i].buf_addr_info.info1);
+		tmp = FIELD_GET(BUFFER_ADDR_INFO1_RET_BUF_MGR,
+				msdu_details[i].buf_addr_info.info1);
+		msdu_list->rbm[i] = tmp;
+	}
+	*num_msdus = i;
+}
+
+static inline u32 ath11k_dp_rx_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id,
+					       u32 *rx_bufs_used)
+{
+	u32 ret = 0;
+
+	if ((*ppdu_id < msdu_ppdu_id) &&
+	    ((msdu_ppdu_id - *ppdu_id) < DP_NOT_PPDU_ID_WRAP_AROUND)) {
+		*ppdu_id = msdu_ppdu_id;
+		ret = msdu_ppdu_id;
+	} else if ((*ppdu_id > msdu_ppdu_id) &&
+		((*ppdu_id - msdu_ppdu_id) > DP_NOT_PPDU_ID_WRAP_AROUND)) {
+		/* mon_dst is behind than mon_status
+		 * skip dst_ring and free it
+		 */
+		*rx_bufs_used += 1;
+		*ppdu_id = msdu_ppdu_id;
+		ret = msdu_ppdu_id;
+	}
+	return ret;
+}
+
+static inline void ath11k_dp_mon_get_buf_len(struct hal_rx_msdu_desc_info *info,
+					     bool *is_frag, u32 *total_len,
+					     u32 *frag_len, u32 *msdu_cnt)
+{
+	if (info->msdu_flags & RX_MSDU_DESC_INFO0_MSDU_CONTINUATION) {
+		if (!*is_frag) {
+			*total_len = info->msdu_len;
+			*is_frag = true;
+		}
+		ath11k_dp_mon_set_frag_len(total_len,
+					   frag_len);
+	} else {
+		if (*is_frag) {
+			ath11k_dp_mon_set_frag_len(total_len,
+						   frag_len);
+		} else {
+			*frag_len = info->msdu_len;
+		}
+		*is_frag = false;
+		*msdu_cnt -= 1;
+	}
+}
+
+int ath11k_dp_rx_pdev_mon_status_attach(struct ath11k *ar)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
+
+	skb_queue_head_init(&pmon->rx_status_q);
+
+	pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
+
+	memset(&pmon->rx_mon_stats, 0,
+	       sizeof(pmon->rx_mon_stats));
+	return 0;
+}
+
+int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct ath11k_mon_data *pmon = &dp->mon_data;
+	struct hal_srng *mon_desc_srng = NULL;
+	struct dp_srng *dp_srng;
+	int ret = 0;
+	u32 n_link_desc = 0;
+
+	ret = ath11k_dp_rx_pdev_mon_status_attach(ar);
+	if (ret) {
+		ath11k_warn(ar->ab, "pdev_mon_status_attach() failed");
+		return ret;
+	}
+
+	dp_srng = &dp->rxdma_mon_desc_ring;
+	n_link_desc = dp_srng->size /
+		ath11k_hal_srng_get_entrysize(HAL_RXDMA_MONITOR_DESC);
+	mon_desc_srng =
+		&ar->ab->hal.srng_list[dp->rxdma_mon_desc_ring.ring_id];
+
+	ret = ath11k_dp_link_desc_setup(ar->ab, pmon->link_desc_banks,
+					HAL_RXDMA_MONITOR_DESC, mon_desc_srng,
+					n_link_desc);
+	if (ret) {
+		ath11k_warn(ar->ab, "mon_link_desc_pool_setup() failed");
+		return ret;
+	}
+	pmon->mon_last_linkdesc_paddr = 0;
+	pmon->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1;
+	spin_lock_init(&pmon->mon_lock);
+	return 0;
+}
+
+int ath11k_dp_mon_link_free(struct ath11k *ar)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct ath11k_mon_data *pmon = &dp->mon_data;
+
+	ath11k_dp_link_desc_cleanup(ar->ab, pmon->link_desc_banks,
+				    HAL_RXDMA_MONITOR_DESC,
+				    &dp->rxdma_mon_desc_ring);
+	return 0;
+}
+
+int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar)
+{
+	ath11k_dp_mon_link_free(ar);
+	return 0;
+}
-- 
2.7.4


_______________________________________________
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 5/6] ath11k: enable/disable monitor mode and destination ring entry process
  2019-04-16  0:12 [PATCH v5 0/6] ath11k: add monitor mode support Miles Hu
                   ` (3 preceding siblings ...)
  2019-04-16  0:12 ` [PATCH v5 4/6] ath11k: monitor mode attach/detach Miles Hu
@ 2019-04-16  0:12 ` Miles Hu
  2019-04-16  0:12 ` [PATCH v5 6/6] ath11k: merge msdu tlv process and status/destination ring process Miles Hu
  2019-04-23 14:05 ` [PATCH v5 0/6] ath11k: add monitor mode support Kalle Valo
  6 siblings, 0 replies; 8+ messages in thread
From: Miles Hu @ 2019-04-16  0:12 UTC (permalink / raw)
  To: ath11k; +Cc: Miles Hu

enable/disable monitor mode in mac.c.
fix bug in ring_peek function.
add destination ring entry process function.

Signed-off-by: Miles Hu <milehu@codeaurora.org>
---
V2:
 - fix warn message style and remove __func__, __LINE__.
 - remove likely and unlikely.

V4:
 - change bool to atomic_t to add protection
 - remove unnecessary print

V5:
 - replace atomic_t by atomic bitmask

 drivers/net/wireless/ath/ath11k/dp_rx.c  | 184 +++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/hal.c    |   2 +-
 drivers/net/wireless/ath/ath11k/hal_rx.c |  28 +++++
 drivers/net/wireless/ath/ath11k/mac.c    |  40 ++++++-
 4 files changed, 252 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index c0c21a8..ca4ffdf 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -3330,6 +3330,190 @@ static inline void ath11k_dp_mon_get_buf_len(struct hal_rx_msdu_desc_info *info,
 	}
 }
 
+u32
+ath11k_dp_rx_mon_mpdu_pop(struct ath11k *ar,
+			  void *ring_entry, struct sk_buff **head_msdu,
+			  struct sk_buff **tail_msdu, u32 *npackets,
+			  u32 *ppdu_id)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
+	struct dp_rxdma_ring *rx_ring = &dp->rxdma_mon_buf_ring;
+	struct sk_buff *msdu, *last;
+	struct hal_rx_msdu_list msdu_list;
+	void *p_buf_addr_info, *p_last_buf_addr_info;
+	void *rx_desc;
+	void *rx_msdu_link_desc;
+	dma_addr_t paddr;
+	u16 num_msdus = 0;
+	u32 rx_buf_size, rx_pkt_offset, sw_cookie;
+	u32 rx_bufs_used = 0, i = 0;
+	u32 msdu_ppdu_id = 0, msdu_cnt = 0;
+	u32 total_len = 0, frag_len = 0;
+	u8 *data = NULL;
+	bool is_frag, is_first_msdu;
+	bool drop_mpdu = false;
+	struct ath11k_skb_rxcb *rxcb;
+	struct hal_reo_entrance_ring *ent_desc =
+			(struct hal_reo_entrance_ring *)ring_entry;
+	int buf_id;
+
+	msdu = 0;
+	last = NULL;
+
+	ath11k_hal_rx_reo_ent_buf_paddr_get(ring_entry, &paddr,
+					    &sw_cookie, &p_last_buf_addr_info,
+					    &msdu_cnt);
+
+	if (FIELD_GET(HAL_REO_ENTR_RING_INFO1_RXDMA_PUSH_REASON,
+		      ent_desc->info1) ==
+		      HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) {
+		u8 rxdma_err =
+			FIELD_GET(HAL_REO_ENTR_RING_INFO1_RXDMA_ERROR_CODE,
+				  ent_desc->info1);
+		if (rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR ||
+		    rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR ||
+		    rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR) {
+			drop_mpdu = true;
+			pmon->rx_mon_stats.dest_mpdu_drop++;
+		}
+	}
+
+	is_frag = false;
+	is_first_msdu = true;
+
+	do {
+		if (pmon->mon_last_linkdesc_paddr == paddr) {
+			pmon->rx_mon_stats.dup_mon_linkdesc_cnt++;
+			return rx_bufs_used;
+		}
+
+		rx_msdu_link_desc =
+			(void *)pmon->link_desc_banks[sw_cookie].vaddr +
+			(paddr - pmon->link_desc_banks[sw_cookie].paddr);
+
+		ath11k_hal_rx_msdu_list_get(ar, rx_msdu_link_desc, &msdu_list,
+					    &num_msdus);
+
+		for (i = 0; i < num_msdus; i++) {
+			u32 l2_hdr_offset;
+
+			if (pmon->mon_last_buf_cookie == msdu_list.sw_cookie[i]) {
+				ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+					   "i %d last_cookie %d is same\n",
+					   i, pmon->mon_last_buf_cookie);
+				drop_mpdu = true;
+				pmon->rx_mon_stats.dup_mon_buf_cnt++;
+				continue;
+			}
+			buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID,
+					   msdu_list.sw_cookie[i]);
+
+			spin_lock_bh(&rx_ring->idr_lock);
+			msdu = idr_find(&rx_ring->bufs_idr, buf_id);
+			spin_unlock_bh(&rx_ring->idr_lock);
+			if (!msdu) {
+				ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+					   "msdu_pop: invalid buf_id %d\n", buf_id);
+				break;
+			}
+			rxcb = ATH11K_SKB_RXCB(msdu);
+			if (!rxcb->unmapped) {
+				dma_unmap_single(ar->ab->dev, rxcb->paddr,
+						 msdu->len +
+						 skb_tailroom(msdu),
+						 DMA_FROM_DEVICE);
+				rxcb->unmapped = 1;
+			}
+			if (drop_mpdu) {
+				ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+					   "i %d drop msdu %p *ppdu_id %x\n",
+					   i, msdu, *ppdu_id);
+				dev_kfree_skb_any(msdu);
+				msdu = NULL;
+				goto next_msdu;
+			}
+			data = msdu->data;
+			rx_desc = msdu->data;
+
+			rx_pkt_offset = sizeof(struct hal_rx_desc);
+			l2_hdr_offset =
+				ath11k_dp_rx_h_msdu_end_l3pad(msdu->data);
+
+			if (is_first_msdu) {
+				if (!ath11k_dp_rxdesc_mpdu_valid(rx_desc)) {
+					drop_mpdu = true;
+					dev_kfree_skb_any(msdu);
+					msdu = NULL;
+					pmon->mon_last_linkdesc_paddr = paddr;
+					goto next_msdu;
+				}
+
+				msdu_ppdu_id =
+					ath11k_dp_rxdesc_get_ppduid(rx_desc);
+
+				if (ath11k_dp_rx_mon_comp_ppduid(msdu_ppdu_id,
+								 ppdu_id,
+								 &rx_bufs_used))
+					return rx_bufs_used;
+				pmon->mon_last_linkdesc_paddr = paddr;
+				is_first_msdu = false;
+			}
+			ath11k_dp_mon_get_buf_len(&msdu_list.msdu_info[i],
+						  &is_frag, &total_len,
+						  &frag_len, &msdu_cnt);
+			rx_buf_size = rx_pkt_offset + l2_hdr_offset + frag_len;
+
+			ath11k_dp_pkt_set_pktlen(msdu, rx_buf_size);
+
+			if (!(*head_msdu))
+				*head_msdu = msdu;
+			else if (last)
+				last->next = msdu;
+
+			last = msdu;
+next_msdu:
+			pmon->mon_last_buf_cookie = msdu_list.sw_cookie[i];
+			rx_bufs_used++;
+			spin_lock_bh(&rx_ring->idr_lock);
+			idr_remove(&rx_ring->bufs_idr, buf_id);
+			spin_unlock_bh(&rx_ring->idr_lock);
+		}
+
+		ath11k_dp_rx_mon_next_link_desc_get(rx_msdu_link_desc, &paddr,
+						    &sw_cookie,
+						    &p_buf_addr_info);
+
+		if (ath11k_dp_rx_monitor_link_desc_return(ar,
+							  p_last_buf_addr_info,
+							  dp->mac_id))
+			ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+				   "dp_rx_monitor_link_desc_return failed");
+
+		p_last_buf_addr_info = p_buf_addr_info;
+
+	} while (paddr && msdu_cnt);
+
+	if (last)
+		last->next = NULL;
+
+	*tail_msdu = msdu;
+
+	if (msdu_cnt == 0)
+		*npackets = 1;
+
+	return rx_bufs_used;
+}
+
+static inline void ath11k_dp_rx_msdus_set_payload(struct sk_buff *msdu)
+{
+	u32 rx_pkt_offset, l2_hdr_offset;
+
+	rx_pkt_offset = sizeof(struct hal_rx_desc);
+	l2_hdr_offset = ath11k_dp_rx_h_msdu_end_l3pad(msdu->data);
+	skb_pull(msdu, rx_pkt_offset + l2_hdr_offset);
+}
+
 int ath11k_dp_rx_pdev_mon_status_attach(struct ath11k *ar)
 {
 	struct ath11k_pdev_dp *dp = &ar->dp;
diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c
index 6888349f..3fe8f81 100644
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -706,7 +706,7 @@ u32 *ath11k_hal_srng_dst_peek(struct ath11k_base *ab, struct hal_srng *srng)
 	lockdep_assert_held(&srng->lock);
 
 	if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp)
-		return ((void *)srng->ring_base_vaddr + srng->u.dst_ring.tp);
+		return (srng->ring_base_vaddr + srng->u.dst_ring.tp);
 
 	return NULL;
 }
diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.c b/drivers/net/wireless/ath/ath11k/hal_rx.c
index 2bdb532..98e8bee 100644
--- a/drivers/net/wireless/ath/ath11k/hal_rx.c
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c
@@ -1201,3 +1201,31 @@ ath11k_hal_rx_parse_mon_status(struct ath11k_base *ab,
 
 	return hal_status;
 }
+
+void ath11k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr,
+					 u32 *sw_cookie, void **pp_buf_addr,
+					 u32  *msdu_cnt)
+{
+	struct hal_reo_entrance_ring *reo_ent_ring =
+		(struct hal_reo_entrance_ring *)rx_desc;
+	struct buffer_addr *buf_addr_info;
+	struct rx_mpdu_desc *rx_mpdu_desc_info_details;
+
+	rx_mpdu_desc_info_details =
+			(struct rx_mpdu_desc *)&reo_ent_ring->rx_mpdu_info;
+
+	*msdu_cnt = FIELD_GET(RX_MPDU_DESC_INFO0_MSDU_COUNT,
+			      rx_mpdu_desc_info_details->info0);
+
+	buf_addr_info = (struct buffer_addr *)&reo_ent_ring->buf_addr_info;
+
+	*paddr = (((u64)FIELD_GET(BUFFER_ADDR_INFO1_ADDR,
+				  buf_addr_info->info1)) << 32) |
+			FIELD_GET(BUFFER_ADDR_INFO0_ADDR,
+				  buf_addr_info->info0);
+
+	*sw_cookie = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE,
+			       buf_addr_info->info1);
+
+	*pp_buf_addr = (void *)buf_addr_info;
+}
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 5196fb7..c311833 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -769,6 +769,21 @@ static void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id)
 	spin_unlock_bh(&ab->data_lock);
 }
 
+static int ath11k_monitor_vdev_up(struct ath11k *ar, int vdev_id)
+{
+	int ret = 0;
+
+	ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
+	if (ret) {
+		ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
+			    vdev_id, ret);
+		return ret;
+	}
+
+	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %i started\n",
+		   vdev_id);
+	return 0;
+}
 static int ath11k_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct ath11k *ar = hw->priv;
@@ -3439,6 +3454,9 @@ static int ath11k_add_interface(struct ieee80211_hw *hw,
 	case NL80211_IFTYPE_AP:
 		arvif->vdev_type = WMI_VDEV_TYPE_AP;
 		break;
+	case NL80211_IFTYPE_MONITOR:
+		arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
+		break;
 	default:
 		WARN_ON(1);
 		break;
@@ -3644,6 +3662,7 @@ static void ath11k_remove_interface(struct ieee80211_hw *hw,
 
 	/* Recalc txpower for remaining vdev */
 	ath11k_mac_txpower_recalc(ar);
+	clear_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
 
 	/* TODO: recal traffic pause state based on the available vdevs */
 
@@ -3666,6 +3685,8 @@ static void ath11k_configure_filter(struct ieee80211_hw *hw,
 				    u64 multicast)
 {
 	struct ath11k *ar = hw->priv;
+	bool reset_flag = false;
+	int ret = 0;
 
 	mutex_lock(&ar->conf_mutex);
 
@@ -3673,8 +3694,19 @@ static void ath11k_configure_filter(struct ieee80211_hw *hw,
 	*total_flags &= SUPPORTED_FILTERS;
 	ar->filter_flags = *total_flags;
 
-	/* TODO: Send filter configuration to target as appropriate */
+	/* For monitor mode */
+	reset_flag = !(ar->filter_flags & FIF_BCN_PRBRESP_PROMISC);
 
+	ret = ath11k_dp_htt_monitor_mode_ring_config(ar, reset_flag);
+	if (!ret) {
+		if (!reset_flag)
+			set_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
+		else
+			clear_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
+	} else {
+		ath11k_warn(ar->ab,
+			    "fail to set monitor filter: %d\n", ret);
+	}
 	mutex_unlock(&ar->conf_mutex);
 }
 
@@ -4119,6 +4151,11 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 			    ctx->def.chan->center_freq, ret);
 		goto err;
 	}
+	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+		ret = ath11k_monitor_vdev_up(ar, arvif->vdev_id);
+		if (ret)
+			goto err;
+	}
 
 	arvif->is_started = true;
 
@@ -5026,6 +5063,7 @@ int ath11k_mac_create(struct ath11k_base *ab)
 
 		INIT_WORK(&ar->wmi_mgmt_tx_work, ath11k_mgmt_over_wmi_tx_work);
 		skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
+		clear_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags);
 
 		ret = ath11k_mac_register(ar);
 		if (ret) {
-- 
2.7.4


_______________________________________________
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 6/6] ath11k: merge msdu tlv process and status/destination ring process
  2019-04-16  0:12 [PATCH v5 0/6] ath11k: add monitor mode support Miles Hu
                   ` (4 preceding siblings ...)
  2019-04-16  0:12 ` [PATCH v5 5/6] ath11k: enable/disable monitor mode and destination ring entry process Miles Hu
@ 2019-04-16  0:12 ` Miles Hu
  2019-04-23 14:05 ` [PATCH v5 0/6] ath11k: add monitor mode support Kalle Valo
  6 siblings, 0 replies; 8+ messages in thread
From: Miles Hu @ 2019-04-16  0:12 UTC (permalink / raw)
  To: ath11k; +Cc: Miles Hu

merge msdu list and process status.
deliver mpdu to upper layer.
process tlv in rx descriptor.
status/destination ring process function.

Signed-off-by: Miles Hu <milehu@codeaurora.org>
---
V2:
 - fix warn message style and remove __func__, __LINE__.
 - remove likely and unlikely.

V3:
 - create common ring reap function for peer-stats and monitor mode.

V4:
 - change bool to atomic_t to add protection

V5:
 - replace atomic_t by atomic bitmask

 drivers/net/wireless/ath/ath11k/dp_rx.c | 293 +++++++++++++++++++++++++++++++-
 1 file changed, 292 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index ca4ffdf..a26654f 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -3330,7 +3330,7 @@ static inline void ath11k_dp_mon_get_buf_len(struct hal_rx_msdu_desc_info *info,
 	}
 }
 
-u32
+static u32
 ath11k_dp_rx_mon_mpdu_pop(struct ath11k *ar,
 			  void *ring_entry, struct sk_buff **head_msdu,
 			  struct sk_buff **tail_msdu, u32 *npackets,
@@ -3514,6 +3514,297 @@ static inline void ath11k_dp_rx_msdus_set_payload(struct sk_buff *msdu)
 	skb_pull(msdu, rx_pkt_offset + l2_hdr_offset);
 }
 
+static inline struct sk_buff *
+ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar,
+			    u32 mac_id, struct sk_buff *head_msdu,
+			    struct sk_buff *last_msdu,
+			    struct ieee80211_rx_status *rxs)
+{
+	struct sk_buff *msdu, *mpdu_buf, *prev_buf;
+	u32 decap_format, wifi_hdr_len;
+	void *rx_desc;
+	char *hdr_desc;
+	u8 *dest;
+	struct ieee80211_hdr_3addr *wh;
+
+	mpdu_buf = NULL;
+
+	if (!head_msdu)
+		goto err_merge_fail;
+
+	rx_desc = head_msdu->data;
+
+	if (ath11k_dp_rxdesc_get_mpdulen_err(rx_desc))
+		return NULL;
+
+	decap_format = ath11k_dp_rxdesc_get_decap_format(rx_desc);
+
+	ath11k_dp_rx_h_ppdu(ar, rx_desc, rxs);
+
+	if (decap_format == DP_RX_DECAP_TYPE_RAW) {
+		ath11k_dp_rx_msdus_set_payload(head_msdu);
+
+		prev_buf = head_msdu;
+		msdu = head_msdu->next;
+
+		while (msdu) {
+			ath11k_dp_rx_msdus_set_payload(msdu);
+
+			prev_buf = msdu;
+			msdu = msdu->next;
+		}
+
+		prev_buf->next = NULL;
+
+		skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN);
+	}	else if (decap_format == DP_RX_DECAP_TYPE_NATIVE_WIFI) {
+		__le16 qos_field;
+		u8 qos_pkt = 0;
+
+		rx_desc = head_msdu->data;
+		hdr_desc = ath11k_dp_rxdesc_get_80211hdr(rx_desc);
+
+		/* Base size */
+		wifi_hdr_len = sizeof(struct ieee80211_hdr_3addr);
+		wh = (struct ieee80211_hdr_3addr *)hdr_desc;
+
+		if (ieee80211_is_data_qos(wh->frame_control)) {
+			struct ieee80211_qos_hdr *qwh =
+					(struct ieee80211_qos_hdr *)hdr_desc;
+
+			qos_field = qwh->qos_ctrl;
+			qos_pkt = 1;
+		}
+		msdu = head_msdu;
+
+		while (msdu) {
+			rx_desc = msdu->data;
+			hdr_desc = ath11k_dp_rxdesc_get_80211hdr(rx_desc);
+
+			if (qos_pkt) {
+				dest = skb_push(msdu, sizeof(__le16));
+				if (!dest)
+					goto err_merge_fail;
+				memcpy(dest, hdr_desc, wifi_hdr_len);
+				memcpy(dest + wifi_hdr_len,
+				       (u8 *)&qos_field, sizeof(__le16));
+			}
+			ath11k_dp_rx_msdus_set_payload(msdu);
+			prev_buf = msdu;
+			msdu = msdu->next;
+		}
+		dest = skb_put(prev_buf, HAL_RX_FCS_LEN);
+		if (!dest)
+			goto err_merge_fail;
+
+		ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+			   "mpdu_buf %pK mpdu_buf->len %u",
+			   prev_buf, prev_buf->len);
+	} else {
+		ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+			   "decap format %d is not supported!\n",
+			   decap_format);
+		goto err_merge_fail;
+	}
+
+	return head_msdu;
+
+err_merge_fail:
+	if (mpdu_buf && decap_format != DP_RX_DECAP_TYPE_RAW) {
+		ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+			   "err_merge_fail mpdu_buf %pK", mpdu_buf);
+		/* Free the head buffer */
+		dev_kfree_skb_any(mpdu_buf);
+	}
+	return NULL;
+}
+
+int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id,
+			     struct sk_buff *head_msdu,
+			     struct sk_buff *tail_msdu,
+			     struct napi_struct *napi)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct sk_buff *mon_skb, *skb_next, *header;
+	struct ieee80211_rx_status *rxs = &dp->rx_status, *status;
+
+	mon_skb = ath11k_dp_rx_mon_merg_msdus(ar, mac_id, head_msdu,
+					      tail_msdu, rxs);
+
+	if (!mon_skb)
+		goto mon_deliver_fail;
+
+	header = mon_skb;
+
+	do {
+		skb_next = mon_skb->next;
+		if (!skb_next)
+			rxs->flag &= ~RX_FLAG_AMSDU_MORE;
+		else
+			rxs->flag |= RX_FLAG_AMSDU_MORE;
+
+		if (mon_skb == header) {
+			header = NULL;
+			rxs->flag &= ~RX_FLAG_ALLOW_SAME_PN;
+		} else {
+			rxs->flag |= RX_FLAG_ALLOW_SAME_PN;
+		}
+		rxs->flag |= RX_FLAG_ONLY_MONITOR;
+
+		status = IEEE80211_SKB_RXCB(mon_skb);
+		*status = *rxs;
+
+		ath11k_dp_rx_deliver_msdu(ar, napi, mon_skb);
+		mon_skb = skb_next;
+	} while (mon_skb && (mon_skb != tail_msdu));
+
+	return 0;
+
+mon_deliver_fail:
+	mon_skb = head_msdu;
+	while (mon_skb) {
+		skb_next = mon_skb->next;
+		dev_kfree_skb_any(mon_skb);
+		mon_skb = skb_next;
+	}
+	return -EINVAL;
+}
+
+void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, u32 quota,
+				   struct napi_struct *napi)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
+	void *ring_entry;
+	void *mon_dst_srng;
+	u32 ppdu_id;
+	u32 rx_bufs_used;
+	struct ath11k_pdev_mon_stats *rx_mon_stats;
+	u32	 npackets = 0;
+
+	mon_dst_srng = &ar->ab->hal.srng_list[dp->rxdma_mon_dst_ring.ring_id];
+
+	if (!mon_dst_srng) {
+		ath11k_warn(ar->ab,
+			    "HAL Monitor Destination Ring Init Failed -- %pK",
+			    mon_dst_srng);
+		return;
+	}
+
+	spin_lock_bh(&pmon->mon_lock);
+
+	ath11k_hal_srng_access_begin(ar->ab, mon_dst_srng);
+
+	ppdu_id = pmon->mon_ppdu_info.ppdu_id;
+	rx_bufs_used = 0;
+	rx_mon_stats = &pmon->rx_mon_stats;
+
+	while ((ring_entry = ath11k_hal_srng_dst_peek(ar->ab, mon_dst_srng))) {
+		struct sk_buff *head_msdu, *tail_msdu;
+
+		head_msdu = NULL;
+		tail_msdu = NULL;
+
+		rx_bufs_used += ath11k_dp_rx_mon_mpdu_pop(ar, ring_entry,
+							  &head_msdu,
+							  &tail_msdu,
+							  &npackets, &ppdu_id);
+
+		if (ppdu_id != pmon->mon_ppdu_info.ppdu_id) {
+			pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
+			ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+				   "dest_rx: new ppdu_id %x != status ppdu_id %x",
+				   ppdu_id, pmon->mon_ppdu_info.ppdu_id);
+			break;
+		}
+		if (head_msdu && tail_msdu) {
+			ath11k_dp_rx_mon_deliver(ar, dp->mac_id, head_msdu,
+						 tail_msdu, napi);
+			rx_mon_stats->dest_mpdu_done++;
+		}
+
+		ring_entry = ath11k_hal_srng_dst_get_next_entry(ar->ab,
+								mon_dst_srng);
+	}
+	ath11k_hal_srng_access_end(ar->ab, mon_dst_srng);
+
+	spin_unlock_bh(&pmon->mon_lock);
+
+	if (rx_bufs_used) {
+		rx_mon_stats->dest_ppdu_done++;
+		ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id,
+					   &dp->rxdma_mon_buf_ring,
+					   rx_bufs_used,
+					   HAL_RX_BUF_RBM_SW3_BM, GFP_ATOMIC);
+	}
+}
+
+static inline void ath11k_dp_rx_mon_status_process_tlv(struct ath11k *ar,
+						       u32 quota,
+						       struct napi_struct *napi)
+{
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
+	struct hal_rx_mon_ppdu_info *ppdu_info;
+	struct sk_buff *status_skb;
+	u8 *rx_tlv;
+	u8 *rx_tlv_start;
+	u32 tlv_status = HAL_TLV_STATUS_BUF_DONE;
+	struct ath11k_pdev_mon_stats *rx_mon_stats;
+
+	ppdu_info = &pmon->mon_ppdu_info;
+	rx_mon_stats = &pmon->rx_mon_stats;
+
+	if (pmon->mon_ppdu_status != DP_PPDU_STATUS_START)
+		return;
+
+	while (!skb_queue_empty(&pmon->rx_status_q)) {
+		status_skb = skb_dequeue(&pmon->rx_status_q);
+
+		rx_tlv = status_skb->data;
+		rx_tlv_start = rx_tlv;
+
+		tlv_status = ath11k_hal_rx_parse_mon_status(ar->ab, ppdu_info,
+							    rx_tlv);
+		if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) {
+			rx_mon_stats->status_ppdu_done++;
+			pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE;
+			ath11k_dp_rx_mon_dest_process(ar, quota, napi);
+			pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
+		}
+		dev_kfree_skb_any(status_skb);
+	}
+}
+
+int ath11k_dp_mon_process_rx(struct ath11k_base *ab, int mac_id,
+			     struct napi_struct *napi, int budget)
+{
+	struct ath11k *ar = ab->pdevs[mac_id].ar;
+	struct ath11k_pdev_dp *dp = &ar->dp;
+	struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
+	int num_buffs_reaped = 0;
+
+	num_buffs_reaped = ath11k_dp_rx_reap_mon_status_ring(ar->ab, dp->mac_id, &budget,
+							     &pmon->rx_status_q);
+	if (num_buffs_reaped)
+		ath11k_dp_rx_mon_status_process_tlv(ar, budget, napi);
+
+	return num_buffs_reaped;
+}
+
+int ath11k_dp_rx_process_mon_rings(struct ath11k_base *ab, int mac_id,
+				   struct napi_struct *napi, int budget)
+{
+	struct ath11k *ar = ab->pdevs[mac_id].ar;
+	int ret = 0;
+
+	if (test_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags))
+		ret = ath11k_dp_mon_process_rx(ab, mac_id, napi, budget);
+	else
+		ret = ath11k_dp_rx_process_mon_status(ab, mac_id, napi, budget);
+	return ret;
+}
+
 int ath11k_dp_rx_pdev_mon_status_attach(struct ath11k *ar)
 {
 	struct ath11k_pdev_dp *dp = &ar->dp;
-- 
2.7.4


_______________________________________________
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 0/6] ath11k: add monitor mode support
  2019-04-16  0:12 [PATCH v5 0/6] ath11k: add monitor mode support Miles Hu
                   ` (5 preceding siblings ...)
  2019-04-16  0:12 ` [PATCH v5 6/6] ath11k: merge msdu tlv process and status/destination ring process Miles Hu
@ 2019-04-23 14:05 ` Kalle Valo
  6 siblings, 0 replies; 8+ messages in thread
From: Kalle Valo @ 2019-04-23 14:05 UTC (permalink / raw)
  To: Miles Hu; +Cc: ath11k

Miles Hu <milehu@codeaurora.org> writes:

> Adding monitor mode in ath11k. It can be enabled
>  by commands below:
>
>   ifconfig wlan0 down
>   iw wlan0 set type monitor
>   ifconfig wlan0 up
>
> change channel:
>   iw wlan0 set freq 5805 80 5775
>
> Change summary:
> 1. create monitor status/destination/buffer/link descriptor rings.
> 2. enable these rings and push ring filters to buffer/status rings.
> 3. add napi entry point for monitor status and destination rings process.
> 4. implement monitor status/buffer rings replenish.
> 5. process entries from the status ring to get ppdu id and tlv status.
> 6. process entries from the destination ring by comparing ppdu id to build
>     msdu list.
> 7. merge msdu list to mpdu and copy rx status to cb.
> 8. deliver mpdu to upper layer.
>
> Known issues:
>  - Coexist with other interface type (AP/STA) not fully supported.
>  - higher data rates (11ax) not supported. radiotap needs proper info.
>  - signal strength and rate idx not accurate in some packets.

This does not apply:

Applying: ath11k: init/deinit monitor rings
fatal: sha1 information is lacking or useless (drivers/net/wireless/ath/ath11k/core.h).
error: could not build fake ancestor
Patch failed at 0001 ath11k: init/deinit monitor rings

And the sha1 id is incorrect so I can't use 3-way merge to correct it
myself. Please ALWAYS use the ath11k-bringup branch as the baseline and
make sure you don't have other patches applied, otherwise it will be
pain to handle conflicts.

-- 
Kalle Valo

_______________________________________________
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-04-23 14:05 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-16  0:12 [PATCH v5 0/6] ath11k: add monitor mode support Miles Hu
2019-04-16  0:12 ` [PATCH v5 1/6] ath11k: init/deinit monitor rings Miles Hu
2019-04-16  0:12 ` [PATCH v5 2/6] ath11k: monitor filter set function Miles Hu
2019-04-16  0:12 ` [PATCH v5 3/6] ath11k: htt setup monitor rings Miles Hu
2019-04-16  0:12 ` [PATCH v5 4/6] ath11k: monitor mode attach/detach Miles Hu
2019-04-16  0:12 ` [PATCH v5 5/6] ath11k: enable/disable monitor mode and destination ring entry process Miles Hu
2019-04-16  0:12 ` [PATCH v5 6/6] ath11k: merge msdu tlv process and status/destination ring process Miles Hu
2019-04-23 14:05 ` [PATCH v5 0/6] ath11k: add monitor mode support Kalle Valo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.