summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGovind Singh <govinds@codeaurora.org>2017-03-07 18:32:57 +0530
committerRakesh Pillai <pillair@codeaurora.org>2017-08-11 10:40:40 +0530
commit2e035860df80737a7885e61dfc0e37cf14672494 (patch)
treec7d64212def4ae1acaf20b1ff05c81f83e697da3
parent39b5f76de03e17a0b80cb94a92496b1f95bf32b0 (diff)
ath10k: Enable pktlog for WCN3990 target
WCN3990 target uses new connect service for pktlog. Add pktlog service request and support for pktlog rx handling. CRs-Fixed: 2038976 Change-Id: I6f7dbd8f8cbeadd0e53844154a9c360011e2c798 Signed-off-by: Govind Singh <govinds@codeaurora.org> Signed-off-by: Ashutosh Kumar <askuma@codeaurora.org>
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c133
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h83
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c21
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h23
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c3
8 files changed, 269 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 10b33840e5e5..041d1d5eb718 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1924,6 +1924,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
goto err_hif_stop;
}
+ status = ath10k_pktlog_connect(ar);
+ if (status) {
+ ath10k_err(ar, "could not connect pktlog: %d\n", status);
+ goto err_hif_stop;
+ }
+
status = ath10k_htc_start(&ar->htc);
if (status) {
ath10k_err(ar, "failed to start htc: %d\n", status);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 8ddbae96794d..ffcf30756b9e 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -467,6 +467,7 @@ struct ath10k_debug {
u64 fw_dbglog_mask;
u32 fw_dbglog_level;
u32 pktlog_filter;
+ enum ath10k_htc_ep_id eid;
u32 reg_addr;
u32 nf_cal_period;
void *cal_data;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index ec8063e7986a..cb152bb4a222 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -25,6 +25,7 @@
#include "core.h"
#include "debug.h"
#include "hif.h"
+#include "htt.h"
#include "wmi-ops.h"
/* ms */
@@ -2617,6 +2618,138 @@ static const struct file_operations fops_fw_checksums = {
.llseek = default_llseek,
};
+static struct txctl_frm_hdr frm_hdr;
+
+static void ath10k_extract_frame_header(u8 *addr1, u8 *addr2, u8 *addr3)
+{
+ frm_hdr.bssid_tail = (addr1[IEEE80211_ADDR_LEN - 2] << BITS_PER_BYTE)
+ | (addr1[IEEE80211_ADDR_LEN - 1]);
+ frm_hdr.sa_tail = (addr2[IEEE80211_ADDR_LEN - 2] << BITS_PER_BYTE)
+ | (addr2[IEEE80211_ADDR_LEN - 1]);
+ frm_hdr.da_tail = (addr3[IEEE80211_ADDR_LEN - 2] << BITS_PER_BYTE)
+ | (addr3[IEEE80211_ADDR_LEN - 1]);
+}
+
+static void ath10k_process_ieee_hdr(void *data)
+{
+ u8 dir;
+ struct ieee80211_frame *wh;
+
+ if (!data)
+ return;
+
+ wh = (struct ieee80211_frame *)(data);
+ frm_hdr.framectrl = *(u_int16_t *)(wh->i_fc);
+ frm_hdr.seqctrl = *(u_int16_t *)(wh->i_seq);
+ dir = (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK);
+
+ if (dir == IEEE80211_FC1_DIR_TODS)
+ ath10k_extract_frame_header(&wh->i_addr1, &wh->i_addr2,
+ &wh->i_addr3);
+ else if (dir == IEEE80211_FC1_DIR_FROMDS)
+ ath10k_extract_frame_header(&wh->i_addr2, &wh->i_addr3,
+ &wh->i_addr1);
+ else
+ ath10k_extract_frame_header(&wh->i_addr3, &wh->i_addr2,
+ &wh->i_addr1);
+}
+
+static void ath10k_pktlog_process_rx(struct ath10k *ar, struct sk_buff *skb)
+{
+ struct ath10k_pktlog_hdr *hdr = (void *)skb->data;
+ struct ath_pktlog_txctl pktlog_tx_ctrl;
+
+ switch (hdr->log_type) {
+ case ATH10K_PKTLOG_TYPE_TX_CTRL: {
+ spin_lock_bh(&ar->htt.tx_lock);
+
+ memcpy((void *)(&pktlog_tx_ctrl.hdr), (void *)hdr,
+ sizeof(pktlog_tx_ctrl.hdr));
+ pktlog_tx_ctrl.frm_hdr = frm_hdr;
+ memcpy((void *)pktlog_tx_ctrl.txdesc_ctl, (void *)hdr->payload,
+ __le16_to_cpu(hdr->size));
+ pktlog_tx_ctrl.hdr.size = sizeof(pktlog_tx_ctrl) -
+ sizeof(pktlog_tx_ctrl.hdr);
+
+ spin_unlock_bh(&ar->htt.tx_lock);
+
+ trace_ath10k_htt_pktlog(ar, (void *)&pktlog_tx_ctrl,
+ sizeof(pktlog_tx_ctrl));
+ break;
+ }
+ case ATH10K_PKTLOG_TYPE_TX_MSDU_ID:
+ break;
+ case ATH10K_PKTLOG_TYPE_TX_FRM_HDR: {
+ ath10k_process_ieee_hdr((void *)(hdr->payload));
+ trace_ath10k_htt_pktlog(ar, hdr, sizeof(*hdr) +
+ __le16_to_cpu(hdr->size));
+ break;
+ }
+ case ATH10K_PKTLOG_TYPE_RX_STAT:
+ case ATH10K_PKTLOG_TYPE_RC_FIND:
+ case ATH10K_PKTLOG_TYPE_RC_UPDATE:
+ case ATH10K_PKTLOG_TYPE_DBG_PRINT:
+ case ATH10K_PKTLOG_TYPE_TX_STAT:
+ case ATH10K_PKTLOG_TYPE_SW_EVENT:
+ trace_ath10k_htt_pktlog(ar, hdr, sizeof(*hdr) +
+ __le16_to_cpu(hdr->size));
+ break;
+ case ATH10K_PKTLOG_TYPE_TX_VIRT_ADDR: {
+ u32 desc_id = (u32)*((u32 *)(hdr->payload));
+ struct sk_buff *msdu;
+
+ spin_lock_bh(&ar->htt.tx_lock);
+ msdu = ath10k_htt_tx_find_msdu_by_id(&ar->htt, desc_id);
+
+ if (!msdu) {
+ ath10k_info(ar,
+ "Failed to get msdu, id: %d\n",
+ desc_id);
+ spin_unlock_bh(&ar->htt.tx_lock);
+ return;
+ }
+ ath10k_process_ieee_hdr((void *)msdu->data);
+ spin_unlock_bh(&ar->htt.tx_lock);
+ trace_ath10k_htt_pktlog(ar, hdr, sizeof(*hdr) +
+ __le16_to_cpu(hdr->size));
+ break;
+ }
+ }
+}
+
+static void ath10k_pktlog_htc_tx_complete(struct ath10k *ar,
+ struct sk_buff *skb)
+{
+ ath10k_info(ar, "PKTLOG htc completed\n");
+}
+
+int ath10k_pktlog_connect(struct ath10k *ar)
+{
+ int status;
+ struct ath10k_htc_svc_conn_req conn_req;
+ struct ath10k_htc_svc_conn_resp conn_resp;
+
+ memset(&conn_req, 0, sizeof(conn_req));
+ memset(&conn_resp, 0, sizeof(conn_resp));
+
+ conn_req.ep_ops.ep_tx_complete = ath10k_pktlog_htc_tx_complete;
+ conn_req.ep_ops.ep_rx_complete = ath10k_pktlog_process_rx;
+ conn_req.ep_ops.ep_tx_credits = NULL;
+
+ /* connect to control service */
+ conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_LOG_MSG;
+ status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp);
+ if (status) {
+ ath10k_warn(ar, "failed to connect to PKTLOG service: %d\n",
+ status);
+ return status;
+ }
+
+ ar->debug.eid = conn_resp.eid;
+
+ return 0;
+}
+
int ath10k_debug_create(struct ath10k *ar)
{
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index f963391e3544..f9e90e1227de 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -57,6 +57,84 @@ enum ath10k_dbg_aggr_mode {
ATH10K_DBG_AGGR_MODE_MAX,
};
+#define IEEE80211_FC1_DIR_MASK 0x03
+#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
+#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
+#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */
+#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */
+#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
+
+#define MAX_PKT_INFO_MSDU_ID 192
+#define MSDU_ID_INFO_ID_OFFSET \
+ ((MAX_PKT_INFO_MSDU_ID >> 3) + 4)
+
+#define PKTLOG_MAX_TXCTL_WORDS 57 /* +2 words for bitmap */
+#define HTT_TX_MSDU_LEN_MASK 0xffff
+
+struct txctl_frm_hdr {
+ __le16 framectrl; /* frame control field from header */
+ __le16 seqctrl; /* frame control field from header */
+ __le16 bssid_tail; /* last two octets of bssid */
+ __le16 sa_tail; /* last two octets of SA */
+ __le16 da_tail; /* last two octets of DA */
+ __le16 resvd;
+} __packed;
+
+struct ath_pktlog_hdr {
+ __le16 flags;
+ __le16 missed_cnt;
+ u8 log_type;
+ u8 macId;
+ __le16 size;
+ __le32 timestamp;
+ __le32 type_specific_data;
+} __packed;
+
+/* generic definitions for IEEE 802.11 frames */
+struct ieee80211_frame {
+ u8 i_fc[2];
+ u8 i_dur[2];
+ union {
+ struct {
+ u8 i_addr1[IEEE80211_ADDR_LEN];
+ u8 i_addr2[IEEE80211_ADDR_LEN];
+ u8 i_addr3[IEEE80211_ADDR_LEN];
+ };
+ u8 i_addr_all[3 * IEEE80211_ADDR_LEN];
+ };
+ u8 i_seq[2];
+} __packed;
+
+struct fw_pktlog_msdu_info {
+ __le32 num_msdu;
+ u8 bound_bmap[MAX_PKT_INFO_MSDU_ID >> 3];
+ __le16 id[MAX_PKT_INFO_MSDU_ID];
+} __packed;
+
+struct ath_pktlog_txctl {
+ struct ath_pktlog_hdr hdr;
+ struct txctl_frm_hdr frm_hdr;
+ __le32 txdesc_ctl[PKTLOG_MAX_TXCTL_WORDS];
+} __packed;
+
+struct ath_pktlog_msdu_id {
+ struct ath_pktlog_hdr hdr;
+ struct fw_pktlog_msdu_info msdu_info;
+} __packed;
+
+struct ath_pktlog_rx_info {
+ struct ath_pktlog_hdr pl_hdr;
+ struct rx_attention attention;
+ struct rx_frag_info frag_info;
+ struct rx_mpdu_start mpdu_start;
+ struct rx_msdu_start msdu_start;
+ struct rx_msdu_end msdu_end;
+ struct rx_mpdu_end mpdu_end;
+ struct rx_ppdu_start ppdu_start;
+ struct rx_ppdu_end ppdu_end;
+ u8 rx_hdr_status[RX_HTT_HDR_STATUS_LEN];
+} __packed;
+
/* FIXME: How to calculate the buffer size sanely? */
#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024)
#define ATH10K_DATAPATH_BUF_SIZE (1024 * 1024)
@@ -98,6 +176,7 @@ void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
struct ethtool_stats *stats, u64 *data);
void fill_datapath_stats(struct ath10k *ar, struct ieee80211_rx_status *status);
size_t get_datapath_stat(char *buf, struct ath10k *ar);
+int ath10k_pktlog_connect(struct ath10k *ar);
#else
static inline int ath10k_debug_start(struct ath10k *ar)
{
@@ -158,6 +237,10 @@ static inline size_t get_datapath_stat(char *buf, struct ath10k *ar)
return 0;
}
+static inline int ath10k_pktlog_connect(struct ath10k *ar)
+{
+ return 0;
+}
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
#define ath10k_debug_get_et_strings NULL
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index b0d6c2614731..2df7fcb4a5ea 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1847,5 +1847,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt,
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
struct sk_buff *skb);
int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget);
+struct sk_buff *ath10k_htt_tx_find_msdu_by_id(struct ath10k_htt *htt,
+ u16 msdu_id);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 1b59721a91ac..6579eb2b410c 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -218,6 +218,27 @@ int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb)
return ret;
}
+struct sk_buff *ath10k_htt_tx_find_msdu_by_id(struct ath10k_htt *htt,
+ u16 msdu_id)
+{
+ struct ath10k *ar;
+ struct sk_buff *ret;
+
+ if (!htt)
+ return NULL;
+
+ ar = htt->ar;
+
+ lockdep_assert_held(&htt->tx_lock);
+
+ ret = (struct sk_buff *)idr_find(&htt->pending_tx, msdu_id);
+
+ ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx find msdu by msdu_id %s\n",
+ !ret ? "Failed" : "Success");
+
+ return ret;
+}
+
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
{
struct ath10k *ar = htt->ar;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 0f2422480c4e..3e1917a6a8e8 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -984,4 +984,27 @@ struct ath10k_shadow_reg_address {
extern struct ath10k_shadow_reg_value wcn3990_shadow_reg_value;
extern struct ath10k_shadow_reg_address wcn3990_shadow_reg_address;
+enum ath10k_pktlog_type {
+ ATH10K_PKTLOG_TYPE_TX_CTRL = 1,
+ ATH10K_PKTLOG_TYPE_TX_STAT,
+ ATH10K_PKTLOG_TYPE_TX_MSDU_ID,
+ ATH10K_PKTLOG_TYPE_TX_FRM_HDR,
+ ATH10K_PKTLOG_TYPE_RX_STAT,
+ ATH10K_PKTLOG_TYPE_RC_FIND,
+ ATH10K_PKTLOG_TYPE_RC_UPDATE,
+ ATH10K_PKTLOG_TYPE_TX_VIRT_ADDR,
+ ATH10K_PKTLOG_TYPE_DBG_PRINT,
+ ATH10K_PKTLOG_TYPE_SW_EVENT,
+ ATH10K_PKTLOG_TYPE_MAX,
+};
+
+struct ath10k_pktlog_hdr {
+ __le16 flags;
+ __le16 missed_cnt;
+ __le16 log_type;
+ __le16 size;
+ __le32 timestamp;
+ u8 payload[0];
+} __packed;
+
#endif /* _HW_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 0c60a7baae82..13736750e463 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -775,9 +775,6 @@ static int ath10k_snoc_hif_map_service_to_pipe(struct ath10k *ar,
}
}
- if (WARN_ON(!ul_set || !dl_set))
- return -ENOENT;
-
return 0;
}