qcacmn: flush pending vdevs and peers when do pdev deinit
Flush all the pending vdevs and peers when do pdev deinit Change-Id: Id99ca5394bc96a07b75a44847dbc1c7681355265 CRs-Fixed: 2532199
This commit is contained in:
@@ -144,6 +144,8 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle,
|
|||||||
static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap);
|
static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap);
|
||||||
static void dp_ppdu_ring_reset(struct dp_pdev *pdev);
|
static void dp_ppdu_ring_reset(struct dp_pdev *pdev);
|
||||||
static void dp_ppdu_ring_cfg(struct dp_pdev *pdev);
|
static void dp_ppdu_ring_cfg(struct dp_pdev *pdev);
|
||||||
|
static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle,
|
||||||
|
bool unmap_only);
|
||||||
#ifdef ENABLE_VERBOSE_DEBUG
|
#ifdef ENABLE_VERBOSE_DEBUG
|
||||||
bool is_dp_verbose_debug_enabled;
|
bool is_dp_verbose_debug_enabled;
|
||||||
#endif
|
#endif
|
||||||
@@ -3773,6 +3775,46 @@ static void dp_pdev_mem_reset(struct dp_pdev *pdev)
|
|||||||
qdf_mem_zero(dp_pdev_offset, len);
|
qdf_mem_zero(dp_pdev_offset, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WLAN_DP_PENDING_MEM_FLUSH
|
||||||
|
/**
|
||||||
|
* dp_pdev_flush_pending_vdevs() - Flush all delete pending vdevs in pdev
|
||||||
|
* @pdev: Datapath PDEV handle
|
||||||
|
*
|
||||||
|
* This is the last chance to flush all pending dp vdevs/peers,
|
||||||
|
* some peer/vdev leak case like Non-SSR + peer unmap missing
|
||||||
|
* will be covered here.
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void dp_pdev_flush_pending_vdevs(struct dp_pdev *pdev)
|
||||||
|
{
|
||||||
|
struct dp_vdev *vdev = NULL;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
qdf_spin_lock_bh(&pdev->vdev_list_lock);
|
||||||
|
TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
|
||||||
|
if (vdev->delete.pending)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
qdf_spin_unlock_bh(&pdev->vdev_list_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vdev will be freed when all peers get cleanup,
|
||||||
|
* dp_delete_pending_vdev will remove vdev from vdev_list
|
||||||
|
* in pdev.
|
||||||
|
*/
|
||||||
|
if (vdev)
|
||||||
|
dp_vdev_flush_peers((struct cdp_vdev *)vdev, 0);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void dp_pdev_flush_pending_vdevs(struct dp_pdev *pdev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dp_pdev_deinit() - Deinit txrx pdev
|
* dp_pdev_deinit() - Deinit txrx pdev
|
||||||
* @txrx_pdev: Datapath PDEV handle
|
* @txrx_pdev: Datapath PDEV handle
|
||||||
@@ -3798,6 +3840,8 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force)
|
|||||||
|
|
||||||
dp_wdi_event_detach(pdev);
|
dp_wdi_event_detach(pdev);
|
||||||
|
|
||||||
|
dp_pdev_flush_pending_vdevs(pdev);
|
||||||
|
|
||||||
dp_tx_pdev_detach(pdev);
|
dp_tx_pdev_detach(pdev);
|
||||||
|
|
||||||
if (wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) {
|
if (wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) {
|
||||||
@@ -4814,10 +4858,10 @@ static void dp_vdev_register_wifi3(struct cdp_vdev *vdev_handle,
|
|||||||
*
|
*
|
||||||
* Return: void
|
* Return: void
|
||||||
*/
|
*/
|
||||||
static inline void dp_peer_flush_ast_entry(struct dp_soc *soc,
|
static void dp_peer_flush_ast_entry(struct dp_soc *soc,
|
||||||
struct dp_peer *peer,
|
struct dp_peer *peer,
|
||||||
uint16_t peer_id,
|
uint16_t peer_id,
|
||||||
uint8_t vdev_id)
|
uint8_t vdev_id)
|
||||||
{
|
{
|
||||||
struct dp_ast_entry *ase, *tmp_ase;
|
struct dp_ast_entry *ase, *tmp_ase;
|
||||||
|
|
||||||
@@ -4846,7 +4890,9 @@ static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle, bool unmap_only)
|
|||||||
struct dp_soc *soc = pdev->soc;
|
struct dp_soc *soc = pdev->soc;
|
||||||
struct dp_peer *peer;
|
struct dp_peer *peer;
|
||||||
uint16_t *peer_ids;
|
uint16_t *peer_ids;
|
||||||
|
struct dp_peer **peer_array;
|
||||||
uint8_t i = 0, j = 0;
|
uint8_t i = 0, j = 0;
|
||||||
|
uint8_t m = 0, n = 0;
|
||||||
|
|
||||||
peer_ids = qdf_mem_malloc(soc->max_peers * sizeof(peer_ids[0]));
|
peer_ids = qdf_mem_malloc(soc->max_peers * sizeof(peer_ids[0]));
|
||||||
if (!peer_ids) {
|
if (!peer_ids) {
|
||||||
@@ -4854,8 +4900,21 @@ static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle, bool unmap_only)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!unmap_only) {
|
||||||
|
peer_array = qdf_mem_malloc(
|
||||||
|
soc->max_peers * sizeof(struct dp_peer *));
|
||||||
|
if (!peer_array) {
|
||||||
|
qdf_mem_free(peer_ids);
|
||||||
|
dp_err("DP alloc failure - unable to flush peers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
qdf_spin_lock_bh(&soc->peer_ref_mutex);
|
qdf_spin_lock_bh(&soc->peer_ref_mutex);
|
||||||
TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
|
TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
|
||||||
|
if (!unmap_only && n < soc->max_peers)
|
||||||
|
peer_array[n++] = peer;
|
||||||
|
|
||||||
for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++)
|
for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++)
|
||||||
if (peer->peer_ids[i] != HTT_INVALID_PEER)
|
if (peer->peer_ids[i] != HTT_INVALID_PEER)
|
||||||
if (j < soc->max_peers)
|
if (j < soc->max_peers)
|
||||||
@@ -4863,25 +4922,35 @@ static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle, bool unmap_only)
|
|||||||
}
|
}
|
||||||
qdf_spin_unlock_bh(&soc->peer_ref_mutex);
|
qdf_spin_unlock_bh(&soc->peer_ref_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If peer id is invalid, need to flush the peer if
|
||||||
|
* peer valid flag is true, this is needed for NAN + SSR case.
|
||||||
|
*/
|
||||||
|
if (!unmap_only) {
|
||||||
|
for (m = 0; m < n ; m++) {
|
||||||
|
peer = peer_array[m];
|
||||||
|
|
||||||
|
dp_info("peer: %pM is getting deleted",
|
||||||
|
peer->mac_addr.raw);
|
||||||
|
/* only if peer valid is true */
|
||||||
|
if (peer->valid)
|
||||||
|
dp_peer_delete_wifi3(peer, 0);
|
||||||
|
}
|
||||||
|
qdf_mem_free(peer_array);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < j ; i++) {
|
for (i = 0; i < j ; i++) {
|
||||||
peer = __dp_peer_find_by_id(soc, peer_ids[i]);
|
peer = __dp_peer_find_by_id(soc, peer_ids[i]);
|
||||||
|
|
||||||
if (!peer)
|
if (!peer)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dp_info("peer: %pM is getting flush",
|
dp_info("peer: %pM is getting unmap",
|
||||||
peer->mac_addr.raw);
|
peer->mac_addr.raw);
|
||||||
/* free AST entries of peer */
|
/* free AST entries of peer */
|
||||||
dp_peer_flush_ast_entry(soc, peer,
|
dp_peer_flush_ast_entry(soc, peer,
|
||||||
peer_ids[i],
|
peer_ids[i],
|
||||||
vdev->vdev_id);
|
vdev->vdev_id);
|
||||||
/*
|
|
||||||
* If peer flag valid is false, then dp_peer_delete_wifi3()
|
|
||||||
* is already executed, skip doing it again to avoid
|
|
||||||
* peer member invalid accessing.
|
|
||||||
*/
|
|
||||||
if (!unmap_only && peer->valid)
|
|
||||||
dp_peer_delete_wifi3(peer, 0);
|
|
||||||
|
|
||||||
dp_rx_peer_unmap_handler(soc, peer_ids[i],
|
dp_rx_peer_unmap_handler(soc, peer_ids[i],
|
||||||
vdev->vdev_id,
|
vdev->vdev_id,
|
||||||
@@ -4889,7 +4958,6 @@ static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle, bool unmap_only)
|
|||||||
}
|
}
|
||||||
|
|
||||||
qdf_mem_free(peer_ids);
|
qdf_mem_free(peer_ids);
|
||||||
|
|
||||||
dp_info("Flushed peers for vdev object %pK ", vdev);
|
dp_info("Flushed peers for vdev object %pK ", vdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user