diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index fac9cc1da518..6ea5718a03aa 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -2025,6 +2025,8 @@ ol_txrx_vdev_attach(struct cdp_pdev *ppdev, vdev->tx_fl_hwm = 0; vdev->rx = NULL; vdev->wait_on_peer_id = OL_TXRX_INVALID_LOCAL_PEER_ID; + qdf_mem_zero(&vdev->last_peer_mac_addr, + sizeof(union ol_txrx_align_mac_addr_t)); qdf_spinlock_create(&vdev->flow_control_lock); vdev->osif_flow_control_cb = NULL; vdev->osif_fc_ctx = NULL; @@ -2379,6 +2381,8 @@ ol_txrx_peer_attach(struct cdp_vdev *pvdev, uint8_t *peer_mac_addr) bool wait_on_deletion = false; unsigned long rc; struct ol_txrx_pdev_t *pdev; + bool cmp_wait_mac = false; + uint8_t zero_mac_addr[QDF_MAC_ADDR_SIZE] = { 0, 0, 0, 0, 0, 0 }; /* preconditions */ TXRX_ASSERT2(vdev); @@ -2387,6 +2391,10 @@ ol_txrx_peer_attach(struct cdp_vdev *pvdev, uint8_t *peer_mac_addr) pdev = vdev->pdev; TXRX_ASSERT2(pdev); + if (qdf_mem_cmp(&zero_mac_addr, &vdev->last_peer_mac_addr, + QDF_MAC_ADDR_SIZE)) + cmp_wait_mac = true; + qdf_spin_lock_bh(&pdev->peer_ref_mutex); /* check for duplicate exsisting peer */ TAILQ_FOREACH(temp_peer, &vdev->peer_list, peer_list_elem) { @@ -2402,14 +2410,40 @@ ol_txrx_peer_attach(struct cdp_vdev *pvdev, uint8_t *peer_mac_addr) vdev->wait_on_peer_id = temp_peer->local_id; qdf_event_reset(&vdev->wait_delete_comp); wait_on_deletion = true; + break; } else { qdf_spin_unlock_bh(&pdev->peer_ref_mutex); return NULL; } } + if (cmp_wait_mac && !ol_txrx_peer_find_mac_addr_cmp( + &temp_peer->mac_addr, + &vdev->last_peer_mac_addr)) { + ol_txrx_info( + "vdev_id %d (%02x:%02x:%02x:%02x:%02x:%02x) old peer exsist.\n", + vdev->vdev_id, + vdev->last_peer_mac_addr.raw[0], + vdev->last_peer_mac_addr.raw[1], + vdev->last_peer_mac_addr.raw[2], + vdev->last_peer_mac_addr.raw[3], + vdev->last_peer_mac_addr.raw[4], + vdev->last_peer_mac_addr.raw[5]); + if (qdf_atomic_read(&temp_peer->delete_in_progress)) { + vdev->wait_on_peer_id = temp_peer->local_id; + qdf_event_reset(&vdev->wait_delete_comp); + wait_on_deletion = true; + break; + } else { + qdf_spin_unlock_bh(&pdev->peer_ref_mutex); + ol_txrx_err("peer not found"); + return NULL; + } + } } qdf_spin_unlock_bh(&pdev->peer_ref_mutex); + qdf_mem_zero(&vdev->last_peer_mac_addr, + sizeof(union ol_txrx_align_mac_addr_t)); if (wait_on_deletion) { /* wait for peer deletion */ rc = qdf_wait_single_event(&vdev->wait_delete_comp, @@ -3387,6 +3421,12 @@ static void ol_txrx_peer_detach(void *ppeer) */ qdf_atomic_set(&peer->delete_in_progress, 1); + if (vdev->opmode == wlan_op_mode_sta) { + qdf_mem_copy(&peer->vdev->last_peer_mac_addr, + &peer->mac_addr, + sizeof(union ol_txrx_align_mac_addr_t)); + } + /* * Create a timer to track unmap events when the sta peer gets deleted. */ diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index c948eaa36625..9b7eadfc6f25 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -1066,6 +1066,7 @@ struct ol_txrx_vdev_t { #endif uint16_t wait_on_peer_id; + union ol_txrx_align_mac_addr_t last_peer_mac_addr; qdf_event_t wait_delete_comp; #if defined(FEATURE_TSO) struct {