* [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(¶ms, 0, sizeof(params));
- ath11k_hal_srng_get_params(ab, srng, ¶ms);
-
- 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(¶ms, 0, sizeof(params));
+ ath11k_hal_srng_get_params(ab, srng, ¶ms);
+
+ 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(¶ms, 0, sizeof(params));
ath11k_hal_srng_get_params(ab, srng, ¶ms);
- 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