diff --git a/umac/tdls/core/src/wlan_tdls_main.c b/umac/tdls/core/src/wlan_tdls_main.c index d969d250693d..312a74bf6e77 100644 --- a/umac/tdls/core/src/wlan_tdls_main.c +++ b/umac/tdls/core/src/wlan_tdls_main.c @@ -358,6 +358,106 @@ static void tdls_get_all_peers_from_list( qdf_mem_free(get_tdls_peers); } +/** + * tdls_process_reset_all_peers() - Reset all tdls peers + * @delete_all_peers_ind: Delete all peers indication + * + * This function is called to reset all tdls peers and + * notify upper layers of teardown inidcation + * + * Return: QDF_STATUS + */ + +static QDF_STATUS tdls_process_reset_all_peers(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + uint8_t staidx; + struct tdls_peer *curr_peer = NULL; + struct tdls_vdev_priv_obj *tdls_vdev; + struct tdls_soc_priv_obj *tdls_soc; + uint8_t reset_session_id; + + status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc); + if (QDF_STATUS_SUCCESS != status) { + tdls_err("tdls objects are NULL "); + return status; + } + + if (!tdls_soc->connected_peer_count) { + tdls_debug("No tdls connected peers"); + return status; + } + + reset_session_id = tdls_vdev->session_id; + for (staidx = 0; staidx < tdls_soc->max_num_tdls_sta; + staidx++) { + if (tdls_soc->tdls_conn_info[staidx].sta_id + == INVALID_TDLS_PEER_ID) + continue; + if (tdls_soc->tdls_conn_info[staidx].session_id != + reset_session_id) + continue; + + curr_peer = + tdls_find_all_peer(tdls_soc, + tdls_soc->tdls_conn_info[staidx]. + peer_mac.bytes); + if (!curr_peer) + continue; + + tdls_notice("indicate TDLS teardown (staId %d)", + curr_peer->sta_id); + + /* Indicate teardown to supplicant */ + tdls_indicate_teardown(tdls_vdev, + curr_peer, + TDLS_TEARDOWN_PEER_UNSPEC_REASON); + + tdls_reset_peer(tdls_vdev, curr_peer->peer_mac.bytes); + + if (tdls_soc->tdls_dereg_peer) + tdls_soc->tdls_dereg_peer( + tdls_soc->tdls_peer_context, + wlan_vdev_get_id(vdev), + curr_peer->sta_id); + tdls_decrement_peer_count(tdls_soc); + tdls_soc->tdls_conn_info[staidx].sta_id = INVALID_TDLS_PEER_ID; + tdls_soc->tdls_conn_info[staidx].session_id = 255; + + qdf_mem_zero(&tdls_soc->tdls_conn_info[staidx].peer_mac, + sizeof(struct qdf_mac_addr)); + } + return status; +} + +/** + * tdls_reset_all_peers() - Reset all tdls peers + * @delete_all_peers_ind: Delete all peers indication + * + * This function is called to reset all tdls peers and + * notify upper layers of teardown inidcation + * + * Return: QDF_STATUS + */ +static QDF_STATUS tdls_reset_all_peers( + struct tdls_delete_all_peers_params *delete_all_peers_ind) +{ + QDF_STATUS status; + + if (!delete_all_peers_ind || !delete_all_peers_ind->vdev) { + tdls_err("invalid param"); + return QDF_STATUS_E_INVAL; + } + + status = tdls_process_reset_all_peers(delete_all_peers_ind->vdev); + + if (delete_all_peers_ind->callback) + delete_all_peers_ind->callback(delete_all_peers_ind->vdev); + + qdf_mem_free(delete_all_peers_ind); + return status; +} + QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg) { QDF_STATUS status = QDF_STATUS_SUCCESS; @@ -435,6 +535,9 @@ QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg) case TDLS_CMD_SET_SECOFFCHANOFFSET: tdls_process_set_secoffchanneloffset(msg->bodyptr); break; + case TDLS_DELETE_ALL_PEERS_INDICATION: + tdls_reset_all_peers(msg->bodyptr); + break; default: break; } @@ -1156,6 +1259,37 @@ QDF_STATUS tdls_peers_deleted_notification( return QDF_STATUS_SUCCESS; } +QDF_STATUS tdls_delete_all_peers_indication( + struct tdls_delete_all_peers_params *delete_peers_ind) +{ + struct scheduler_msg msg = {0, }; + struct tdls_delete_all_peers_params *indication; + QDF_STATUS status; + + indication = qdf_mem_malloc(sizeof(*indication)); + if (!indication) { + tdls_err("memory allocation failed !!!"); + return QDF_STATUS_E_NULL_VALUE; + } + + *indication = *delete_peers_ind; + + msg.bodyptr = indication; + msg.callback = tdls_process_cmd; + msg.type = TDLS_DELETE_ALL_PEERS_INDICATION; + + status = scheduler_post_message(QDF_MODULE_ID_TDLS, + QDF_MODULE_ID_TDLS, + QDF_MODULE_ID_OS_IF, &msg); + if (QDF_IS_STATUS_ERROR(status)) { + qdf_mem_free(indication); + tdls_alert("message post failed "); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + /** * tdls_set_mode_in_vdev() - set TDLS mode * @tdls_vdev: tdls vdev object diff --git a/umac/tdls/core/src/wlan_tdls_main.h b/umac/tdls/core/src/wlan_tdls_main.h index 421d6f2bd0d0..fc1230429131 100644 --- a/umac/tdls/core/src/wlan_tdls_main.h +++ b/umac/tdls/core/src/wlan_tdls_main.h @@ -725,4 +725,15 @@ void tdls_scan_serialization_comp_info_cb(struct wlan_objmgr_vdev *vdev, QDF_STATUS tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc, struct tdls_channel_switch_params *param); +/** + * tdls_delete_all_peers_indication() - update tdls status info + * @delete_peers_ind: Delete peers indication params + * + * Notify tdls component to cleanup all peers + * + * Return: QDF_STATUS. + */ + +QDF_STATUS tdls_delete_all_peers_indication( + struct tdls_delete_all_peers_params *delete_peers_ind); #endif diff --git a/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h b/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h index 3aa85b71aeb5..261a1e9af8f3 100644 --- a/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h +++ b/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h @@ -193,6 +193,7 @@ enum tdls_feature_mode { * @TDLS_CMD_SET_OFFCHANNEL: tdls offchannel * @TDLS_CMD_SET_OFFCHANMODE: tdls offchannel mode * @TDLS_CMD_SET_SECOFFCHANOFFSET: tdls secondary offchannel offset + * @TDLS_DELETE_ALL_PEERS_INDICATION: tdls delete all peers indication */ enum tdls_command_type { TDLS_CMD_TX_ACTION = 1, @@ -217,7 +218,8 @@ enum tdls_command_type { TDLS_CMD_ANTENNA_SWITCH, TDLS_CMD_SET_OFFCHANNEL, TDLS_CMD_SET_OFFCHANMODE, - TDLS_CMD_SET_SECOFFCHANOFFSET + TDLS_CMD_SET_SECOFFCHANOFFSET, + TDLS_DELETE_ALL_PEERS_INDICATION }; /** @@ -591,6 +593,11 @@ typedef void (*tdls_sta_notify_callback)(struct wlan_objmgr_vdev *vdev); /* This callback is to release vdev ref for tdls offchan param related msg */ typedef void (*tdls_offchan_parms_callback)(struct wlan_objmgr_vdev *vdev); +/* This callback is to release vdev ref for tdls_delete_all_peers_ + * callback related msg. + */ +typedef void (*tdls_delete_all_peers_callback)(struct wlan_objmgr_vdev *vdev); + /** * struct tdls_start_params - tdls start params * @config: tdls user config @@ -1072,6 +1079,16 @@ struct tdls_sta_notify_params { tdls_sta_notify_callback callback; }; +/** + * struct tdls_delete_all_peers_params - TDLS set mode params + * @vdev: vdev object + * @callback: callback to release vdev ref + */ +struct tdls_delete_all_peers_params { + struct wlan_objmgr_vdev *vdev; + tdls_delete_all_peers_callback callback; +}; + /** * struct tdls_set_mode_params - TDLS set mode params * @vdev: vdev object diff --git a/umac/tdls/dispatcher/inc/wlan_tdls_tgt_api.h b/umac/tdls/dispatcher/inc/wlan_tdls_tgt_api.h index 4b1e99c4a302..14a19006b997 100644 --- a/umac/tdls/dispatcher/inc/wlan_tdls_tgt_api.h +++ b/umac/tdls/dispatcher/inc/wlan_tdls_tgt_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -158,4 +158,16 @@ QDF_STATUS tgt_tdls_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc, void tgt_tdls_peers_deleted_notification(struct wlan_objmgr_psoc *psoc, uint32_t session_id); +/** + * tgt_tdls_delete_all_peers_indication()- Indication to tdls component + * @psoc: soc object + * @session_id: session id + * + * This function called from legacy lim to tdls component to delete tdls peers. + * + * Return: None + */ +void tgt_tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc, + uint32_t session_id); + #endif diff --git a/umac/tdls/dispatcher/src/wlan_tdls_tgt_api.c b/umac/tdls/dispatcher/src/wlan_tdls_tgt_api.c index a6eb77716fc3..cf43a2f64b06 100644 --- a/umac/tdls/dispatcher/src/wlan_tdls_tgt_api.c +++ b/umac/tdls/dispatcher/src/wlan_tdls_tgt_api.c @@ -375,3 +375,50 @@ void tgt_tdls_peers_deleted_notification(struct wlan_objmgr_psoc *psoc, } } +/** + * tgt_tdls_delete_all_peers_ind_callback()- Callback to call from + * TDLS component + * @psoc: soc object + * @session_id: session id + * + * This function release the obj mgr vdev ref + * + * Return: None + */ +static void tgt_tdls_delete_all_peers_ind_callback( + struct wlan_objmgr_vdev *vdev) +{ + if (!vdev) { + tdls_err("vdev is NULL"); + return; + } + + wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID); +} + +void tgt_tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc, + uint32_t session_id) +{ + struct wlan_objmgr_vdev *vdev; + struct tdls_delete_all_peers_params delete_peers_ind; + QDF_STATUS status; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, + session_id, + WLAN_TDLS_SB_ID); + + if (!vdev) { + tdls_err("vdev not exist for the session id %d", + session_id); + return; + } + + delete_peers_ind.vdev = vdev; + delete_peers_ind.callback = tgt_tdls_delete_all_peers_ind_callback; + status = tdls_delete_all_peers_indication(&delete_peers_ind); + if (QDF_IS_STATUS_ERROR(status)) { + tdls_err("tdls_delete_all_peers_indication failed"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID); + } +} +