diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index bb5c47d6dc..a448e230b6 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -520,6 +520,80 @@ static inline void cdp_peer_ast_set_type soc->ops->cmn_drv_ops->txrx_peer_ast_set_type(soc, ast_handle, type); } +#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND) +static inline void cdp_peer_ast_set_cp_ctx(struct cdp_soc_t *soc, + void *ast_handle, + void *cp_ctx) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "Invalid Instance:"); + QDF_BUG(0); + return; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_ast_set_cp_ctx) + return; + + soc->ops->cmn_drv_ops->txrx_peer_ast_set_cp_ctx(soc, ast_handle, + cp_ctx); +} + +static inline void *cdp_peer_ast_get_cp_ctx(struct cdp_soc_t *soc, + void *ast_handle) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "Invalid Instance:"); + QDF_BUG(0); + return NULL; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_ast_get_cp_ctx) + return NULL; + + return soc->ops->cmn_drv_ops->txrx_peer_ast_get_cp_ctx(soc, ast_handle); +} + +static inline bool cdp_peer_ast_get_wmi_sent(struct cdp_soc_t *soc, + void *ast_handle) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "Invalid Instance:"); + QDF_BUG(0); + return false; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_ast_get_wmi_sent) + return false; + + return soc->ops->cmn_drv_ops->txrx_peer_ast_get_wmi_sent(soc, + ast_handle); +} + +static inline +void cdp_peer_ast_free_entry(struct cdp_soc_t *soc, + void *ast_handle) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "Invalid Instance:"); + QDF_BUG(0); + return; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_ast_free_entry) + return; + + soc->ops->cmn_drv_ops->txrx_peer_ast_free_entry(soc, ast_handle); +} +#endif + static inline void cdp_peer_teardown (ol_txrx_soc_handle soc, struct cdp_vdev *vdev, void *peer) { diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index fe293fae39..eae5b563a0 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -118,6 +118,20 @@ struct cdp_cmn_ops { void (*txrx_peer_ast_set_type) (ol_txrx_soc_handle soc, void *ast_hdl, enum cdp_txrx_ast_entry_type type); +#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND) + void (*txrx_peer_ast_set_cp_ctx)(ol_txrx_soc_handle soc, + void *ast_entry, + void *cp_ctx); + + void * (*txrx_peer_ast_get_cp_ctx)(ol_txrx_soc_handle soc, + void *ast_entry); + + bool (*txrx_peer_ast_get_wmi_sent)(ol_txrx_soc_handle soc, + void *ast_entry); + + void (*txrx_peer_ast_free_entry)(ol_txrx_soc_handle soc, + void *ast_entry); +#endif enum cdp_txrx_ast_entry_type (*txrx_peer_ast_get_type) (ol_txrx_soc_handle soc, void *ast_hdl); @@ -803,6 +817,9 @@ struct ol_if_ops { uint32_t flags); void (*peer_del_wds_entry)(void *ol_soc_handle, uint8_t *wds_macaddr); +#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND) + void (*peer_del_wds_cp_ctx)(void *cp_ctx); +#endif QDF_STATUS (*lro_hash_config)(struct wlan_objmgr_psoc *ctrl_psoc, struct cdp_lro_hash_config *rx_offld_hash); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 3a616a3eb1..57f43a5ec3 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -644,6 +644,58 @@ static enum cdp_txrx_ast_entry_type dp_peer_ast_get_type_wifi3( return ((struct dp_ast_entry *)ast_entry_hdl)->type; } +#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND) +void dp_peer_ast_set_cp_ctx_wifi3(struct cdp_soc_t *soc_handle, + void *ast_entry, + void *cp_ctx) +{ + struct dp_soc *soc = (struct dp_soc *)soc_handle; + + qdf_spin_lock_bh(&soc->ast_lock); + dp_peer_ast_set_cp_ctx(soc, + (struct dp_ast_entry *)ast_entry, cp_ctx); + qdf_spin_unlock_bh(&soc->ast_lock); +} + +void *dp_peer_ast_get_cp_ctx_wifi3(struct cdp_soc_t *soc_handle, + void *ast_entry) +{ + struct dp_soc *soc = (struct dp_soc *)soc_handle; + void *cp_ctx = NULL; + + qdf_spin_lock_bh(&soc->ast_lock); + cp_ctx = dp_peer_ast_get_cp_ctx(soc, + (struct dp_ast_entry *)ast_entry); + qdf_spin_unlock_bh(&soc->ast_lock); + + return cp_ctx; +} + +bool dp_peer_ast_get_wmi_sent_wifi3(struct cdp_soc_t *soc_handle, + void *ast_entry) +{ + struct dp_soc *soc = (struct dp_soc *)soc_handle; + bool wmi_sent = false; + + qdf_spin_lock_bh(&soc->ast_lock); + wmi_sent = dp_peer_ast_get_wmi_sent(soc, + (struct dp_ast_entry *)ast_entry); + qdf_spin_unlock_bh(&soc->ast_lock); + + return wmi_sent; +} + +void dp_peer_ast_free_entry_wifi3(struct cdp_soc_t *soc_handle, + void *ast_entry) +{ + struct dp_soc *soc = (struct dp_soc *)soc_handle; + + qdf_spin_lock_bh(&soc->ast_lock); + dp_peer_ast_free_entry(soc, (struct dp_ast_entry *)ast_entry); + qdf_spin_unlock_bh(&soc->ast_lock); +} +#endif + /** * dp_srng_find_ring_in_mask() - find which ext_group a ring belongs * @ring_num: ring num of the ring being queried @@ -7699,6 +7751,12 @@ static struct cdp_cmn_ops dp_ops_cmn = { .txrx_peer_ast_get_next_hop = dp_peer_ast_get_next_hop_wifi3, .txrx_peer_ast_set_type = dp_peer_ast_set_type_wifi3, .txrx_peer_ast_get_type = dp_peer_ast_get_type_wifi3, +#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND) + .txrx_peer_ast_set_cp_ctx = dp_peer_ast_set_cp_ctx_wifi3, + .txrx_peer_ast_get_cp_ctx = dp_peer_ast_get_cp_ctx_wifi3, + .txrx_peer_ast_get_wmi_sent = dp_peer_ast_get_wmi_sent_wifi3, + .txrx_peer_ast_free_entry = dp_peer_ast_free_entry_wifi3, +#endif .txrx_peer_delete = dp_peer_delete_wifi3, .txrx_vdev_register = dp_vdev_register_wifi3, .txrx_soc_detach = dp_soc_detach_wifi3, diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 4b4e0ce91b..8b4876708f 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -225,6 +225,21 @@ static int dp_peer_ast_hash_attach(struct dp_soc *soc) return 0; } +#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND) +static inline void dp_peer_ast_cleanup(struct dp_soc *soc, + struct dp_ast_entry *ast) +{ + struct cdp_soc_t *cdp_soc = &soc->cdp_soc; + + if (ast->cp_ctx && cdp_soc->ol_ops->peer_del_wds_cp_ctx) + cdp_soc->ol_ops->peer_del_wds_cp_ctx(ast->cp_ctx); +} +#else +static inline void dp_peer_ast_cleanup(struct dp_soc *soc, + struct dp_ast_entry *ast) +{ +} +#endif /* * dp_peer_ast_hash_detach() - Free AST Hash table * @soc: SoC handle @@ -529,6 +544,22 @@ int dp_peer_add_ast(struct dp_soc *soc, return ret; } +#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND) +void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) +{ + struct dp_peer *peer = ast_entry->peer; + + if (ast_entry->next_hop) { + dp_peer_ast_send_wds_del(soc, ast_entry); + } else { + soc->ast_table[ast_entry->ast_idx] = NULL; + TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); + DP_STATS_INC(soc, ast.deleted, 1); + dp_peer_ast_hash_remove(soc, ast_entry); + qdf_mem_free(ast_entry); + } +} +#else /* * dp_peer_del_ast() - Delete and free AST entry * @soc: SoC handle @@ -558,6 +589,7 @@ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) dp_peer_ast_hash_remove(soc, ast_entry); qdf_mem_free(ast_entry); } +#endif /* * dp_peer_update_ast() - Delete and free AST entry @@ -708,6 +740,57 @@ uint8_t dp_peer_ast_get_next_hop(struct dp_soc *soc, } #endif +#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND) +void dp_peer_ast_set_cp_ctx(struct dp_soc *soc, + struct dp_ast_entry *ast_entry, + void *cp_ctx) +{ + ast_entry->cp_ctx = cp_ctx; +} + +void *dp_peer_ast_get_cp_ctx(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + void *cp_ctx = NULL; + + cp_ctx = ast_entry->cp_ctx; + ast_entry->cp_ctx = NULL; + + return cp_ctx; +} + +void dp_peer_ast_send_wds_del(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + struct dp_peer *peer = ast_entry->peer; + struct cdp_soc_t *cdp_soc = &soc->cdp_soc; + + if (!ast_entry->wmi_sent) { + cdp_soc->ol_ops->peer_del_wds_entry(peer->vdev->osif_vdev, + ast_entry->mac_addr.raw); + ast_entry->wmi_sent = true; + } +} + +bool dp_peer_ast_get_wmi_sent(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + return ast_entry->wmi_sent; +} + +void dp_peer_ast_free_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + struct dp_peer *peer = ast_entry->peer; + + soc->ast_table[ast_entry->ast_idx] = NULL; + TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); + DP_STATS_INC(soc, ast.deleted, 1); + dp_peer_ast_hash_remove(soc, ast_entry); + qdf_mem_free(ast_entry); +} +#endif + struct dp_peer *dp_peer_find_hash_find(struct dp_soc *soc, uint8_t *peer_mac_addr, int mac_addr_is_aligned, uint8_t vdev_id) { diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 2a456b81bc..c7827f0b81 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -107,6 +107,25 @@ void dp_peer_ast_set_type(struct dp_soc *soc, struct dp_ast_entry *ast_entry, enum cdp_txrx_ast_entry_type type); +#if defined(FEATURE_AST) && defined(AST_HKV1_WORKAROUND) +void dp_peer_ast_set_cp_ctx(struct dp_soc *soc, + struct dp_ast_entry *ast_entry, + void *cp_ctx); + +void *dp_peer_ast_get_cp_ctx(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + +void dp_peer_ast_send_wds_del(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + +bool dp_peer_ast_get_wmi_sent(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + +void dp_peer_ast_free_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + +#endif + /* * dp_get_vdev_from_soc_vdev_id_wifi3() - * Returns vdev object given the vdev id diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index af456870a0..2f1043be68 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -622,6 +622,8 @@ union dp_align_mac_addr { * @ast_hash_value: hast value in HW * @ref_cnt: reference count * @type: flag to indicate type of the entry(static/WDS/MEC) + * @wmi_sent: Flag to identify of WMI to del ast is sent (AST_HKV1_WORKAROUND) + * @cp_ctx: Opaque context used by control path (AST_HKV1_WORKAROUND) * @hash_list_elem: node in soc AST hash list (mac address used as hash) */ struct dp_ast_entry { @@ -637,6 +639,10 @@ struct dp_ast_entry { uint16_t ast_hash_value; qdf_atomic_t ref_cnt; enum cdp_txrx_ast_entry_type type; +#ifdef AST_HKV1_WORKAROUND + bool wmi_sent; + void *cp_ctx; +#endif TAILQ_ENTRY(dp_ast_entry) ase_list_elem; TAILQ_ENTRY(dp_ast_entry) hash_list_elem; }; diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 2eed73a4f1..6538517ed0 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -20574,6 +20574,8 @@ static QDF_STATUS extract_wds_addr_event_tlv(wmi_unified_t wmi_handle, wds_ev->dest_mac[4+i] = ((u_int8_t *)&(ev->dest_mac.mac_addr47to32))[i]; } + wds_ev->vdev_id = ev->vdev_id; + return QDF_STATUS_SUCCESS; } @@ -23242,6 +23244,9 @@ static void populate_tlv_events_id(uint32_t *event_ids) event_ids[wmi_wlan_sar2_result_event_id] = WMI_SAR2_RESULT_EVENTID; event_ids[wmi_esp_estimate_event_id] = WMI_ESP_ESTIMATE_EVENTID; event_ids[wmi_roam_scan_stats_event_id] = WMI_ROAM_SCAN_STATS_EVENTID; +#ifdef AST_HKV1_WORKAROUND + event_ids[wmi_wds_peer_event_id] = WMI_WDS_PEER_EVENTID; +#endif } /**