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>
This commit is contained in:
parent
39b5f76de0
commit
2e035860df
8 changed files with 269 additions and 3 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue