From ed35f4499d15ade1e7dc250b779eb10c44990d57 Mon Sep 17 00:00:00 2001 From: Kiran Venkatappa Date: Thu, 19 Jul 2018 22:22:29 +0530 Subject: [PATCH] qcacmn: Add logic to wait for wds del resp before peer create WDS entry should be removed before adding peer with same mac address. iIn DBDC mode, this can be ensured only by waiting for response for WDS delete from FW before creating peer. Add logic to defer AUTH until WDS is removed from FW. Change-Id: Ie76d08c4817f953504913ae6cc49fc5388169e4a CRs-Fixed: 2270592 --- dp/inc/cdp_txrx_cmn.h | 74 ++++++++++++++++++++++++++++++++++ dp/inc/cdp_txrx_ops.h | 17 ++++++++ dp/wifi3.0/dp_main.c | 58 +++++++++++++++++++++++++++ dp/wifi3.0/dp_peer.c | 83 +++++++++++++++++++++++++++++++++++++++ dp/wifi3.0/dp_peer.h | 19 +++++++++ dp/wifi3.0/dp_types.h | 6 +++ wmi/src/wmi_unified_tlv.c | 5 +++ 7 files changed, 262 insertions(+) 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 } /**