qca-wifi: Register and correlate dbr and tx events

Register tx and dbr events and extract data required from
these events to pass it on to relayfs.

Change-Id: I9be9d0f9d47fa926406ee525742886d55229bab0
Этот коммит содержится в:
Abhiram Jogadenu
2019-02-22 11:16:49 +05:30
коммит произвёл Vikram Kandukuri
родитель 83a229c759
Коммит 96b7e0affb
5 изменённых файлов: 563 добавлений и 142 удалений

Просмотреть файл

@@ -32,40 +32,438 @@
#include <target_if_direct_buf_rx_api.h>
#endif
#ifdef DIRECT_BUF_RX_ENABLE
void dump_dma_hdr(struct whal_cfir_dma_hdr *dma_hdr)
static u_int32_t end_magic = 0xBEAFDEAD;
int dump_lut(struct wlan_objmgr_pdev *pdev)
{
cfr_info("Tag: 0x%02x Length: %d udone: %d ctype: %d preamble: %d\n",
dma_hdr->tag, dma_hdr->length, dma_hdr->upload_done,
dma_hdr->capture_type, dma_hdr->preamble_type);
cfr_info("Nss: %d num_chains: %d bw: %d\n", dma_hdr->nss,
dma_hdr->num_chains, dma_hdr->upload_pkt_bw);
cfr_info("peervalid: %d peer_id: %d ppdu_id: 0x%04x\n",
dma_hdr->sw_peer_id_valid, dma_hdr->sw_peer_id,
dma_hdr->phy_ppdu_id);
struct pdev_cfr *pdev_cfrobj;
struct look_up_table *lut = NULL;
int i = 0;
pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_UMAC_COMP_CFR);
if (!pdev_cfrobj) {
cfr_err("pdev object for CFR is null");
return -EINVAL;
}
for (i = 0; i < 136; i++) {
lut = &pdev_cfrobj->lut[i];
cfr_err("idx:%d dbrevnt: %d txevent: %d dbrppdu:0x%x txppdu:0x%x\n",
i, lut->dbr_recv, lut->tx_recv,
lut->dbr_ppdu_id, lut->tx_ppdu_id);
}
return 0;
}
#ifdef DIRECT_BUF_RX_ENABLE
void dump_dma_hdr(struct whal_cfir_dma_hdr *dma_hdr, int error)
{
if (!error) {
cfr_debug("Tag: 0x%02x Length: %d udone: %d ctype: %d preamble: %d",
dma_hdr->tag, dma_hdr->length, dma_hdr->upload_done,
dma_hdr->capture_type, dma_hdr->preamble_type);
cfr_debug("Nss: %d num_chains: %d bw: %d", dma_hdr->nss,
dma_hdr->num_chains, dma_hdr->upload_pkt_bw);
cfr_debug("peervalid: %d peer_id: %d ppdu_id: 0x%04x",
dma_hdr->sw_peer_id_valid, dma_hdr->sw_peer_id,
dma_hdr->phy_ppdu_id);
} else {
cfr_err("Tag: 0x%02x Length: %d udone: %d ctype: %d preamble: %d",
dma_hdr->tag, dma_hdr->length, dma_hdr->upload_done,
dma_hdr->capture_type, dma_hdr->preamble_type);
cfr_err("Nss: %d num_chains: %d bw: %d", dma_hdr->nss,
dma_hdr->num_chains, dma_hdr->upload_pkt_bw);
cfr_err("peervalid: %d peer_id: %d ppdu_id: 0x%04x",
dma_hdr->sw_peer_id_valid, dma_hdr->sw_peer_id,
dma_hdr->phy_ppdu_id);
}
}
int compute_length(struct whal_cfir_dma_hdr *dma_hdr)
{
uint8_t bw = dma_hdr->upload_pkt_bw;
uint8_t preamble = dma_hdr->preamble_type;
switch (preamble) {
case 0:
case 2:
switch (bw) {
case 0:
return TONES_IN_20MHZ;
case 1: /* DUP40/VHT40 */
return TONES_IN_40MHZ;
case 2: /* DUP80/VHT80 */
return TONES_IN_80MHZ;
case 3: /* DUP160/VHT160 */
return TONES_IN_160MHZ;
}
case 1:
switch (bw) {
case 0:
return TONES_IN_20MHZ;
case 1:
return TONES_IN_40MHZ;
}
}
return TONES_INVALID;
}
int release_lut_entry(struct wlan_objmgr_pdev *pdev,
struct look_up_table *lut)
{
lut->dbr_recv = false;
lut->tx_recv = false;
lut->data = NULL;
lut->data_len = 0;
lut->dbr_ppdu_id = 0;
lut->tx_ppdu_id = 0;
qdf_mem_zero(&lut->header, sizeof(struct csi_cfr_header));
return 0;
}
int correlate_and_relay(struct wlan_objmgr_pdev *pdev, uint32_t cookie,
struct look_up_table *lut, uint8_t module_id)
{
struct pdev_cfr *pdev_cfrobj;
if (module_id > 1) {
cfr_err("Received request with invalid mod id. Investigate!!");
QDF_ASSERT(0);
return STATUS_ERROR;
}
pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_UMAC_COMP_CFR);
if (module_id == CORRELATE_TX_EV_MODULE_ID) {
pdev_cfrobj->tx_evt_cnt++;
lut->tx_recv = true;
} else if (module_id == CORRELATE_DBR_MODULE_ID) {
pdev_cfrobj->dbr_evt_cnt++;
lut->dbr_recv = true;
}
if ((lut->dbr_recv == true) && (lut->tx_recv == true)) {
if (lut->dbr_ppdu_id == lut->tx_ppdu_id) {
pdev_cfrobj->release_cnt++;
return STATUS_STREAM_AND_RELEASE;
} else {
/*
* When there is a ppdu id mismatch, discard the other
* older event's data and wait hold for new event
*/
if (module_id == CORRELATE_TX_EV_MODULE_ID) {
cfr_debug("Received new tx event for same cookie %u",
cookie);
lut->dbr_recv = false;
lut->data = NULL;
lut->data_len = 0;
lut->dbr_ppdu_id = 0;
qdf_mem_zero(&lut->dbr_address, sizeof(lut->dbr_address));
} else if (module_id == CORRELATE_DBR_MODULE_ID) {
cfr_debug("Received new dbr event for same cookie %u",
cookie);
lut->tx_recv = false;
lut->tx_ppdu_id = 0;
}
/*
* This is condition can occur if DBR buffer did not get
* released or leaked either by Host / Target
* we may need to add recovery here.
*
* 1. Stop all captures
* 2. Flush/release DBR buffer and LUT
* 3. Start capture again
*/
if (pdev_cfrobj->dbr_evt_cnt - pdev_cfrobj->release_cnt > 1) {
cfr_err("cookie = %u dbr_cnt = %d, release_cnt = %d",
cookie, pdev_cfrobj->dbr_evt_cnt,
pdev_cfrobj->release_cnt);
dump_lut(pdev);
dump_dma_hdr(&lut->dma_hdr, 1);
cfr_debug("correlation_info1: 0x%08x correlation_info2 0x%08x",
lut->tx_address1, lut->tx_address2);
}
return STATUS_HOLD;
}
} else {
return STATUS_HOLD;
}
}
bool cfr_dbr_event_handler(struct wlan_objmgr_pdev *pdev,
struct direct_buf_rx_data *payload)
struct direct_buf_rx_data *payload)
{
uint8_t *data = payload->vaddr;
uint32_t cookie = payload->cookie;
struct whal_cfir_dma_hdr dma_hdr = {0};
int length = 8, tones = 0, status = 0;
struct wlan_objmgr_psoc *psoc;
struct pdev_cfr *pdev_cfrobj;
struct look_up_table *lut = NULL;
struct csi_cfr_header *header = NULL;
if ((!pdev) || (!payload)) {
cfr_err("%s Error!! pdev or payload is null\n", __func__);
cfr_err("pdev or payload is null");
return true;
}
psoc = wlan_pdev_get_psoc(pdev);
if (!psoc) {
cfr_err("psoc is null");
return true;
}
pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_UMAC_COMP_CFR);
if (!pdev_cfrobj) {
cfr_err("pdev object for CFR is null");
return true;
}
cfr_debug("bufferaddr: 0x%pK cookie: %u", payload->paddr, cookie);
qdf_mem_copy(&dma_hdr, &data[0], sizeof(struct whal_cfir_dma_hdr));
dump_dma_hdr(&dma_hdr);
dump_dma_hdr(&dma_hdr, 0);
tones = compute_length(&dma_hdr);
if (tones == TONES_INVALID) {
cfr_err("Number of tones received is invalid. Investigate!");
return true;
}
length += tones * (dma_hdr.num_chains + 1);
lut = &pdev_cfrobj->lut[cookie];
lut->data = data;
lut->data_len = length;
lut->dbr_ppdu_id = dma_hdr.phy_ppdu_id;
lut->dbr_address = payload->paddr;
qdf_mem_copy(&lut->dma_hdr, &dma_hdr, sizeof(struct whal_cfir_dma_hdr));
header = &lut->header;
header->u.meta_v1.capture_bw = dma_hdr.upload_pkt_bw;
header->u.meta_v1.num_rx_chain = dma_hdr.num_chains + 1;
header->u.meta_v1.length = length;
status = correlate_and_relay(pdev, cookie, lut,
CORRELATE_DBR_MODULE_ID);
if (status == STATUS_STREAM_AND_RELEASE) {
/*
* Message format
* Meta data Header + actual payload + trailer
*/
status = psoc->soc_cb.rx_ops.cfr_rx_ops.cfr_info_send(pdev, &lut->header,
sizeof(struct csi_cfr_header),
lut->data, lut->data_len, &end_magic, 4);
release_lut_entry(pdev, lut);
cfr_debug("Data sent to upper layers, released look up table");
return true;
} else if (status == STATUS_HOLD) {
cfr_debug("Tx event not received yet. Buffer is not released");
return false;
} else {
cfr_err("Correlation returned invalid status!!");
return true;
}
return true;
}
#endif
static int
target_if_peer_capture_event(ol_scn_t sc, u_int8_t *data, u_int32_t datalen)
void dump_cfr_peer_tx_event(wmi_cfr_peer_tx_event_param *event)
{
cfr_debug("CFR capture method: %d vdev_id: %d mac: %s",
event->capture_method, event->vdev_id,
ether_sprintf(&event->peer_mac_addr.bytes[0]));
cfr_debug("Chan: %d bw: %d phymode: %d cfreq1: %d cfrq2: %d nss: %d",
event->primary_20mhz_chan, event->bandwidth,
event->phy_mode, event->band_center_freq1,
event->band_center_freq2, event->spatial_streams);
cfr_debug("Correlation_info1: 0x%08x Correlation_info2: 0x%08x",
event->correlation_info_1, event->correlation_info_2);
cfr_debug("status: 0x%x ts: %d counter: %d rssi0: 0x%08x",
event->status, event->timestamp_us, event->counter,
event->chain_rssi[0]);
}
static int
target_if_peer_capture_event(ol_scn_t sc, uint8_t *data, uint32_t datalen)
{
QDF_STATUS retval = 0;
ol_ath_soc_softc_t *scn = (ol_ath_soc_softc_t *)sc;
struct common_wmi_handle *wmi_handle;
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_pdev *pdev;
struct wlan_objmgr_vdev *vdev;
uint32_t cookie;
struct pdev_cfr *pdev_cfrobj;
struct look_up_table *lut = NULL;
struct csi_cfr_header *header = NULL;
wmi_cfr_peer_tx_event_param tx_evt_param = {0};
qdf_dma_addr_t buf_addr = 0, buf_addr_temp = 0;
int status;
psoc = scn->psoc_obj;
if (!psoc) {
cfr_err("psoc is null");
return -EINVAL;
}
retval = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_CFR_ID);
if (QDF_IS_STATUS_ERROR(retval)) {
cfr_err("unable to get psoc reference");
return -EINVAL;
}
wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
if (!wmi_handle) {
cfr_err("wmi_handle is null");
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
return -EINVAL;
}
retval = wmi_extract_cfr_peer_tx_event_param(wmi_handle, data,
&tx_evt_param);
if (retval != QDF_STATUS_SUCCESS) {
cfr_err("Failed to extract cfr tx event param");
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
return -EINVAL;
}
dump_cfr_peer_tx_event(&tx_evt_param);
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, tx_evt_param.vdev_id,
WLAN_CFR_ID);
if (!vdev) {
cfr_err("vdev is null");
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
return -EINVAL;
}
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
cfr_err("pdev is null");
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
return -EINVAL;
}
retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID);
if (retval != QDF_STATUS_SUCCESS){
cfr_err("failed to get pdev reference");
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
return -EINVAL;
}
pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_UMAC_COMP_CFR);
if (!pdev_cfrobj) {
cfr_err("pdev object for CFR is NULL");
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
return -EINVAL;
}
if ((tx_evt_param.status & PEER_CFR_CAPTURE_EVT_STATUS_MASK) == 0) {
cfr_debug("CFR capture failed for peer : %s",
ether_sprintf(&tx_evt_param.peer_mac_addr.bytes[0]));
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
return -EINVAL;
}
if (tx_evt_param.status & CFR_TX_EVT_STATUS_MASK) {
cfr_debug("TX packet returned status %d for peer: %s",
tx_evt_param.status & CFR_TX_EVT_STATUS_MASK,
ether_sprintf(&tx_evt_param.peer_mac_addr.bytes[0]));
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
return -EINVAL;
}
buf_addr_temp = (tx_evt_param.correlation_info_2 & 0x0f);
buf_addr = (tx_evt_param.correlation_info_1 |((uint64_t)buf_addr_temp << 32));
if (target_if_dbr_cookie_lookup(pdev, DBR_MODULE_CFR, buf_addr,
&cookie)) {
cfr_debug("Cookie lookup failure for addr: 0x%pK status: 0x%x",
buf_addr, tx_evt_param.status);
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
return -EINVAL;
}
cfr_debug("buffer address: 0x%pK cookie: %u", buf_addr, cookie);
lut = &pdev_cfrobj->lut[cookie];
lut->tx_ppdu_id = (tx_evt_param.correlation_info_2 >> 16);
lut->tx_address1 = tx_evt_param.correlation_info_1;
lut->tx_address2 = tx_evt_param.correlation_info_2;
header = &lut->header;
header->start_magic_num = 0xDEADBEAF;
header->vendorid = 0x8cfdf0;
header->cfr_metadata_version = CFR_META_VERSION_1;
header->cfr_data_version = CFR_DATA_VERSION_1;
header->chip_type = CFR_CAPTURE_RADIO_HKV2;
header->pltform_type = CFR_PLATFORM_TYPE_ARM;
header->Reserved = 0;
header->u.meta_v1.status = tx_evt_param.status;
header->u.meta_v1.channel_bw = tx_evt_param.bandwidth;
header->u.meta_v1.phy_mode = tx_evt_param.phy_mode;
header->u.meta_v1.prim20_chan = tx_evt_param.primary_20mhz_chan;
header->u.meta_v1.center_freq1 = tx_evt_param.band_center_freq1;
header->u.meta_v1.center_freq2 = tx_evt_param.band_center_freq2;
header->u.meta_v1.capture_type = tx_evt_param.capture_method;
header->u.meta_v1.sts_count = tx_evt_param.spatial_streams;
header->u.meta_v1.timestamp = tx_evt_param.timestamp_us;
qdf_mem_copy(&header->u.meta_v1.peer_addr[0],
&tx_evt_param.peer_mac_addr.bytes[0], IEEE80211_ADDR_LEN);
status = correlate_and_relay(pdev, cookie, lut,
CORRELATE_TX_EV_MODULE_ID);
if (status == STATUS_STREAM_AND_RELEASE) {
status = psoc->soc_cb.rx_ops.cfr_rx_ops.cfr_info_send(pdev, &lut->header,
sizeof(struct csi_cfr_header),
lut->data, lut->data_len, &end_magic, 4);
release_lut_entry(pdev, lut);
target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, buf_addr,
cookie);
cfr_debug("Data sent to upper layers, releasing look up table");
} else if (status == STATUS_HOLD) {
cfr_debug("HOLD for buffer address: 0x%pK cookie: %u",
buf_addr, cookie);
} else {
cfr_err("Correlation returned invalid status!!");
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
return -EINVAL;
}
wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
return 0;
}
@@ -73,14 +471,39 @@ int
target_if_register_tx_completion_event_handler(struct wlan_objmgr_psoc *psoc)
{
/* Register completion handler here */
return 0;
wmi_unified_t wmi_hdl;
int ret = 0;
wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_hdl) {
cfr_err("Unable to get wmi handle");
return -EINVAL;
}
ret = wmi_unified_register_event_handler(wmi_hdl,
wmi_peer_cfr_capture_event_id,
target_if_peer_capture_event,
WMI_RX_UMAC_CTX);
return ret;
}
int
target_if_unregister_tx_completion_event_handler(struct wlan_objmgr_psoc *psoc)
{
/* UnRegister completion hoandler here */
return 0;
/* Unregister completion handler here */
wmi_unified_t wmi_hdl;
int status = 0;
wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_hdl) {
cfr_err("Unable to get wmi handle");
return -EINVAL;
}
status = wmi_unified_unregister_event(wmi_hdl,
wmi_peer_cfr_capture_event_id);
return status;
}
#ifdef DIRECT_BUF_RX_ENABLE
@@ -94,44 +517,30 @@ target_if_register_to_dbr(struct wlan_objmgr_pdev *pdev)
dbr_tx_ops = &psoc->soc_cb.tx_ops.dbr_tx_ops;
if (dbr_tx_ops->direct_buf_rx_module_register) {
return dbr_tx_ops->direct_buf_rx_module_register
(pdev, 1,
(pdev, DBR_MODULE_CFR,
cfr_dbr_event_handler);
}
return QDF_STATUS_SUCCESS;
}
#else
QDF_STATUS
target_if_cfr_register_to_dbr(struct wlan_objmgr_pdev *pdev)
target_if_unregister_to_dbr(struct wlan_objmgr_pdev *pdev)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL;
psoc = wlan_pdev_get_psoc(pdev);
dbr_tx_ops = &psoc->soc_cb.tx_ops.dbr_tx_ops;
if (dbr_tx_ops->direct_buf_rx_module_register) {
return dbr_tx_ops->direct_buf_rx_module_unregister
(pdev, DBR_MODULE_CFR);
}
return QDF_STATUS_SUCCESS;
}
#endif
int cfr_8074v2_init_pdev(
struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_pdev *pdev)
{
int status;
status = target_if_register_to_dbr(pdev);
status = target_if_register_tx_completion_event_handler(psoc);
return status;
}
int cfr_8074v2_deinit_pdev(
struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_pdev *pdev)
{
int status;
status = target_if_unregister_tx_completion_event_handler(psoc);
return status;
}
#ifdef DIRECT_BUF_RX_ENABLE
struct module_ring_params *
struct module_ring_params*
target_if_dbr_get_ring_params(struct wlan_objmgr_pdev *pdev)
{
struct wlan_objmgr_psoc *psoc;
@@ -142,13 +551,70 @@ target_if_dbr_get_ring_params(struct wlan_objmgr_pdev *pdev)
dbr_tx_ops = &psoc->soc_cb.tx_ops.dbr_tx_ops;
if(dbr_tx_ops->direct_buf_rx_get_ring_params)
dbr_tx_ops->direct_buf_rx_get_ring_params(pdev, param, 1);
dbr_tx_ops->direct_buf_rx_get_ring_params(pdev, param,
DBR_MODULE_CFR);
return param;
}
#else
struct module_ring_params *
QDF_STATUS
target_if_cfr_register_to_dbr(struct wlan_objmgr_pdev *pdev)
{
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
target_if_unregister_to_dbr(struct wlan_objmgr_pdev *pdev)
{
return QDF_STATUS_SUCCESS;
}
struct module_ring_params*
target_if_dbr_get_ring_params(struct wlan_objmgr_pdev *pdev)
{
return NULL;
}
#endif
int cfr_8074v2_init_pdev(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_pdev *pdev)
{
int status;
struct pdev_cfr *pdev_cfrobj;
pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_UMAC_COMP_CFR);
if (!pdev_cfrobj)
return -EINVAL;
status = target_if_register_to_dbr(pdev);
if (QDF_STATUS_SUCCESS != status) {
cfr_err("Failed to register with dbr");
return -EINVAL;
}
status = target_if_register_tx_completion_event_handler(psoc);
if (QDF_STATUS_SUCCESS != status) {
cfr_err("Failed to register with tx event handler");
return -EINVAL;
}
pdev_cfrobj->cfr_max_sta_count = MAX_PEERS_HKV2;
pdev_cfrobj->subbuf_size = STREAMFS_MAX_SUBBUF_8S;
pdev_cfrobj->num_subbufs = STREAMFS_NUM_SUBBUF_8S;
return status;
}
int cfr_8074v2_deinit_pdev(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_pdev *pdev)
{
int status;
status = target_if_unregister_to_dbr(pdev);
if (QDF_STATUS_SUCCESS != status) {
cfr_err("Failed to register with dbr");
}
status = target_if_unregister_tx_completion_event_handler(psoc);
return status;
}