diff --git a/components/tdls/core/src/wlan_tdls_ct.c b/components/tdls/core/src/wlan_tdls_ct.c index e8236e0ba3..3d00088ab1 100644 --- a/components/tdls/core/src/wlan_tdls_ct.c +++ b/components/tdls/core/src/wlan_tdls_ct.c @@ -816,8 +816,8 @@ void tdls_ct_idle_handler(void *user_data) */ static void tdls_ct_process_idle_and_discovery(struct tdls_peer *curr_peer, - struct tdls_vdev_priv_obj *tdls_vdev_obj, - struct tdls_soc_priv_obj *tdls_soc_obj) + struct tdls_vdev_priv_obj *tdls_vdev_obj, + struct tdls_soc_priv_obj *tdls_soc_obj) { uint16_t valid_peers; @@ -942,10 +942,10 @@ static void tdls_ct_process_cap_unknown(struct tdls_peer *curr_peer, struct tdls_vdev_priv_obj *tdls_vdev, struct tdls_soc_priv_obj *tdls_soc) { - if (TDLS_IS_EXTERNAL_CONTROL_ENABLED( - tdls_soc->tdls_configs.tdls_feature_flags) && - (!curr_peer->is_forced_peer)) - return; + if (!curr_peer->is_forced_peer && + TDLS_IS_EXTERNAL_CONTROL_ENABLED( + tdls_soc->tdls_configs.tdls_feature_flags)) + return; if (curr_peer->rx_pkt || curr_peer->tx_pkt) tdls_debug(QDF_MAC_ADDR_FMT "link_status %d tdls_support %d tx %d rx %d vdev %d", @@ -954,29 +954,31 @@ static void tdls_ct_process_cap_unknown(struct tdls_peer *curr_peer, curr_peer->tx_pkt, curr_peer->rx_pkt, wlan_vdev_get_id(tdls_vdev->vdev)); - if (!TDLS_IS_LINK_CONNECTED(curr_peer) && - ((curr_peer->tx_pkt + curr_peer->rx_pkt) >= - tdls_vdev->threshold_config.tx_packet_n)) { - /* Ignore discovery attempt if External Control is enabled, that + if (TDLS_IS_LINK_CONNECTED(curr_peer)) + return; + + if ((curr_peer->tx_pkt + curr_peer->rx_pkt) >= + tdls_vdev->threshold_config.tx_packet_n) { + /* + * Ignore discovery attempt if External Control is enabled, that * is, peer is forced. In that case, continue discovery attempt * regardless attempt count */ tdls_debug("TDLS UNKNOWN pre discover "); if (curr_peer->is_forced_peer || - curr_peer->discovery_attempt++ < + curr_peer->discovery_attempt < tdls_vdev->threshold_config.discovery_tries_n) { tdls_debug("TDLS UNKNOWN discover "); tdls_vdev->curr_candidate = curr_peer; tdls_implicit_send_discovery_request(tdls_vdev); - } else { - if (curr_peer->link_status != TDLS_LINK_CONNECTING) { - curr_peer->tdls_support = - TDLS_CAP_NOT_SUPPORTED; - tdls_set_peer_link_status( - curr_peer, - TDLS_LINK_IDLE, - TDLS_LINK_NOT_SUPPORTED); - } + + return; + } + + if (curr_peer->link_status != TDLS_LINK_CONNECTING) { + curr_peer->tdls_support = TDLS_CAP_NOT_SUPPORTED; + tdls_set_peer_link_status(curr_peer, TDLS_LINK_IDLE, + TDLS_LINK_NOT_SUPPORTED); } } } diff --git a/components/tdls/core/src/wlan_tdls_main.c b/components/tdls/core/src/wlan_tdls_main.c index e6a1aa807e..3383adbed0 100644 --- a/components/tdls/core/src/wlan_tdls_main.c +++ b/components/tdls/core/src/wlan_tdls_main.c @@ -1550,6 +1550,37 @@ tdls_process_sta_connect(struct tdls_sta_notify_params *notify) return QDF_STATUS_SUCCESS; } +static void +tdls_update_discovery_tries(struct wlan_objmgr_vdev *vdev) +{ + struct tdls_soc_priv_obj *soc_obj; + struct tdls_vdev_priv_obj *vdev_obj; + struct tdls_user_config *tdls_config; + struct tdls_config_params *vdev_config; + QDF_STATUS status; + + status = tdls_get_vdev_objects(vdev, &vdev_obj, &soc_obj); + if (QDF_IS_STATUS_ERROR(status)) { + tdls_err("can't get vdev_obj & soc_obj"); + return; + } + + vdev_config = &vdev_obj->threshold_config; + tdls_config = &soc_obj->tdls_configs; + + vdev_config->discovery_tries_n = + tdls_config->tdls_max_discovery_attempt; + + /* + * For MLO peer discovery will happen on 2 links and the best link + * will be chosen based on score for TDLS. So factor that into the + * number of discovery attempts to increase the discoverability + * window for the peer. + */ + if (wlan_vdev_mlme_is_mlo_vdev(vdev)) + vdev_config->discovery_tries_n *= 2; +} + QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify) { QDF_STATUS status; @@ -1566,6 +1597,8 @@ QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify) } status = tdls_process_sta_connect(notify); + if (QDF_IS_STATUS_SUCCESS(status)) + tdls_update_discovery_tries(notify->vdev); wlan_objmgr_vdev_release_ref(notify->vdev, WLAN_TDLS_NB_ID); qdf_mem_free(notify); diff --git a/components/tdls/core/src/wlan_tdls_main.h b/components/tdls/core/src/wlan_tdls_main.h index 1313b5ff60..1daa67d696 100644 --- a/components/tdls/core/src/wlan_tdls_main.h +++ b/components/tdls/core/src/wlan_tdls_main.h @@ -473,6 +473,8 @@ wlan_vdev_get_tdls_vdev_obj(struct wlan_objmgr_vdev *vdev) * @mac: mac address of tdls peer * @link_state: tdls link state * @link_reason: reason + * + * Return: None */ void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev, const uint8_t *mac, diff --git a/components/tdls/core/src/wlan_tdls_peer.c b/components/tdls/core/src/wlan_tdls_peer.c index 90acd3502c..e8b5438382 100644 --- a/components/tdls/core/src/wlan_tdls_peer.c +++ b/components/tdls/core/src/wlan_tdls_peer.c @@ -821,15 +821,6 @@ static void tdls_update_pmo_status(struct tdls_vdev_priv_obj *tdls_vdev, } #endif -/** - * tdls_set_link_status() - set link statue for TDLS peer - * @vdev_obj: TDLS vdev object - * @mac: MAC address of current TDLS peer - * @link_status: link status - * @link_reason: reason with link status - * - * Return: None. - */ void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev_obj, const uint8_t *mac, enum tdls_link_state link_status, diff --git a/components/tdls/dispatcher/inc/wlan_tdls_api.h b/components/tdls/dispatcher/inc/wlan_tdls_api.h index fff6670dc1..a31b7c10af 100644 --- a/components/tdls/dispatcher/inc/wlan_tdls_api.h +++ b/components/tdls/dispatcher/inc/wlan_tdls_api.h @@ -193,6 +193,19 @@ void wlan_tdls_handle_p2p_client_connect(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev) {} #endif /* WLAN_FEATURE_TDLS_CONCURRENCIES */ + +/** + * wlan_tdls_increment_discovery_attempts() - Increment TDLS peer discovery + * attempts + * @psoc: Pointer to PSOC object + * @vdev_id: Vdev id + * @peer_addr: Peer mac address + * + * Return: None + */ +void wlan_tdls_increment_discovery_attempts(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + uint8_t *peer_addr); #else #ifdef FEATURE_SET @@ -267,5 +280,11 @@ void wlan_tdls_handle_p2p_client_connect(struct wlan_objmgr_psoc *psoc, static inline void wlan_tdls_notify_start_bss_failure(struct wlan_objmgr_psoc *psoc) {} + +static inline +void wlan_tdls_increment_discovery_attempts(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + uint8_t *peer_addr) +{} #endif #endif diff --git a/components/tdls/dispatcher/src/wlan_tdls_api.c b/components/tdls/dispatcher/src/wlan_tdls_api.c index 980d477129..88d8ec3f98 100644 --- a/components/tdls/dispatcher/src/wlan_tdls_api.c +++ b/components/tdls/dispatcher/src/wlan_tdls_api.c @@ -26,6 +26,7 @@ #include "../../core/src/wlan_tdls_main.h" #include "../../core/src/wlan_tdls_ct.h" #include "../../core/src/wlan_tdls_mgmt.h" +#include "wlan_tdls_peer.h" #include #include #include "wlan_tdls_cfg_api.h" @@ -470,3 +471,39 @@ void wlan_tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev *vdev, { tdls_update_rx_pkt_cnt(vdev, mac_addr, dest_mac_addr); } + +void wlan_tdls_increment_discovery_attempts(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + uint8_t *peer_addr) +{ + struct tdls_soc_priv_obj *tdls_soc_obj; + struct tdls_vdev_priv_obj *tdls_vdev_obj; + struct tdls_peer *peer; + struct wlan_objmgr_vdev *vdev; + QDF_STATUS status; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_TDLS_NB_ID); + if (!vdev) + return; + + status = tdls_get_vdev_objects(vdev, &tdls_vdev_obj, &tdls_soc_obj); + if (QDF_IS_STATUS_ERROR(status)) { + tdls_err("Failed to get TDLS objects"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID); + return; + } + + peer = tdls_get_peer(tdls_vdev_obj, peer_addr); + if (!peer) { + tdls_err("tdls_peer is NULL"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID); + return; + } + + peer->discovery_attempt++; + tdls_debug("vdev:%d peer discovery attempts:%d", vdev_id, + peer->discovery_attempt); + + wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID); +} diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index 18f105eda1..d206e157e3 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -98,6 +98,21 @@ static const uint8_t eth_890d_header[] = { 0x00, 0x00, 0x89, 0x0d, }; +#define ETH_ADDR_LEN 6 /* bytes */ + +struct tdls_ethernet_hdr { + uint8_t dest_addr[ETH_ADDR_LEN]; + uint8_t src_addr[ETH_ADDR_LEN]; +} qdf_packed; + +#define eth_890d_hdr_len 2 /* bytes */ + +static const uint8_t eth_890d_tdls_discvory_frm_hdr[] = { + 0x89, 0x0d, 0x02, 0x0c, 0x0a, +}; + +#define TDLS_ETHR_HDR_LEN (sizeof(struct tdls_ethernet_hdr)) + /* * type of links used in TDLS */ @@ -547,21 +562,45 @@ static uint32_t lim_prepare_tdls_frame_header(struct mac_context *mac, uint8_t * * @tx_complete: indicates tx success/failure * @params: tx completion params * - * function will be invoked on receiving tx completion indication + * Function will be invoked on receiving tx completion indication * - * return: success: eHAL_STATUS_SUCCESS failure: eHAL_STATUS_FAILURE + * Return: success: eHAL_STATUS_SUCCESS failure: eHAL_STATUS_FAILURE */ -static QDF_STATUS lim_mgmt_tdls_tx_complete(void *context, - qdf_nbuf_t buf, - uint32_t tx_complete, - void *params) +static QDF_STATUS lim_mgmt_tdls_tx_complete(void *context, qdf_nbuf_t buf, + uint32_t tx_complete, void *params) { struct mac_context *mac_ctx = (struct mac_context *)context; + struct tdls_ethernet_hdr *ethernet_hdr; + tpSirMacActionFrameHdr action_hdr; + bool is_tdls_discvory_frm; pe_debug("tdls_frm_session_id: %x tx_complete: %x", - mac_ctx->lim.tdls_frm_session_id, tx_complete); + mac_ctx->lim.tdls_frm_session_id, tx_complete); if (NO_SESSION != mac_ctx->lim.tdls_frm_session_id) { + if (buf && + (qdf_nbuf_len(buf) >= (TDLS_ETHR_HDR_LEN + + eth_890d_hdr_len + + PAYLOAD_TYPE_TDLS_SIZE + + sizeof(*action_hdr)))) { + ethernet_hdr = + (struct tdls_ethernet_hdr *)qdf_nbuf_data(buf); + is_tdls_discvory_frm = + !qdf_mem_cmp(((uint8_t *)qdf_nbuf_data(buf) + + TDLS_ETHR_HDR_LEN), + eth_890d_tdls_discvory_frm_hdr, + sizeof(eth_890d_tdls_discvory_frm_hdr)); + + pe_debug("is_tdls_discvory_frm: %d", + is_tdls_discvory_frm); + if (is_tdls_discvory_frm && + tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) + wlan_tdls_increment_discovery_attempts( + mac_ctx->psoc, + mac_ctx->lim.tdls_frm_session_id, + ethernet_hdr->dest_addr); + } + lim_send_sme_mgmt_tx_completion(mac_ctx, mac_ctx->lim.tdls_frm_session_id, tx_complete); @@ -3886,8 +3925,8 @@ lim_send_tdls_comp_mgmt_rsp(struct mac_context *mac_ctx, uint16_t msg_type, struct tdls_send_mgmt_rsp *sme_rsp; QDF_STATUS status; - pe_debug("Sending message %s with reasonCode %s", - lim_msg_str(msg_type), lim_result_code_str(result_code)); + pe_debug("vdev:%d Sending message %s with reasonCode %s", vdev_id, + lim_msg_str(msg_type), lim_result_code_str(result_code)); sme_rsp = qdf_mem_malloc(sizeof(*sme_rsp)); if (!sme_rsp) diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 3b72aa5f81..21103f1b2d 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1124,12 +1124,14 @@ enum frame_index { * @sub_type: sub type * @status: status * @ack_cmp_work: work structure + * @frame: frame nbuf */ struct wma_tx_ack_work_ctx { tp_wma_handle wma_handle; uint16_t sub_type; int32_t status; qdf_work_t ack_cmp_work; + qdf_nbuf_t frame; }; /** diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index d50a5bd284..930fe5d39e 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -963,23 +963,27 @@ static void wma_data_tx_ack_work_handler(void *ack_work) wma_handle = work->wma_handle; if (!wma_handle || cds_is_load_or_unload_in_progress()) { wma_err("Driver load/unload in progress"); - goto end; + goto free_frame; } + + wma_debug("Data Tx Ack Cb Status %d", work->status); ack_cb = wma_handle->umac_data_ota_ack_cb; - - if (work->status) - wma_debug("Data Tx Ack Cb Status %d", work->status); - else - wma_debug("Data Tx Ack Cb Status %d", work->status); - - /* Call the Ack Cb registered by UMAC */ - if (ack_cb) - ack_cb(wma_handle->mac_context, NULL, work->status, NULL); - else + if (!ack_cb) { wma_err("Data Tx Ack Cb is NULL"); + goto free_frame; + } + + ack_cb(wma_handle->mac_context, work->frame, work->status, + NULL); + goto end; + +free_frame: + if (work->frame) + qdf_nbuf_free(work->frame); end: qdf_mem_free(work); + if (wma_handle) { wma_handle->umac_data_ota_ack_cb = NULL; wma_handle->last_umac_data_nbuf = NULL; @@ -1002,38 +1006,59 @@ void wma_data_tx_ack_comp_hdlr(void *wma_context, qdf_nbuf_t netbuf, int32_t status) { tp_wma_handle wma_handle = (tp_wma_handle) wma_context; + struct wma_tx_ack_work_ctx *ack_work; + QDF_STATUS qdf_status; if (wma_validate_handle(wma_handle)) return; + if (!netbuf) { + wma_debug("netbuf is NULL"); + return; + } + /* * if netBuf does not match with pending nbuf then just free the * netbuf and do not call ack cb */ if (wma_handle->last_umac_data_nbuf != netbuf) { - if (wma_handle->umac_data_ota_ack_cb) { - wma_err("nbuf does not match but umac_data_ota_ack_cb is not null"); - } else { - wma_err("nbuf does not match and umac_data_ota_ack_cb is also null"); - } + wma_err("nbuf does not match but umac_data_ota_ack_cb is %s null", + wma_handle->umac_data_ota_ack_cb ? "not" : ""); goto free_nbuf; } - if (wma_handle->umac_data_ota_ack_cb) { - struct wma_tx_ack_work_ctx *ack_work; + if (!wma_handle->umac_data_ota_ack_cb) { + wma_err_rl("ota_ack cb not registered"); + goto free_nbuf; + } - ack_work = qdf_mem_malloc(sizeof(struct wma_tx_ack_work_ctx)); + ack_work = qdf_mem_malloc(sizeof(struct wma_tx_ack_work_ctx)); + if (ack_work) { wma_handle->ack_work_ctx = ack_work; - if (ack_work) { - ack_work->wma_handle = wma_handle; - ack_work->sub_type = 0; - ack_work->status = status; - qdf_create_work(0, &ack_work->ack_cmp_work, - wma_data_tx_ack_work_handler, - ack_work); - qdf_sched_work(0, &ack_work->ack_cmp_work); + ack_work->wma_handle = wma_handle; + ack_work->sub_type = 0; + ack_work->status = status; + ack_work->frame = netbuf; + + /* + * free of the netbuf will be done by the scheduled work so + * just do unmap here + */ + qdf_nbuf_unmap_single(wma_handle->qdf_dev, netbuf, + QDF_DMA_TO_DEVICE); + + qdf_status = qdf_create_work(0, &ack_work->ack_cmp_work, + wma_data_tx_ack_work_handler, + ack_work); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + qdf_nbuf_free(netbuf); + wma_err("Failed to create TX ack work"); + return; } + + qdf_sched_work(0, &ack_work->ack_cmp_work); + return; } free_nbuf: diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index a1fcb92676..0e4f3bde6d 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -4813,6 +4813,9 @@ QDF_STATUS wma_stop(void) if (wma_handle->ack_work_ctx) { cds_flush_work(&wma_handle->ack_work_ctx->ack_cmp_work); + if (wma_handle->ack_work_ctx->frame) + qdf_nbuf_free(wma_handle->ack_work_ctx->frame); + qdf_mem_free(wma_handle->ack_work_ctx); wma_handle->ack_work_ctx = NULL; }