qcacmn: Add sta connect/disconnect in TDLS UMAC component

Add sta connection and disconnection event related
methods into TDLS component

Change-Id: I1309792cf68df87b1ecf5a7686ac645ac21d1c7c
CRs-Fixed: 2034220
Este commit está contenido en:
Kabilan Kannan
2017-02-28 20:28:54 -08:00
cometido por Sandeep Puligilla
padre 97bc1c725a
commit 3e4752133a
Se han modificado 10 ficheros con 884 adiciones y 15 borrados

Ver fichero

@@ -211,6 +211,10 @@ QDF_STATUS target_if_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
/* Converged UMAC components to register P2P TX-ops */
target_if_p2p_register_tx_ops(tx_ops);
#endif
#ifdef CONVERGED_TDLS_ENABLE
target_if_tdls_register_tx_ops(tx_ops);
#endif
return QDF_STATUS_SUCCESS;
}

Ver fichero

@@ -644,6 +644,22 @@ struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_macaddr_no_state(
struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
wlan_objmgr_ref_dbgid dbg_id);
/**
* wlan_objmgr_get_vdev_by_opmode_from_psoc() - retrieve vdev by opmode
* @psoc: PSOC object
* @opmode: vdev operating mode
* @dbg_id: id of the caller
*
* API to find vdev object pointer by vdev operating mode from psoc
*
* Return: vdev pointer
* NULL on FAILURE
*/
struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc(
struct wlan_objmgr_psoc *psoc,
enum tQDF_ADAPTER_MODE opmode,
wlan_objmgr_ref_dbgid dbg_id);
/**
* wlan_objmgr_get_vdev_by_id_from_psoc() - retrieve vdev by id
* @psoc: PSOC object

Ver fichero

@@ -858,6 +858,40 @@ QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_SUCCESS;
}
struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc(
struct wlan_objmgr_psoc *psoc,
enum tQDF_ADAPTER_MODE opmode,
wlan_objmgr_ref_dbgid dbg_id)
{
struct wlan_objmgr_vdev *vdev;
int vdev_cnt = 0;
/* if PSOC is NULL, return */
if (psoc == NULL)
return NULL;
wlan_psoc_obj_lock(psoc);
/* retrieve vdev pointer from vdev list */
while (vdev_cnt < WLAN_UMAC_PSOC_MAX_VDEVS) {
vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_cnt];
vdev_cnt++;
if (vdev == NULL)
continue;
wlan_vdev_obj_lock(vdev);
if (vdev->vdev_mlme.vdev_opmode == opmode) {
wlan_vdev_obj_unlock(vdev);
if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
QDF_STATUS_SUCCESS)
vdev = NULL;
break;
}
wlan_vdev_obj_unlock(vdev);
}
wlan_psoc_obj_unlock(psoc);
return vdev;
}
struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc(
struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,

Ver fichero

@@ -796,8 +796,8 @@ struct policy_mgr_hdd_cbacks {
* @check_is_tdls_allowed: check if tdls allowed or not
*/
struct policy_mgr_tdls_cbacks {
void (*set_tdls_ct_mode)(struct wlan_objmgr_psoc *psoc);
bool (*check_is_tdls_allowed)(enum tQDF_ADAPTER_MODE device_mode);
void (*tdls_notify_increment_session)(struct wlan_objmgr_psoc *psoc);
void (*tdls_notify_decrement_session)(struct wlan_objmgr_psoc *psoc);
};
/**

Ver fichero

@@ -1114,9 +1114,10 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc,
qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
}
/* set tdls connection tracker state */
if (pm_ctx->tdls_cbacks.set_tdls_ct_mode)
pm_ctx->tdls_cbacks.set_tdls_ct_mode(psoc);
/* Notify tdls */
if (pm_ctx->tdls_cbacks.tdls_notify_increment_session)
pm_ctx->tdls_cbacks.tdls_notify_increment_session(psoc);
policy_mgr_dump_current_concurrency(psoc);
qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
@@ -1152,9 +1153,9 @@ void policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc,
policy_mgr_decr_connection_count(psoc, session_id);
/* set tdls connection tracker state */
if (pm_ctx->tdls_cbacks.set_tdls_ct_mode)
pm_ctx->tdls_cbacks.set_tdls_ct_mode(psoc);
/* Notify tdls */
if (pm_ctx->tdls_cbacks.tdls_notify_decrement_session)
pm_ctx->tdls_cbacks.tdls_notify_decrement_session(psoc);
policy_mgr_dump_current_concurrency(psoc);
}

Ver fichero

@@ -605,10 +605,10 @@ QDF_STATUS policy_mgr_register_tdls_cb(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_E_FAILURE;
}
pm_ctx->tdls_cbacks.check_is_tdls_allowed =
tdls_cbacks->check_is_tdls_allowed;
pm_ctx->tdls_cbacks.set_tdls_ct_mode =
tdls_cbacks->set_tdls_ct_mode;
pm_ctx->tdls_cbacks.tdls_notify_increment_session =
tdls_cbacks->tdls_notify_increment_session;
pm_ctx->tdls_cbacks.tdls_notify_decrement_session =
tdls_cbacks->tdls_notify_decrement_session;
return QDF_STATUS_SUCCESS;
}

Ver fichero

@@ -27,6 +27,10 @@
#include "wlan_tdls_peer.h"
#include "wlan_tdls_ct.h"
#include "wlan_tdls_mgmt.h"
#include "wlan_tdls_tgt_api.h"
#include "wlan_policy_mgr_public_struct.h"
#include "wlan_policy_mgr_api.h"
QDF_STATUS tdls_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc,
void *arg_list)
@@ -387,3 +391,665 @@ QDF_STATUS tdls_get_vdev_objects(struct wlan_objmgr_vdev *vdev,
return QDF_STATUS_SUCCESS;
}
/**
* tdls_state_param_setting_dump() - print tdls state & parameters to send to fw
* @info: tdls setting to be sent to fw
*
* Return: void
*/
static void tdls_state_param_setting_dump(struct tdls_info *info)
{
if (!info)
return;
tdls_debug("Setting tdls state and param in fw: vdev_id: %d, tdls_state: %d, notification_interval_ms: %d, tx_discovery_threshold: %d, tx_teardown_threshold: %d, rssi_teardown_threshold: %d, rssi_delta: %d, tdls_options: 0x%x, peer_traffic_ind_window: %d, peer_traffic_response_timeout: %d, puapsd_mask: 0x%x, puapsd_inactivity_time: %d, puapsd_rx_frame_threshold: %d, teardown_notification_ms: %d, tdls_peer_kickout_threshold: %d",
info->vdev_id,
info->tdls_state,
info->notification_interval_ms,
info->tx_discovery_threshold,
info->tx_teardown_threshold,
info->rssi_teardown_threshold,
info->rssi_delta,
info->tdls_options,
info->peer_traffic_ind_window,
info->peer_traffic_response_timeout,
info->puapsd_mask,
info->puapsd_inactivity_time,
info->puapsd_rx_frame_threshold,
info->teardown_notification_ms,
info->tdls_peer_kickout_threshold);
}
/**
* tdls_update_fw_tdls_state() - update tdls status info
* @tdls_soc_obj: TDLS soc object
* @tdls_info_to_fw: TDLS state info to update in f/w.
*
* send message to WMA to set TDLS state in f/w
*
* Return: QDF_STATUS.
*/
static
QDF_STATUS tdls_update_fw_tdls_state(struct tdls_soc_priv_obj *tdls_soc_obj,
struct tdls_info *tdls_info_to_fw)
{
QDF_STATUS status;
/* wmi_unified_update_fw_tdls_state_cmd() will be called directly */
status = tgt_tdls_set_fw_state(tdls_soc_obj->soc, tdls_info_to_fw);
if (!QDF_IS_STATUS_SUCCESS(status))
status = QDF_STATUS_E_FAILURE;
return status;
}
bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
{
struct tdls_vdev_priv_obj *tdls_vdev_obj;
struct tdls_soc_priv_obj *tdls_soc_obj;
bool state = false;
if (QDF_STATUS_SUCCESS != wlan_objmgr_vdev_try_get_ref(vdev,
WLAN_TDLS_NB_ID))
return state;
if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev, &tdls_vdev_obj,
&tdls_soc_obj)) {
wlan_objmgr_vdev_release_ref(vdev,
WLAN_TDLS_NB_ID);
return state;
}
if (policy_mgr_get_connection_count(tdls_soc_obj->soc) == 1)
state = true;
else
tdls_warn("Concurrent sessions are running or TDLS disabled");
/* If any concurrency is detected */
/* print session information */
wlan_objmgr_vdev_release_ref(vdev,
WLAN_TDLS_NB_ID);
return state;
}
/**
* cds_set_tdls_ct_mode() - Set the tdls connection tracker mode
* @hdd_ctx: hdd context
*
* This routine is called to set the tdls connection tracker operation status
*
* Return: NONE
*/
void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc)
{
bool state = false;
struct tdls_soc_priv_obj *tdls_soc_obj;
tdls_soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (NULL == tdls_soc_obj)
return;
/* If any concurrency is detected, skip tdls pkt tracker */
if (policy_mgr_get_connection_count(psoc) > 1) {
state = false;
goto set_state;
}
if (TDLS_SUPPORT_DISABLED == tdls_soc_obj->tdls_current_mode ||
TDLS_SUPPORT_SUSPENDED == tdls_soc_obj->tdls_current_mode ||
!TDLS_IS_IMPLICIT_TRIG_ENABLED(
tdls_soc_obj->tdls_configs.tdls_feature_flags)) {
state = false;
goto set_state;
} else if (policy_mgr_mode_specific_connection_count(psoc,
PM_STA_MODE,
NULL) == 1) {
state = true;
} else if (policy_mgr_mode_specific_connection_count(psoc,
PM_P2P_CLIENT_MODE,
NULL) == 1){
state = true;
} else {
state = false;
goto set_state;
}
/* In case of TDLS external control, peer should be added
* by the user space to start connection tracker.
*/
if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(
tdls_soc_obj->tdls_configs.tdls_feature_flags)) {
if (tdls_soc_obj->tdls_external_peer_count)
state = true;
else
state = false;
}
set_state:
tdls_soc_obj->enable_tdls_connection_tracker = state;
tdls_notice("enable_tdls_connection_tracker %d",
tdls_soc_obj->enable_tdls_connection_tracker);
}
QDF_STATUS
tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
{
if (!psoc) {
tdls_err("psoc: %p", psoc);
return QDF_STATUS_E_NULL_VALUE;
}
tdls_debug("enter ");
tdls_set_ct_mode(psoc);
tdls_debug("exit ");
return QDF_STATUS_SUCCESS;
}
/**
* tdls_get_vdev() - Get tdls specific vdev object manager
* @psoc: wlan psoc object manager
* @dbg_id: debug id
*
* If TDLS possible, return the corresponding vdev
* to enable TDLS in the system.
*
* Return: vdev manager pointer or NULL.
*/
struct wlan_objmgr_vdev *tdls_get_vdev(struct wlan_objmgr_psoc *psoc,
wlan_objmgr_ref_dbgid dbg_id)
{
if (policy_mgr_get_connection_count(psoc) > 1)
return NULL;
if (policy_mgr_mode_specific_connection_count(psoc,
PM_STA_MODE,
NULL) == 1)
return wlan_objmgr_get_vdev_by_opmode_from_psoc(psoc,
QDF_STA_MODE,
dbg_id);
if (policy_mgr_mode_specific_connection_count(psoc,
PM_P2P_CLIENT_MODE,
NULL) == 1)
return wlan_objmgr_get_vdev_by_opmode_from_psoc(psoc,
QDF_P2P_CLIENT_MODE,
dbg_id);
return NULL;
}
/**
* tdls_process_session_update() - update session count information
* @psoc: soc object
* @notification: TDLS os if notification
*
* update the session information in connection tracker
*
* Return: None
*/
static void tdls_process_session_update(struct wlan_objmgr_psoc *psoc,
enum tdls_command_type cmd_type)
{
struct scheduler_msg msg = {0};
QDF_STATUS status;
msg.bodyptr = psoc;
msg.callback = tdls_process_cmd;
msg.type = (uint16_t)cmd_type;
status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg);
if (QDF_IS_STATUS_ERROR(status))
tdls_alert("message post failed ");
}
void tdls_notify_increment_session(struct wlan_objmgr_psoc *psoc)
{
tdls_process_session_update(psoc, TDLS_CMD_SESSION_INCREMENT);
}
void tdls_notify_decrement_session(struct wlan_objmgr_psoc *psoc)
{
tdls_process_session_update(psoc, TDLS_CMD_SESSION_DECREMENT);
}
/**
* tdls_send_update_to_fw - update tdls status info
* @tdls_vdev_obj: tdls vdev private object.
* @tdls_prohibited: indicates whether tdls is prohibited.
* @tdls_chan_swit_prohibited: indicates whether tdls channel switch
* is prohibited.
* @sta_connect_event: indicate sta connect or disconnect event
* @session_id: session id
*
* Normally an AP does not influence TDLS connection between STAs
* associated to it. But AP may set bits for TDLS Prohibited or
* TDLS Channel Switch Prohibited in Extended Capability IE in
* Assoc/Re-assoc response to STA. So after STA is connected to
* an AP, call this function to update TDLS status as per those
* bits set in Ext Cap IE in received Assoc/Re-assoc response
* from AP.
*
* Return: None.
*/
static void tdls_send_update_to_fw(struct tdls_vdev_priv_obj *tdls_vdev_obj,
struct tdls_soc_priv_obj *tdls_soc_obj,
bool tdls_prohibited,
bool tdls_chan_swit_prohibited,
bool sta_connect_event,
uint8_t session_id)
{
struct tdls_info *tdls_info_to_fw;
struct tdls_config_params *threshold_params;
uint32_t tdls_feature_flags;
QDF_STATUS status;
/* If TDLS support is disabled then no need to update target */
if (tdls_soc_obj->tdls_current_mode <= TDLS_SUPPORT_SUSPENDED) {
tdls_err("TDLS not enabled or suspended");
return;
}
if (tdls_soc_obj->set_state_info.set_state_cnt == 0 &&
!sta_connect_event) {
return;
}
tdls_feature_flags = tdls_soc_obj->tdls_configs.tdls_feature_flags;
/* If AP or caller indicated TDLS Prohibited then disable tdls mode */
if (tdls_prohibited) {
tdls_soc_obj->tdls_current_mode = TDLS_SUPPORT_DISABLED;
} else {
tdls_debug("TDLS feature flags from ini %d ",
tdls_feature_flags);
if (!TDLS_IS_IMPLICIT_TRIG_ENABLED(tdls_feature_flags))
tdls_soc_obj->tdls_current_mode =
TDLS_SUPPORT_EXP_TRIG_ONLY;
else if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(tdls_feature_flags))
tdls_soc_obj->tdls_current_mode =
TDLS_SUPPORT_EXT_CONTROL;
else
tdls_soc_obj->tdls_current_mode =
TDLS_SUPPORT_IMP_MODE;
}
tdls_info_to_fw = qdf_mem_malloc(sizeof(struct tdls_info));
if (!tdls_info_to_fw) {
tdls_err("memory allocation failed for tdlsParams");
QDF_ASSERT(0);
return;
}
threshold_params = &tdls_vdev_obj->threshold_config;
tdls_info_to_fw->notification_interval_ms =
threshold_params->tx_period_t;
tdls_info_to_fw->tx_discovery_threshold =
threshold_params->tx_packet_n;
tdls_info_to_fw->tx_teardown_threshold =
threshold_params->idle_packet_n;
tdls_info_to_fw->rssi_teardown_threshold =
threshold_params->rssi_teardown_threshold;
tdls_info_to_fw->rssi_delta = threshold_params->rssi_delta;
if (tdls_soc_obj->set_state_info.set_state_cnt == 1 &&
sta_connect_event) {
tdls_warn("Concurrency not allowed in TDLS! set state cnt %d",
tdls_soc_obj->set_state_info.set_state_cnt);
/* disable off channel and teardown links */
/* Go through the peer list and delete them */
tdls_soc_obj->tdls_current_mode = TDLS_SUPPORT_DISABLED;
tdls_info_to_fw->vdev_id = tdls_soc_obj->set_state_info.vdev_id;
} else {
tdls_info_to_fw->vdev_id = session_id;
}
tdls_info_to_fw->tdls_state = tdls_soc_obj->tdls_current_mode;
tdls_info_to_fw->tdls_options = 0;
/* Do not enable TDLS offchannel, if AP prohibited TDLS
* channel switch
*/
if (TDLS_IS_OFF_CHANNEL_ENABLED(tdls_feature_flags) &&
(!tdls_chan_swit_prohibited))
tdls_info_to_fw->tdls_options = ENA_TDLS_OFFCHAN;
if (TDLS_IS_BUFFER_STA_ENABLED(tdls_feature_flags))
tdls_info_to_fw->tdls_options |= ENA_TDLS_BUFFER_STA;
if (TDLS_IS_SLEEP_STA_ENABLED(tdls_feature_flags))
tdls_info_to_fw->tdls_options |= ENA_TDLS_SLEEP_STA;
tdls_info_to_fw->peer_traffic_ind_window =
tdls_soc_obj->tdls_configs.tdls_uapsd_pti_window;
tdls_info_to_fw->peer_traffic_response_timeout =
tdls_soc_obj->tdls_configs.tdls_uapsd_ptr_timeout;
tdls_info_to_fw->puapsd_mask =
tdls_soc_obj->tdls_configs.tdls_uapsd_mask;
tdls_info_to_fw->puapsd_inactivity_time =
tdls_soc_obj->tdls_configs.tdls_uapsd_inactivity_time;
tdls_info_to_fw->puapsd_rx_frame_threshold =
tdls_soc_obj->tdls_configs.tdls_rx_pkt_threshold;
tdls_info_to_fw->teardown_notification_ms =
tdls_soc_obj->tdls_configs.tdls_idle_timeout;
tdls_info_to_fw->tdls_peer_kickout_threshold =
tdls_soc_obj->tdls_configs.tdls_peer_kickout_threshold;
tdls_state_param_setting_dump(tdls_info_to_fw);
status = tdls_update_fw_tdls_state(tdls_soc_obj, tdls_info_to_fw);
if (QDF_STATUS_SUCCESS != status) {
qdf_mem_free(tdls_info_to_fw);
goto done;
}
if (sta_connect_event) {
tdls_soc_obj->set_state_info.set_state_cnt++;
tdls_soc_obj->set_state_info.vdev_id = session_id;
} else {
tdls_soc_obj->set_state_info.set_state_cnt--;
}
tdls_debug("TDLS Set state cnt %d",
tdls_soc_obj->set_state_info.set_state_cnt);
if (tdls_soc_obj->set_state_info.set_state_cnt == 1)
/* register callbacks with tx/rx mgmt */
tdls_mgmt_rx_ops(tdls_soc_obj->soc, true);
else
/* deregister callbacks with tx/rx mgmt */
tdls_mgmt_rx_ops(tdls_soc_obj->soc, false);
done:
tdls_process_session_update(tdls_soc_obj->soc,
TDLS_CMD_SESSION_INCREMENT);
return;
}
static QDF_STATUS
tdls_process_sta_connect(struct tdls_sta_notify_params *notify)
{
struct tdls_vdev_priv_obj *tdls_vdev_obj;
struct tdls_soc_priv_obj *tdls_soc_obj;
if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(notify->vdev,
&tdls_vdev_obj,
&tdls_soc_obj))
return QDF_STATUS_E_INVAL;
tdls_debug("Check and update TDLS state");
/* Association event */
if (!tdls_soc_obj->tdls_disable_in_progress) {
tdls_send_update_to_fw(tdls_vdev_obj,
tdls_soc_obj,
notify->tdls_prohibited,
notify->tdls_chan_swit_prohibited,
true,
notify->session_id);
}
/* check and set the connection tracker */
tdls_set_ct_mode(tdls_soc_obj->soc);
if (tdls_soc_obj->enable_tdls_connection_tracker)
tdls_implicit_enable(tdls_vdev_obj);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify)
{
QDF_STATUS status;
if (!notify || !notify->vdev)
return QDF_STATUS_E_INVAL;
if (QDF_STATUS_SUCCESS != wlan_objmgr_vdev_try_get_ref(notify->vdev,
WLAN_TDLS_NB_ID))
return QDF_STATUS_E_INVAL;
status = tdls_process_sta_connect(notify);
wlan_objmgr_vdev_release_ref(notify->vdev,
WLAN_TDLS_NB_ID);
qdf_mem_free(notify);
return status;
}
static QDF_STATUS
tdls_process_sta_disconnect(struct tdls_sta_notify_params *notify)
{
struct tdls_vdev_priv_obj *tdls_vdev_obj;
struct tdls_vdev_priv_obj *curr_tdls_vdev;
struct tdls_soc_priv_obj *tdls_soc_obj;
struct tdls_soc_priv_obj *curr_tdls_soc;
struct wlan_objmgr_vdev *temp_vdev = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(notify->vdev,
&tdls_vdev_obj,
&tdls_soc_obj))
return QDF_STATUS_E_INVAL;
tdls_debug("Check and update TDLS state");
curr_tdls_vdev = tdls_vdev_obj;
curr_tdls_soc = tdls_soc_obj;
/* Disassociation event */
if (!tdls_soc_obj->tdls_disable_in_progress)
tdls_send_update_to_fw(tdls_vdev_obj, tdls_soc_obj, false,
false, false, notify->session_id);
/* If concurrency is not marked, then we have to
* check, whether TDLS could be enabled in the
* system after this disassoc event.
*/
if (!notify->lfr_roam && !tdls_soc_obj->tdls_disable_in_progress) {
temp_vdev = tdls_get_vdev(tdls_soc_obj->soc, WLAN_TDLS_NB_ID);
if (NULL != temp_vdev) {
status = tdls_get_vdev_objects(temp_vdev,
&tdls_vdev_obj,
&tdls_soc_obj);
if (QDF_STATUS_SUCCESS == status) {
tdls_send_update_to_fw(tdls_vdev_obj,
tdls_soc_obj,
false,
false,
true,
notify->session_id);
curr_tdls_vdev = tdls_vdev_obj;
curr_tdls_soc = tdls_soc_obj;
}
}
}
/* Check and set the connection tracker and implicit timers */
tdls_set_ct_mode(curr_tdls_soc->soc);
if (curr_tdls_soc->enable_tdls_connection_tracker)
tdls_implicit_enable(curr_tdls_vdev);
else
tdls_implicit_disable(curr_tdls_vdev);
/* release the vdev ref , if temp vdev was acquired */
if (temp_vdev)
wlan_objmgr_vdev_release_ref(temp_vdev,
WLAN_TDLS_NB_ID);
return status;
}
QDF_STATUS tdls_notify_sta_disconnect(struct tdls_sta_notify_params *notify)
{
QDF_STATUS status;
if (!notify || !notify->vdev)
return QDF_STATUS_E_INVAL;
if (QDF_STATUS_SUCCESS != wlan_objmgr_vdev_try_get_ref(notify->vdev,
WLAN_TDLS_NB_ID))
return QDF_STATUS_E_INVAL;
status = tdls_process_sta_disconnect(notify);
wlan_objmgr_vdev_release_ref(notify->vdev,
WLAN_TDLS_NB_ID);
qdf_mem_free(notify);
return status;
}
/**
* tdls_set_mode_in_vdev() - set TDLS mode
* @tdls_vdev: tdls vdev object
* @tdls_soc: tdls soc object
* @tdls_mode: TDLS mode
* @source: TDLS disable source enum values
*
* Return: Void
*/
static void tdls_set_mode_in_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
struct tdls_soc_priv_obj *tdls_soc,
enum tdls_feature_mode tdls_mode,
enum tdls_disable_sources source)
{
if (!tdls_vdev)
return;
tdls_debug("enter tdls mode is %d", tdls_mode);
if (TDLS_SUPPORT_IMP_MODE == tdls_mode ||
TDLS_SUPPORT_EXT_CONTROL == tdls_mode) {
clear_bit((unsigned long)source,
&tdls_soc->tdls_source_bitmap);
/*
* Check if any TDLS source bit is set and if
* bitmap is not zero then we should not
* enable TDLS
*/
if (tdls_soc->tdls_source_bitmap) {
tdls_notice("Don't enable TDLS, source bitmap: %lu",
tdls_soc->tdls_source_bitmap);
return;
}
tdls_implicit_enable(tdls_vdev);
/* tdls implicit mode is enabled, so
* enable the connection tracker
*/
tdls_soc->enable_tdls_connection_tracker =
true;
} else if (TDLS_SUPPORT_DISABLED == tdls_mode) {
set_bit((unsigned long)source,
&tdls_soc->tdls_source_bitmap);
tdls_implicit_disable(tdls_vdev);
/* If tdls implicit mode is disabled, then
* stop the connection tracker.
*/
tdls_soc->enable_tdls_connection_tracker =
false;
} else if (TDLS_SUPPORT_EXP_TRIG_ONLY ==
tdls_mode) {
clear_bit((unsigned long)source,
&tdls_soc->tdls_source_bitmap);
tdls_implicit_disable(tdls_vdev);
/* If tdls implicit mode is disabled, then
* stop the connection tracker.
*/
tdls_soc->enable_tdls_connection_tracker =
false;
/*
* Check if any TDLS source bit is set and if
* bitmap is not zero then we should not
* enable TDLS
*/
if (tdls_soc->tdls_source_bitmap)
return;
}
tdls_debug("exit ");
}
/**
* tdls_set_current_mode() - set TDLS mode
* @tdls_soc: tdls soc object
* @tdls_mode: TDLS mode
* @update_last: indicate to record the last tdls mode
* @source: TDLS disable source enum values
*
* Return: Void
*/
static void tdls_set_current_mode(struct tdls_soc_priv_obj *tdls_soc,
enum tdls_feature_mode tdls_mode,
bool update_last,
enum tdls_disable_sources source)
{
struct wlan_objmgr_vdev *vdev;
struct tdls_vdev_priv_obj *tdls_vdev;
if (!tdls_soc)
return;
tdls_debug("mode %d", (int)tdls_mode);
if (update_last)
tdls_soc->tdls_last_mode = tdls_mode;
if (tdls_soc->tdls_current_mode == tdls_mode) {
tdls_debug("already in mode %d", tdls_mode);
switch (tdls_mode) {
/* TDLS is already enabled hence clear source mask, return */
case TDLS_SUPPORT_IMP_MODE:
case TDLS_SUPPORT_EXP_TRIG_ONLY:
case TDLS_SUPPORT_EXT_CONTROL:
clear_bit((unsigned long)source,
&tdls_soc->tdls_source_bitmap);
tdls_debug("clear source mask:%d", source);
return;
/* TDLS is already disabled hence set source mask, return */
case TDLS_SUPPORT_DISABLED:
set_bit((unsigned long)source,
&tdls_soc->tdls_source_bitmap);
tdls_debug("set source mask:%d", source);
return;
default:
return;
}
}
/* get sta vdev */
vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc(tdls_soc->soc,
QDF_STA_MODE,
WLAN_TDLS_NB_ID);
if (NULL != vdev) {
tdls_debug("set mode in tdls vdev ");
tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
if (!tdls_vdev)
tdls_set_mode_in_vdev(tdls_vdev, tdls_soc,
tdls_mode, source);
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
}
/* get p2p client vdev */
vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc(tdls_soc->soc,
QDF_P2P_CLIENT_MODE,
WLAN_TDLS_NB_ID);
if (NULL != vdev) {
tdls_debug("set mode in tdls vdev ");
tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
if (!tdls_vdev)
tdls_set_mode_in_vdev(tdls_vdev, tdls_soc,
tdls_mode, source);
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
}
if (!update_last)
tdls_soc->tdls_last_mode = tdls_soc->tdls_current_mode;
tdls_soc->tdls_current_mode = tdls_mode;
}

Ver fichero

@@ -145,7 +145,8 @@ struct tdls_set_state_info {
* struct tdls_psoc_priv_ctx - tdls context
* @soc: objmgr psoc
* @tdls_current_mode: current tdls mode
* @tdls_user_config_mode: user configure tdls mode
* @tdls_last_mode: last tdls mode
* @tdls_source_bitmap: bit map to set/reset TDLS by different sources
* @tdls_conn_info: this tdls_conn_info can be removed and we can use peer type
* of peer object to get the active tdls peers
* @tdls_configs: tdls user configure
@@ -180,7 +181,8 @@ struct tdls_set_state_info {
struct tdls_soc_priv_obj {
struct wlan_objmgr_psoc *soc;
enum tdls_feature_mode tdls_current_mode;
enum tdls_feature_mode tdls_user_config_mode;
enum tdls_feature_mode tdls_last_mode;
unsigned long tdls_source_bitmap;
struct tdls_conn_info tdls_conn_info[WLAN_TDLS_STA_MAX_NUM];
struct tdls_user_config tdls_configs;
uint16_t max_num_tdls_sta;
@@ -192,6 +194,7 @@ struct tdls_soc_priv_obj {
uint8_t tdls_external_peer_count;
bool tdls_nss_switch_in_progress;
bool tdls_nss_teardown_complete;
bool tdls_disable_in_progress;
enum tdls_nss_transition_state tdls_nss_transition_mode;
int32_t tdls_teardown_peers_cnt;
struct tdls_set_state_info set_state_info;
@@ -320,6 +323,25 @@ struct tdls_peer {
struct tdls_peer_mlme_info *tdls_info;
};
/**
* struct tdls_os_if_event - TDLS os event info
* @type: type of event
* @info: pointer to event information
*/
struct tdls_os_if_event {
uint32_t type;
void *info;
};
/**
* enum tdls_os_if_notification - TDLS notification from OS IF
* @TDLS_NOTIFY_STA_SESSION_INCREMENT: sta session count incremented
* @TDLS_NOTIFY_STA_SESSION_DECREMENT: sta session count decremented
*/
enum tdls_os_if_notification {
TDLS_NOTIFY_STA_SESSION_INCREMENT,
TDLS_NOTIFY_STA_SESSION_DECREMENT
};
/**
* wlan_vdev_get_tdls_soc_obj - private API to get tdls soc object from vdev
* @vdev: vdev object
@@ -501,4 +523,103 @@ QDF_STATUS tdls_get_vdev_objects(struct wlan_objmgr_vdev *vdev,
struct tdls_vdev_priv_obj **tdls_vdev_obj,
struct tdls_soc_priv_obj **tdls_soc_obj);
/**
* cds_set_tdls_ct_mode() - Set the tdls connection tracker mode
* @hdd_ctx: hdd context
*
* This routine is called to set the tdls connection tracker operation status
*
* Return: NONE
*/
void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc);
/**
* tdls_notify_sta_connect() - Update tdls state for every
* connect event.
* @vdev: vdev object manager
* @tdls_prohibited: flag to tell whether tdls prohibited in this bss
* @tdls_chan_swit_prohibited: flag to tell whether tdls channel switch
* prohibited in this bss
* @session_id: session id
*
* After every connect event in the system, check whether TDLS
* can be enabled in the system. If TDLS can be enabled, update the
* TDLS state as needed.
*
* Return: None
*/
void tdls_notify_sta_connect(struct wlan_objmgr_vdev *vdev,
bool tdls_prohibited,
bool tdls_chan_swit_prohibited,
uint8_t session_id);
/**
* tdls_notify_sta_disconnect() - Update tdls state for every
* disconnect event.
* @vdev: vdev object manager
* @lfr_roam: roaming case
* @session_id: session id
*
* After every disconnect event in the system, check whether TDLS
* can be disabled/enabled in the system and update the
* TDLS state as needed.
*
* Return: None
*/
void tdls_notify_sta_disconnect(struct wlan_objmgr_vdev *vdev,
bool lfr_roam,
uint8_t session_id);
/**
* tdls_notify_decrement_session() - Notify the session decrement
* @psoc: psoc object manager
*
* Policy manager notify TDLS about session decrement
*
* Return: None
*/
void tdls_notify_decrement_session(struct wlan_objmgr_psoc *psoc);
/**
* tdls_notify_increment_session() - Notify the session increment
* @psoc: psoc object manager
*
* Policy manager notify TDLS about session increment
*
* Return: None
*/
void tdls_notify_increment_session(struct wlan_objmgr_psoc *psoc);
/**
* tdls_check_is_tdls_allowed() - check is tdls allowed or not
* @vdev: vdev object
*
* Function determines the whether TDLS allowed in the system
*
* Return: true or false
*/
bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev);
/**
* tdls_get_vdev() - Get tdls specific vdev object manager
* @psoc: wlan psoc object manager
* @dbg_id: debug id
*
* If TDLS possible, return the corresponding vdev
* to enable TDLS in the system.
*
* Return: vdev manager pointer or NULL.
*/
struct wlan_objmgr_vdev *tdls_get_vdev(struct wlan_objmgr_psoc *psoc,
wlan_objmgr_ref_dbgid dbg_id);
/**
* tdls_process_policy_mgr_notification() - process policy manager notification
* @psoc: soc object manager
*
* Return: QDF_STATUS
*/
QDF_STATUS
tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc);
#endif

Ver fichero

@@ -286,6 +286,22 @@ enum tdls_event_reason {
TDLS_SCAN_COMPLETED,
};
/**
* enum tdls_disable_sources - TDLS disable sources
* @TDLS_SET_MODE_SOURCE_USER: disable from user
* @TDLS_SET_MODE_SOURCE_SCAN: disable during scan
* @TDLS_SET_MODE_SOURCE_OFFCHANNEL: disable during offchannel
* @TDLS_SET_MODE_SOURCE_BTC: disable during bluetooth
* @TDLS_SET_MODE_SOURCE_P2P: disable during p2p
*/
enum tdls_disable_sources {
TDLS_SET_MODE_SOURCE_USER = 0,
TDLS_SET_MODE_SOURCE_SCAN,
TDLS_SET_MODE_SOURCE_OFFCHANNEL,
TDLS_SET_MODE_SOURCE_BTC,
TDLS_SET_MODE_SOURCE_P2P,
};
/**
* struct tdls_osif_indication - tdls indication to os if layer
* @vdev: vdev object

Ver fichero

@@ -28,6 +28,7 @@
#include "../../core/src/wlan_tdls_cmds_process.h"
#include <wlan_objmgr_global_obj.h>
#include <wlan_objmgr_cmn.h>
#include "wlan_policy_mgr_api.h"
QDF_STATUS ucfg_tdls_init(void)
{
@@ -122,7 +123,6 @@ static QDF_STATUS tdls_global_init(struct tdls_soc_priv_obj *soc_obj)
soc_obj->tdls_teardown_peers_cnt = 0;
soc_obj->tdls_nss_teardown_complete = false;
soc_obj->tdls_nss_transition_mode = TDLS_NSS_TRANSITION_S_UNKNOWN;
soc_obj->tdls_user_config_mode = TDLS_SUPPORT_DISABLED;
feature = soc_obj->tdls_configs.tdls_feature_flags;
if (TDLS_IS_BUFFER_STA_ENABLED(feature) ||
@@ -178,6 +178,7 @@ QDF_STATUS ucfg_tdls_update_config(struct wlan_objmgr_psoc *psoc,
{
struct tdls_soc_priv_obj *soc_obj;
uint32_t tdls_feature_flags;
struct policy_mgr_tdls_cbacks tdls_pm_call_backs;
tdls_notice("tdls update config ");
if (!psoc || !req) {
@@ -208,6 +209,16 @@ QDF_STATUS ucfg_tdls_update_config(struct wlan_objmgr_psoc *psoc,
soc_obj->tdls_add_sta_req = req->tdls_add_sta_req;
soc_obj->tdls_del_sta_req = req->tdls_del_sta_req;
soc_obj->tdls_update_peer_state = req->tdls_update_peer_state;
tdls_pm_call_backs.tdls_notify_increment_session =
tdls_notify_increment_session;
tdls_pm_call_backs.tdls_notify_decrement_session =
tdls_notify_decrement_session;
if (QDF_STATUS_SUCCESS != policy_mgr_register_tdls_cb(
psoc, &tdls_pm_call_backs)) {
tdls_err("policy manager callback registration failed ");
return QDF_STATUS_E_FAILURE;
}
/* Update TDLS user config */
qdf_mem_copy(&soc_obj->tdls_configs, &req->config, sizeof(req->config));