All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/6] ath11k: add monitor mode support
@ 2019-05-06 14:54 Miles Hu
  2019-05-06 14:54 ` [PATCH v3 1/6] ath11k: init/deinit monitor rings Miles Hu
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Miles Hu @ 2019-05-06 14:54 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:
 - Move to ath11k-bringup branch
V3:
 - Fix compile error on x86

 drivers/net/wireless/ath/ath11k/core.h     |   8 +-
 drivers/net/wireless/ath/ath11k/dp.c       | 111 ++--
 drivers/net/wireless/ath/ath11k/dp.h       | 189 ++++++-
 drivers/net/wireless/ath/ath11k/dp_rx.c    | 864 ++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath11k/dp_rx.h    |  61 +-
 drivers/net/wireless/ath/ath11k/dp_tx.c    | 179 +++---
 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, 1341 insertions(+), 163 deletions(-)

-- 
2.7.4


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

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

* [PATCH v3 1/6] ath11k: init/deinit monitor rings
  2019-05-06 14:54 [PATCH v3 0/6] ath11k: add monitor mode support Miles Hu
@ 2019-05-06 14:54 ` Miles Hu
  2019-05-08  9:50   ` Kalle Valo
  2019-05-06 14:54 ` [PATCH v3 2/6] ath11k: monitor filter set function Miles Hu
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Miles Hu @ 2019-05-06 14:54 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:
 - Move to ath11k-bringup branch
V3:
 - Fix compile error on x86

 drivers/net/wireless/ath/ath11k/core.h     |   8 +-
 drivers/net/wireless/ath/ath11k/dp.c       | 111 +++++++++--------
 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, 262 insertions(+), 68 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index c2068b5..c8c1cd6 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;
@@ -433,8 +438,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;
@@ -443,7 +448,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 5a7b480..2426b0b 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);
 
@@ -832,7 +833,9 @@ 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;
+	u32 n_link_desc = 0;
 	int ret;
 	int i;
 
@@ -842,7 +845,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;
@@ -877,7 +889,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 d4a68a8..b8a5b7c 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;
@@ -72,6 +73,59 @@ struct dp_tx_ring {
 	spinlock_t tx_status_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;
@@ -79,8 +133,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
@@ -95,18 +154,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
@@ -127,6 +174,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;
@@ -1324,4 +1471,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 4082c2f..b2f3332 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,
 				    struct htt_ext_stats_cfg_params *cfg_params,
 				    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] 9+ messages in thread

* [PATCH v3 2/6] ath11k: monitor filter set function
  2019-05-06 14:54 [PATCH v3 0/6] ath11k: add monitor mode support Miles Hu
  2019-05-06 14:54 ` [PATCH v3 1/6] ath11k: init/deinit monitor rings Miles Hu
@ 2019-05-06 14:54 ` Miles Hu
  2019-05-06 14:54 ` [PATCH v3 3/6] ath11k: htt setup monitor rings Miles Hu
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Miles Hu @ 2019-05-06 14:54 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:
 - Move to ath11k-bringup branch

 drivers/net/wireless/ath/ath11k/dp_tx.c | 179 +++++++++++++++++++-------------
 1 file changed, 107 insertions(+), 72 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 86e9d01..ffef794 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -553,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:
@@ -586,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 = 0;
+
+	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;
@@ -784,7 +798,7 @@ int ath11k_dp_htt_rx_filter_setup(struct ath11k_base *ab, u32 ring_id,
 	int len = sizeof(*cmd);
 	enum htt_srng_ring_type htt_ring_type;
 	enum htt_srng_ring_id htt_ring_id;
-	int ret;
+	int ret = 0;
 
 	skb = ath11k_htc_alloc_skb(ab, len);
 	if (!skb)
@@ -793,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;
@@ -830,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,
@@ -903,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] 9+ messages in thread

* [PATCH v3 3/6] ath11k: htt setup monitor rings
  2019-05-06 14:54 [PATCH v3 0/6] ath11k: add monitor mode support Miles Hu
  2019-05-06 14:54 ` [PATCH v3 1/6] ath11k: init/deinit monitor rings Miles Hu
  2019-05-06 14:54 ` [PATCH v3 2/6] ath11k: monitor filter set function Miles Hu
@ 2019-05-06 14:54 ` Miles Hu
  2019-05-06 14:54 ` [PATCH v3 4/6] ath11k: monitor mode attach/detach Miles Hu
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Miles Hu @ 2019-05-06 14:54 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:
 - Move to ath11k-bringup branch

 drivers/net/wireless/ath/ath11k/dp_rx.c | 236 ++++++++++++++++++++++++++++----
 drivers/net/wireless/ath/ath11k/dp_rx.h |  61 ++++++++-
 2 files changed, 265 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 257dd97..c9cb35a 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);
@@ -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;
 }
 
@@ -2200,21 +2253,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;
@@ -2222,13 +2270,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)
@@ -2268,7 +2316,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,
@@ -2293,6 +2341,25 @@ 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)
+{
+	struct ath11k *ar = ab->pdevs[mac_id].ar;
+	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;
 
@@ -3103,14 +3170,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] 9+ messages in thread

* [PATCH v3 4/6] ath11k: monitor mode attach/detach
  2019-05-06 14:54 [PATCH v3 0/6] ath11k: add monitor mode support Miles Hu
                   ` (2 preceding siblings ...)
  2019-05-06 14:54 ` [PATCH v3 3/6] ath11k: htt setup monitor rings Miles Hu
@ 2019-05-06 14:54 ` Miles Hu
  2019-05-06 14:54 ` [PATCH v3 5/6] ath11k: enable/disable monitor mode and destination ring entry process Miles Hu
  2019-05-06 14:54 ` [PATCH v3 6/6] ath11k: merge msdu tlv process and status/destination ring process Miles Hu
  5 siblings, 0 replies; 9+ messages in thread
From: Miles Hu @ 2019-05-06 14:54 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:
 - Move to ath11k-bringup branch

 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 2426b0b..2fddbef 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 c9cb35a..73cfe08 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -3294,3 +3294,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] 9+ messages in thread

* [PATCH v3 5/6] ath11k: enable/disable monitor mode and destination ring entry process
  2019-05-06 14:54 [PATCH v3 0/6] ath11k: add monitor mode support Miles Hu
                   ` (3 preceding siblings ...)
  2019-05-06 14:54 ` [PATCH v3 4/6] ath11k: monitor mode attach/detach Miles Hu
@ 2019-05-06 14:54 ` Miles Hu
  2019-05-06 14:54 ` [PATCH v3 6/6] ath11k: merge msdu tlv process and status/destination ring process Miles Hu
  5 siblings, 0 replies; 9+ messages in thread
From: Miles Hu @ 2019-05-06 14:54 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:
 - Move to ath11k-bringup branch

 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 73cfe08..faadfd1 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -3383,6 +3383,190 @@ static inline void ath11k_dp_mon_get_buf_len(struct hal_rx_msdu_desc_info *info,
 	}
 }
 
+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,
+			  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 76022fa..224d12a 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;
@@ -3473,6 +3488,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;
@@ -3678,6 +3696,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 */
 
@@ -3700,6 +3719,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);
 
@@ -3707,8 +3728,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);
 }
 
@@ -4164,6 +4196,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;
 
@@ -5075,6 +5112,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] 9+ messages in thread

* [PATCH v3 6/6] ath11k: merge msdu tlv process and status/destination ring process
  2019-05-06 14:54 [PATCH v3 0/6] ath11k: add monitor mode support Miles Hu
                   ` (4 preceding siblings ...)
  2019-05-06 14:54 ` [PATCH v3 5/6] ath11k: enable/disable monitor mode and destination ring entry process Miles Hu
@ 2019-05-06 14:54 ` Miles Hu
  5 siblings, 0 replies; 9+ messages in thread
From: Miles Hu @ 2019-05-06 14:54 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:
 - Move to ath11k-bringup branch

 drivers/net/wireless/ath/ath11k/dp_rx.c | 291 ++++++++++++++++++++++++++++++++
 1 file changed, 291 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index faadfd1..f61adf2 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -3567,6 +3567,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] 9+ messages in thread

* Re: [PATCH v3 1/6] ath11k: init/deinit monitor rings
  2019-05-06 14:54 ` [PATCH v3 1/6] ath11k: init/deinit monitor rings Miles Hu
@ 2019-05-08  9:50   ` Kalle Valo
  2019-05-08  9:52     ` Kalle Valo
  0 siblings, 1 reply; 9+ messages in thread
From: Kalle Valo @ 2019-05-08  9:50 UTC (permalink / raw)
  To: Miles Hu; +Cc: ath11k

Miles Hu <milehu@codeaurora.org> wrote:

> 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>

6 patches applied to ath.git, thanks.

a7e7c50ca095 ath11k: init/deinit monitor rings
c4e302228175 ath11k: monitor filter set function
db308ba7f43a ath11k: htt setup monitor rings
820370c8f81d ath11k: monitor mode attach/detach
5f201992710f ath11k: enable/disable monitor mode and destination ring entry process
a8c71066a0b2 ath11k: merge msdu tlv process and status/destination ring process

-- 
https://patchwork.kernel.org/patch/10931185/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


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

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

* Re: [PATCH v3 1/6] ath11k: init/deinit monitor rings
  2019-05-08  9:50   ` Kalle Valo
@ 2019-05-08  9:52     ` Kalle Valo
  0 siblings, 0 replies; 9+ messages in thread
From: Kalle Valo @ 2019-05-08  9:52 UTC (permalink / raw)
  To: Miles Hu; +Cc: ath11k

Kalle Valo <kvalo@codeaurora.org> writes:

> Miles Hu <milehu@codeaurora.org> wrote:
>
>> 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>
>
> 6 patches applied to ath.git, thanks.
>
> a7e7c50ca095 ath11k: init/deinit monitor rings
> c4e302228175 ath11k: monitor filter set function
> db308ba7f43a ath11k: htt setup monitor rings
> 820370c8f81d ath11k: monitor mode attach/detach
> 5f201992710f ath11k: enable/disable monitor mode and destination ring entry process
> a8c71066a0b2 ath11k: merge msdu tlv process and status/destination ring process

But these added a new warning:

drivers/net/wireless/ath/ath11k/dp_tx.c: In function 'ath11k_dp_htt_srng_setup':
drivers/net/wireless/ath/ath11k/dp_tx.c:615:6: warning: unused variable 'lmac_ring_id_offset' [-Wunused-variable]
  int lmac_ring_id_offset;
      ^~~~~~~~~~~~~~~~~~~

Please send a followup patch to fix that.

-- 
Kalle Valo

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

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

end of thread, other threads:[~2019-05-08  9:52 UTC | newest]

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

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.