qcacmn: Adding support to drain mgmt frames

FW recovery path needs this function as mgmt Tx
completions are not expected from the FW.

CRs-Fixed: 2178618
Change-Id: I7dddbff544dcce4dd9fe95ab79fb891bbd11b4ab
This commit is contained in:
Vinay Adella 2018-01-25 12:46:37 +05:30 • committed by snandini
commit 1de7baec7e
2 changed files with 73 additions and 0 deletions

View file

@ -689,6 +689,19 @@ typedef QDF_STATUS (*mgmt_frame_rx_callback)(
struct mgmt_rx_event_params *mgmt_rx_params,
enum mgmt_frame_type frm_type);
/**
* mgmt_frame_fill_peer_cb - Function pointer to fill peer in the buf
* @peer: peer
* @buf: buffer
*
* This is the function pointer to be called during drain to fill the
* peer into the buf's cb structure.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
typedef QDF_STATUS (*mgmt_frame_fill_peer_cb)(
struct wlan_objmgr_peer *peer,
qdf_nbuf_t buf);
/**
* struct mgmt_txrx_mgmt_frame_cb_info - frm and corresponding rx cb info
@ -792,6 +805,22 @@ QDF_STATUS wlan_mgmt_txrx_register_rx_cb(
struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info,
uint8_t num_entries);
/**
* wlan_mgmt_txrx_pdev_drain() - Function to drain all mgmt packets
* @pdev: pdev context
* @mgmt_fill_peer_cb: callback func to UMAC to fill peer into buf
* @status: opaque pointer about the status of the pkts passed to UMAC
*
* This function drains all mgmt packets. This can be used in the
* event of target going down without sending completions.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS wlan_mgmt_txrx_pdev_drain(
struct wlan_objmgr_pdev *pdev,
mgmt_frame_fill_peer_cb mgmt_fill_peer_cb,
void *status);
/**
* wlan_mgmt_txrx_deregister_rx_cb() - deregisters the rx cb for mgmt. frames
* @psoc: psoc context

View file

@ -30,6 +30,7 @@
#include "wlan_objmgr_vdev_obj.h"
#include "wlan_objmgr_peer_obj.h"
#include "qdf_nbuf.h"
#include "wlan_lmac_if_api.h"
/**
* wlan_mgmt_txrx_psoc_obj_create_notification() - called from objmgr when psoc
@ -768,3 +769,46 @@ QDF_STATUS wlan_mgmt_txrx_psoc_close(struct wlan_objmgr_psoc *psoc)
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS wlan_mgmt_txrx_pdev_drain(struct wlan_objmgr_pdev *pdev,
mgmt_frame_fill_peer_cb mgmt_fill_peer_cb,
void *status)
{
struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
struct mgmt_txrx_desc_elem_t *mgmt_desc;
struct wlan_objmgr_peer *peer;
uint32_t pool_size;
int i;
if (!pdev) {
mgmt_txrx_err("pdev context is NULL");
return QDF_STATUS_E_INVAL;
}
mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_UMAC_COMP_MGMT_TXRX);
if (!mgmt_txrx_pdev_ctx) {
mgmt_txrx_err("mgmt txrx context is NULL");
return QDF_STATUS_E_FAILURE;
}
pool_size = mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size;
if (!pool_size) {
mgmt_txrx_err("pool size is 0");
return QDF_STATUS_E_FAILURE;
}
for (i = 0; i < pool_size; i++) {
if (mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].in_use) {
mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i];
peer = mgmt_txrx_get_peer(pdev, mgmt_desc->desc_id);
QDF_ASSERT(peer != NULL);
if (mgmt_fill_peer_cb)
mgmt_fill_peer_cb(peer, mgmt_desc->nbuf);
mgmt_txrx_tx_completion_handler(pdev,
mgmt_desc->desc_id, 0, status);
}
}
return QDF_STATUS_SUCCESS;
}