qcacmn: update peer reuse logic and add peer state lock
With new design, peer is deleted from hash table in cdp_peer_delete. Hash table search in dp_peer_can_reuse API at cdp_peer_create will always fail Update the peer reuse logic to search from inactive list. Insert peer to inactive list from cdp_peer_delete() and in peer reuse case search in inactive list to get peer. Also add a new lock to protect peer state transition Change-Id: I2e672fc4a9346c95d67716d437538dd0f96b2207
This commit is contained in:

committed by
snandini

parent
f7771e45d8
commit
3ac6dedea7
@@ -5589,43 +5589,35 @@ static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc,
|
|||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ATH_SUPPORT_WRAP
|
|
||||||
static inline struct dp_peer *dp_peer_can_reuse(struct dp_vdev *vdev,
|
static inline struct dp_peer *dp_peer_can_reuse(struct dp_vdev *vdev,
|
||||||
uint8_t *peer_mac_addr)
|
uint8_t *peer_mac_addr)
|
||||||
{
|
{
|
||||||
struct dp_peer *peer;
|
struct dp_peer *peer;
|
||||||
|
struct dp_soc *soc = vdev->pdev->soc;
|
||||||
|
|
||||||
peer = dp_peer_find_hash_find(vdev->pdev->soc, peer_mac_addr,
|
qdf_spin_lock_bh(&soc->inactive_peer_list_lock);
|
||||||
0, vdev->vdev_id,
|
TAILQ_FOREACH(peer, &soc->inactive_peer_list,
|
||||||
DP_MOD_ID_CONFIG);
|
inactive_list_elem) {
|
||||||
if (!peer)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (peer->bss_peer)
|
/* reuse bss peer only when vdev matches*/
|
||||||
return peer;
|
if (peer->bss_peer && (peer->vdev == vdev) &&
|
||||||
|
qdf_mem_cmp(peer_mac_addr, peer->mac_addr.raw,
|
||||||
|
QDF_MAC_ADDR_SIZE) == 0) {
|
||||||
|
/* increment ref count for cdp_peer_create*/
|
||||||
|
if (dp_peer_get_ref(soc, peer, DP_MOD_ID_CONFIG) ==
|
||||||
|
QDF_STATUS_SUCCESS) {
|
||||||
|
TAILQ_REMOVE(&soc->inactive_peer_list, peer,
|
||||||
|
inactive_list_elem);
|
||||||
|
qdf_spin_unlock_bh
|
||||||
|
(&soc->inactive_peer_list_lock);
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
|
qdf_spin_unlock_bh(&soc->inactive_peer_list_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static inline struct dp_peer *dp_peer_can_reuse(struct dp_vdev *vdev,
|
|
||||||
uint8_t *peer_mac_addr)
|
|
||||||
{
|
|
||||||
struct dp_peer *peer;
|
|
||||||
|
|
||||||
peer = dp_peer_find_hash_find(vdev->pdev->soc, peer_mac_addr,
|
|
||||||
0, vdev->vdev_id,
|
|
||||||
DP_MOD_ID_CONFIG);
|
|
||||||
if (!peer)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (peer->bss_peer && (peer->vdev->vdev_id == vdev->vdev_id))
|
|
||||||
return peer;
|
|
||||||
|
|
||||||
dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FEATURE_AST
|
#ifdef FEATURE_AST
|
||||||
static inline void dp_peer_ast_handle_roam_del(struct dp_soc *soc,
|
static inline void dp_peer_ast_handle_roam_del(struct dp_soc *soc,
|
||||||
@@ -5699,9 +5691,15 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
|
|||||||
peer = dp_peer_can_reuse(vdev, peer_mac_addr);
|
peer = dp_peer_can_reuse(vdev, peer_mac_addr);
|
||||||
|
|
||||||
if (peer) {
|
if (peer) {
|
||||||
|
dp_peer_vdev_list_add(soc, vdev, peer);
|
||||||
|
|
||||||
|
dp_peer_find_hash_add(soc, peer);
|
||||||
qdf_atomic_init(&peer->is_default_route_set);
|
qdf_atomic_init(&peer->is_default_route_set);
|
||||||
dp_peer_cleanup(vdev, peer);
|
dp_peer_cleanup(vdev, peer);
|
||||||
|
|
||||||
|
for (i = 0; i < DP_MAX_TIDS; i++)
|
||||||
|
qdf_spinlock_create(&peer->rx_tid[i].tid_lock);
|
||||||
|
|
||||||
qdf_spin_lock_bh(&soc->ast_lock);
|
qdf_spin_lock_bh(&soc->ast_lock);
|
||||||
dp_peer_delete_ast_entries(soc, peer);
|
dp_peer_delete_ast_entries(soc, peer);
|
||||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||||
@@ -5871,6 +5869,7 @@ dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
|
|||||||
|
|
||||||
dp_set_peer_isolation(peer, false);
|
dp_set_peer_isolation(peer, false);
|
||||||
|
|
||||||
|
qdf_spinlock_create(&peer->peer_state_lock);
|
||||||
dp_peer_update_state(soc, peer, DP_PEER_STATE_INIT);
|
dp_peer_update_state(soc, peer, DP_PEER_STATE_INIT);
|
||||||
|
|
||||||
dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP);
|
dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP);
|
||||||
@@ -6557,7 +6556,7 @@ void dp_peer_unref_delete(struct dp_peer *peer, enum dp_mod_id mod_id)
|
|||||||
struct cdp_peer_cookie peer_cookie;
|
struct cdp_peer_cookie peer_cookie;
|
||||||
struct dp_peer *tmp_peer;
|
struct dp_peer *tmp_peer;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int tid;
|
int tid = 0;
|
||||||
|
|
||||||
if (mod_id > DP_MOD_ID_RX)
|
if (mod_id > DP_MOD_ID_RX)
|
||||||
QDF_ASSERT(qdf_atomic_dec_return(&peer->mod_refs[mod_id]) >= 0);
|
QDF_ASSERT(qdf_atomic_dec_return(&peer->mod_refs[mod_id]) >= 0);
|
||||||
@@ -6623,9 +6622,12 @@ void dp_peer_unref_delete(struct dp_peer *peer, enum dp_mod_id mod_id)
|
|||||||
DP_AST_ASSERT(TAILQ_EMPTY(&peer->ast_entry_list));
|
DP_AST_ASSERT(TAILQ_EMPTY(&peer->ast_entry_list));
|
||||||
dp_peer_update_state(soc, peer, DP_PEER_STATE_FREED);
|
dp_peer_update_state(soc, peer, DP_PEER_STATE_FREED);
|
||||||
|
|
||||||
|
/* cleanup the peer data */
|
||||||
|
dp_peer_cleanup(vdev, peer);
|
||||||
for (tid = 0; tid < DP_MAX_TIDS; tid++)
|
for (tid = 0; tid < DP_MAX_TIDS; tid++)
|
||||||
qdf_spinlock_destroy(&peer->rx_tid[tid].tid_lock);
|
qdf_spinlock_destroy(&peer->rx_tid[tid].tid_lock);
|
||||||
|
|
||||||
|
qdf_spinlock_destroy(&peer->peer_state_lock);
|
||||||
qdf_mem_free(peer);
|
qdf_mem_free(peer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -6704,6 +6706,11 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl,
|
|||||||
|
|
||||||
dp_peer_vdev_list_remove(soc, vdev, peer);
|
dp_peer_vdev_list_remove(soc, vdev, peer);
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&soc->inactive_peer_list_lock);
|
||||||
|
TAILQ_INSERT_TAIL(&soc->inactive_peer_list, peer,
|
||||||
|
inactive_list_elem);
|
||||||
|
qdf_spin_unlock_bh(&soc->inactive_peer_list_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the reference added during peer_attach.
|
* Remove the reference added during peer_attach.
|
||||||
* The peer will still be left allocated until the
|
* The peer will still be left allocated until the
|
||||||
@@ -10064,9 +10071,6 @@ dp_peer_teardown_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
|
|||||||
return QDF_STATUS_E_FAILURE;
|
return QDF_STATUS_E_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peer->peer_state == DP_PEER_STATE_INIT)
|
|
||||||
dp_peer_cleanup(peer->vdev, peer);
|
|
||||||
|
|
||||||
qdf_spin_lock_bh(&soc->ast_lock);
|
qdf_spin_lock_bh(&soc->ast_lock);
|
||||||
dp_peer_delete_ast_entries(soc, peer);
|
dp_peer_delete_ast_entries(soc, peer);
|
||||||
|
|
||||||
|
@@ -890,7 +890,7 @@ QDF_STATUS dp_peer_add_ast(struct dp_soc *soc,
|
|||||||
|
|
||||||
qdf_spin_lock_bh(&soc->ast_lock);
|
qdf_spin_lock_bh(&soc->ast_lock);
|
||||||
|
|
||||||
if (peer->peer_state != DP_PEER_STATE_ACTIVE) {
|
if (!dp_peer_state_cmp(peer, DP_PEER_STATE_ACTIVE)) {
|
||||||
if ((type != CDP_TXRX_AST_TYPE_STATIC) &&
|
if ((type != CDP_TXRX_AST_TYPE_STATIC) &&
|
||||||
(type != CDP_TXRX_AST_TYPE_SELF)) {
|
(type != CDP_TXRX_AST_TYPE_SELF)) {
|
||||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||||
@@ -1319,7 +1319,7 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer,
|
|||||||
* 3) We did not get the HTT map for create event
|
* 3) We did not get the HTT map for create event
|
||||||
*/
|
*/
|
||||||
if (ast_entry->delete_in_progress ||
|
if (ast_entry->delete_in_progress ||
|
||||||
(peer->peer_state != DP_PEER_STATE_ACTIVE) ||
|
!dp_peer_state_cmp(peer, DP_PEER_STATE_ACTIVE) ||
|
||||||
!ast_entry->is_mapped)
|
!ast_entry->is_mapped)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -1983,7 +1983,7 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc,
|
|||||||
* if peer is in logical delete CP triggered delete before map
|
* if peer is in logical delete CP triggered delete before map
|
||||||
* is received ignore this event
|
* is received ignore this event
|
||||||
*/
|
*/
|
||||||
if (peer->peer_state == DP_PEER_STATE_LOGICAL_DELETE) {
|
if (dp_peer_state_cmp(peer, DP_PEER_STATE_LOGICAL_DELETE)) {
|
||||||
dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
|
dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
|
||||||
dp_alert("Peer %pK["QDF_MAC_ADDR_FMT"] logical delete state vid %d",
|
dp_alert("Peer %pK["QDF_MAC_ADDR_FMT"] logical delete state vid %d",
|
||||||
peer, QDF_MAC_ADDR_REF(peer_mac_addr),
|
peer, QDF_MAC_ADDR_REF(peer_mac_addr),
|
||||||
@@ -2171,14 +2171,8 @@ dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
vdev = peer->vdev;
|
vdev = peer->vdev;
|
||||||
/* cleanup the peer data */
|
|
||||||
dp_peer_cleanup(vdev, peer);
|
|
||||||
DP_UPDATE_STATS(vdev, peer);
|
DP_UPDATE_STATS(vdev, peer);
|
||||||
|
|
||||||
qdf_spin_lock_bh(&soc->inactive_peer_list_lock);
|
|
||||||
TAILQ_INSERT_TAIL(&soc->inactive_peer_list, peer, inactive_list_elem);
|
|
||||||
qdf_spin_unlock_bh(&soc->inactive_peer_list_lock);
|
|
||||||
|
|
||||||
dp_peer_update_state(soc, peer, DP_PEER_STATE_INACTIVE);
|
dp_peer_update_state(soc, peer, DP_PEER_STATE_INACTIVE);
|
||||||
dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
|
dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
|
||||||
/*
|
/*
|
||||||
|
@@ -434,6 +434,28 @@ dp_soc_iterate_peer_lock_safe(struct dp_soc *soc,
|
|||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp_peer_state_cmp() - compare dp peer state
|
||||||
|
*
|
||||||
|
* @peer : DP peer
|
||||||
|
* @state : state
|
||||||
|
*
|
||||||
|
* Return: true if state matches with peer state
|
||||||
|
* false if it does not match
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
dp_peer_state_cmp(struct dp_peer *peer,
|
||||||
|
enum dp_peer_state state)
|
||||||
|
{
|
||||||
|
bool is_status_equal = false;
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&peer->peer_state_lock);
|
||||||
|
is_status_equal = (peer->peer_state == state);
|
||||||
|
qdf_spin_unlock_bh(&peer->peer_state_lock);
|
||||||
|
|
||||||
|
return is_status_equal;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dp_peer_update_state() - update dp peer state
|
* dp_peer_update_state() - update dp peer state
|
||||||
*
|
*
|
||||||
@@ -448,7 +470,10 @@ dp_peer_update_state(struct dp_soc *soc,
|
|||||||
struct dp_peer *peer,
|
struct dp_peer *peer,
|
||||||
enum dp_peer_state state)
|
enum dp_peer_state state)
|
||||||
{
|
{
|
||||||
uint8_t peer_state = peer->peer_state;
|
uint8_t peer_state;
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&peer->peer_state_lock);
|
||||||
|
peer_state = peer->peer_state;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case DP_PEER_STATE_INIT:
|
case DP_PEER_STATE_INIT:
|
||||||
@@ -488,12 +513,14 @@ dp_peer_update_state(struct dp_soc *soc,
|
|||||||
default:
|
default:
|
||||||
dp_alert("Invalid peer state %u for peer "QDF_MAC_ADDR_FMT,
|
dp_alert("Invalid peer state %u for peer "QDF_MAC_ADDR_FMT,
|
||||||
state, QDF_MAC_ADDR_REF(peer->mac_addr.raw));
|
state, QDF_MAC_ADDR_REF(peer->mac_addr.raw));
|
||||||
|
qdf_spin_unlock_bh(&peer->peer_state_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dp_info("Updating peer state from %u to %u mac "QDF_MAC_ADDR_FMT"\n",
|
dp_info("Updating peer state from %u to %u mac "QDF_MAC_ADDR_FMT"\n",
|
||||||
peer_state, state,
|
peer_state, state,
|
||||||
QDF_MAC_ADDR_REF(peer->mac_addr.raw));
|
QDF_MAC_ADDR_REF(peer->mac_addr.raw));
|
||||||
peer->peer_state = state;
|
peer->peer_state = state;
|
||||||
|
qdf_spin_unlock_bh(&peer->peer_state_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dp_print_ast_stats(struct dp_soc *soc);
|
void dp_print_ast_stats(struct dp_soc *soc);
|
||||||
|
@@ -177,29 +177,29 @@ enum dp_peer_state {
|
|||||||
* enum for modules ids of
|
* enum for modules ids of
|
||||||
*/
|
*/
|
||||||
enum dp_mod_id {
|
enum dp_mod_id {
|
||||||
DP_MOD_ID_TX_COMP,
|
DP_MOD_ID_TX_COMP = 0,
|
||||||
DP_MOD_ID_RX,
|
DP_MOD_ID_RX = 1,
|
||||||
DP_MOD_ID_HTT_COMP,
|
DP_MOD_ID_HTT_COMP = 2,
|
||||||
DP_MOD_ID_RX_ERR,
|
DP_MOD_ID_RX_ERR = 3,
|
||||||
DP_MOD_ID_TX_PPDU_STATS,
|
DP_MOD_ID_TX_PPDU_STATS = 4,
|
||||||
DP_MOD_ID_RX_PPDU_STATS,
|
DP_MOD_ID_RX_PPDU_STATS = 5,
|
||||||
DP_MOD_ID_CDP,
|
DP_MOD_ID_CDP = 6,
|
||||||
DP_MOD_ID_GENERIC_STATS,
|
DP_MOD_ID_GENERIC_STATS = 7,
|
||||||
DP_MOD_ID_TX_MULTIPASS,
|
DP_MOD_ID_TX_MULTIPASS = 8,
|
||||||
DP_MOD_ID_TX_CAPTURE,
|
DP_MOD_ID_TX_CAPTURE = 9,
|
||||||
DP_MOD_ID_NSS_OFFLOAD,
|
DP_MOD_ID_NSS_OFFLOAD = 10,
|
||||||
DP_MOD_ID_CONFIG,
|
DP_MOD_ID_CONFIG = 11,
|
||||||
DP_MOD_ID_HTT,
|
DP_MOD_ID_HTT = 12,
|
||||||
DP_MOD_ID_IPA,
|
DP_MOD_ID_IPA = 13,
|
||||||
DP_MOD_ID_AST,
|
DP_MOD_ID_AST = 14,
|
||||||
DP_MOD_ID_MCAST2UCAST,
|
DP_MOD_ID_MCAST2UCAST = 15,
|
||||||
DP_MOD_ID_CHILD,
|
DP_MOD_ID_CHILD = 16,
|
||||||
DP_MOD_ID_MESH,
|
DP_MOD_ID_MESH = 17,
|
||||||
DP_MOD_ID_TX_EXCEPTION,
|
DP_MOD_ID_TX_EXCEPTION = 18,
|
||||||
DP_MOD_ID_TDLS,
|
DP_MOD_ID_TDLS = 19,
|
||||||
DP_MOD_ID_MISC,
|
DP_MOD_ID_MISC = 20,
|
||||||
DP_MOD_ID_MSCS,
|
DP_MOD_ID_MSCS = 21,
|
||||||
DP_MOD_ID_MAX,
|
DP_MOD_ID_MAX = 22,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DP_PDEV_ITERATE_VDEV_LIST(_pdev, _vdev) \
|
#define DP_PDEV_ITERATE_VDEV_LIST(_pdev, _vdev) \
|
||||||
@@ -2291,9 +2291,6 @@ struct dp_vdev {
|
|||||||
/* Rx Decapsulation type for this VAP */
|
/* Rx Decapsulation type for this VAP */
|
||||||
enum htt_cmn_pkt_type rx_decap_type;
|
enum htt_cmn_pkt_type rx_decap_type;
|
||||||
|
|
||||||
/* BSS peer */
|
|
||||||
struct dp_peer *vap_bss_peer;
|
|
||||||
|
|
||||||
/* WDS enabled */
|
/* WDS enabled */
|
||||||
bool wds_enabled;
|
bool wds_enabled;
|
||||||
|
|
||||||
@@ -2736,6 +2733,7 @@ struct dp_peer {
|
|||||||
qdf_atomic_t mod_refs[DP_MOD_ID_MAX];
|
qdf_atomic_t mod_refs[DP_MOD_ID_MAX];
|
||||||
|
|
||||||
uint8_t peer_state;
|
uint8_t peer_state;
|
||||||
|
qdf_spinlock_t peer_state_lock;
|
||||||
#ifdef WLAN_SUPPORT_MSCS
|
#ifdef WLAN_SUPPORT_MSCS
|
||||||
struct dp_peer_mscs_parameter mscs_ipv4_parameter, mscs_ipv6_parameter;
|
struct dp_peer_mscs_parameter mscs_ipv4_parameter, mscs_ipv6_parameter;
|
||||||
bool mscs_active;
|
bool mscs_active;
|
||||||
|
Reference in New Issue
Block a user