qcacmn: Handle STA roaming to another AP/Repeater

Add support in DP WDS source port learning handler to kickout a STA,
when direct associated peer(SA) roams to another AP/Repeater and
reachable via TA peer

Change-Id: I84d0b92c9b4e39c05f4d7c25b3f5afb1d535ca02
CRs-Fixed: 2219924
This commit is contained in:
Pamidipati, Vijay 2018-04-09 23:03:12 +05:30 • committed by nshrivas
commit d578db10c0
3 changed files with 63 additions and 40 deletions

View file

@ -749,6 +749,8 @@ struct ol_if_ops {
int (*config_bssid_in_fw_for_nac_rssi)(struct wlan_objmgr_pdev *pdev,
u_int8_t vdev_id, enum cdp_nac_param_cmd cmd, char *bssid);
#endif
int (*peer_sta_kickout)(void *osif_pdev, uint8_t *peer_macaddr);
/* TODO: Add any other control path calls required to OL_IF/WMA layer */
};

View file

@ -546,8 +546,25 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer,
{
int ret = -1;
struct dp_peer *old_peer;
struct dp_peer *sa_peer;
qdf_spin_lock_bh(&soc->ast_lock);
if (ast_entry->type == CDP_TXRX_AST_TYPE_STATIC) {
sa_peer = ast_entry->peer;
/*
* Kickout, when direct associated peer(SA) roams
* to another AP and reachable via TA peer
*/
if (!sa_peer->delete_in_progress) {
sa_peer->delete_in_progress = true;
if (soc->cdp_soc.ol_ops->peer_sta_kickout) {
soc->cdp_soc.ol_ops->peer_sta_kickout(
sa_peer->vdev->pdev->osif_pdev,
ast_entry->mac_addr.raw);
}
return 0;
}
}
old_peer = ast_entry->peer;
TAILQ_REMOVE(&old_peer->ast_entry_list, ast_entry, ase_list_elem);
@ -559,19 +576,11 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer,
ast_entry->is_active = TRUE;
TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry, ase_list_elem);
if (ast_entry->type != CDP_TXRX_AST_TYPE_STATIC) {
if (QDF_STATUS_SUCCESS ==
soc->cdp_soc.ol_ops->peer_update_wds_entry(
peer->vdev->osif_vdev,
ret = soc->cdp_soc.ol_ops->peer_update_wds_entry(
peer->vdev->osif_vdev,
ast_entry->mac_addr.raw,
peer->mac_addr.raw,
flags)) {
qdf_spin_unlock_bh(&soc->ast_lock);
return 0;
}
}
qdf_spin_unlock_bh(&soc->ast_lock);
flags);
return ret;
}

View file

@ -366,6 +366,8 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc,
uint32_t flags = IEEE80211_NODE_F_WDS_HM;
uint32_t ret = 0;
uint8_t wds_src_mac[IEEE80211_ADDR_LEN];
struct dp_ast_entry *ast;
uint16_t sa_idx;
/* Do wds source port learning only if it is a 4-address mpdu */
if (!(qdf_nbuf_is_rx_chfrag_start(nbuf) &&
@ -381,32 +383,42 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc,
wds_src_mac,
CDP_TXRX_AST_TYPE_WDS,
flags);
return;
} else {
/*
* Get the AST entry from HW SA index and mark it as active
*/
struct dp_ast_entry *ast;
uint16_t sa_idx = hal_rx_msdu_end_sa_idx_get(rx_tlv_hdr);
ast = soc->ast_table[sa_idx];
/*
* Ensure we are updating the right AST entry by
* validating ast_idx.
* There is a possibility we might arrive here without
* AST MAP event , so this check is mandatory
*/
if (ast && (ast->ast_idx == sa_idx)) {
ast->is_active = TRUE;
}
if (ast && sa_sw_peer_id != ta_peer->peer_ids[0])
dp_peer_update_ast(soc, ta_peer, ast, flags);
}
/*
* Get the AST entry from HW SA index and mark it as active
*/
sa_idx = hal_rx_msdu_end_sa_idx_get(rx_tlv_hdr);
qdf_spin_lock_bh(&soc->ast_lock);
ast = soc->ast_table[sa_idx];
if (!ast) {
qdf_spin_unlock_bh(&soc->ast_lock);
return;
}
/*
* Ensure we are updating the right AST entry by
* validating ast_idx.
* There is a possibility we might arrive here without
* AST MAP event , so this check is mandatory
*/
if (ast->ast_idx == sa_idx)
ast->is_active = TRUE;
/* Handle client roaming */
if (sa_sw_peer_id != ta_peer->peer_ids[0])
dp_peer_update_ast(soc, ta_peer, ast, flags);
qdf_spin_unlock_bh(&soc->ast_lock);
return;
}
#else
static inline void
static inline void
dp_rx_wds_srcport_learn(struct dp_soc *soc,
uint8_t *rx_tlv_hdr,
struct dp_peer *ta_peer,
@ -417,7 +429,7 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc,
uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf);
void dp_rx_process_invalid_peer_wrapper(struct dp_soc *soc,
qdf_nbuf_t mpdu, bool mpdu_done);
qdf_nbuf_t mpdu, bool mpdu_done);
void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr);
#define DP_RX_LIST_APPEND(head, tail, elem) \
@ -428,19 +440,19 @@ void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tl
qdf_nbuf_set_next((tail), (elem)); \
} \
(tail) = (elem); \
qdf_nbuf_set_next((tail), NULL); \
} while (0)
qdf_nbuf_set_next((tail), NULL); \
} while (0)
#ifndef BUILD_X86
static inline int check_x86_paddr(struct dp_soc *dp_soc, qdf_nbuf_t *rx_netbuf,
qdf_dma_addr_t *paddr, struct dp_pdev *pdev)
qdf_dma_addr_t *paddr, struct dp_pdev *pdev)
{
return QDF_STATUS_SUCCESS;
}
#else
#define MAX_RETRY 100
static inline int check_x86_paddr(struct dp_soc *dp_soc, qdf_nbuf_t *rx_netbuf,
qdf_dma_addr_t *paddr, struct dp_pdev *pdev)
qdf_dma_addr_t *paddr, struct dp_pdev *pdev)
{
uint32_t nbuf_retry = 0;
int32_t ret;
@ -455,13 +467,13 @@ static inline int check_x86_paddr(struct dp_soc *dp_soc, qdf_nbuf_t *rx_netbuf,
return QDF_STATUS_SUCCESS;
else {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
"phy addr %pK exceded 0x50000000 trying again\n",
paddr);
"phy addr %pK exceded 0x50000000 trying again\n",
paddr);
nbuf_retry++;
if ((*rx_netbuf)) {
qdf_nbuf_unmap_single(dp_soc->osdev, *rx_netbuf,
QDF_DMA_BIDIRECTIONAL);
QDF_DMA_BIDIRECTIONAL);
/* Not freeing buffer intentionally.
* Observed that same buffer is getting
* re-allocated resulting in longer load time