blob: d90f44f641e756e7a505587e8d2a5b0a5bc6018a [file] [log] [blame]
/*
* Copyright (c) 2018-2019 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: Implements VDEV MLME public APIs
*/
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_mlme_dbg.h>
#include "include/wlan_vdev_mlme.h"
#include "../../core/src/vdev_mlme_sm.h"
#include <wlan_vdev_mlme_api.h>
#include <qdf_module.h>
struct vdev_mlme_obj *wlan_vdev_mlme_get_cmpt_obj(struct wlan_objmgr_vdev *vdev)
{
struct vdev_mlme_obj *vdev_mlme;
if (!vdev) {
mlme_err("vdev is NULL");
return NULL;
}
vdev_mlme = wlan_objmgr_vdev_get_comp_private_obj(vdev,
WLAN_UMAC_COMP_MLME);
if (!vdev_mlme) {
mlme_err(" MLME component object is NULL");
return NULL;
}
return vdev_mlme;
}
qdf_export_symbol(wlan_vdev_mlme_get_cmpt_obj);
void wlan_vdev_mlme_set_ext_hdl(struct wlan_objmgr_vdev *vdev, void *ext_hdl)
{
struct vdev_mlme_obj *vdev_mlme;
if (!ext_hdl) {
mlme_err("Invalid input");
return;
}
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (vdev_mlme)
vdev_mlme->ext_vdev_ptr = ext_hdl;
}
qdf_export_symbol(wlan_vdev_mlme_set_ext_hdl);
void *wlan_vdev_mlme_get_ext_hdl(struct wlan_objmgr_vdev *vdev)
{
struct vdev_mlme_obj *vdev_mlme;
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (vdev_mlme)
return vdev_mlme->ext_vdev_ptr;
return NULL;
}
qdf_export_symbol(wlan_vdev_mlme_get_ext_hdl);
QDF_STATUS wlan_vdev_mlme_sm_deliver_evt(struct wlan_objmgr_vdev *vdev,
enum wlan_vdev_sm_evt event,
uint16_t event_data_len,
void *event_data)
{
struct vdev_mlme_obj *vdev_mlme;
QDF_STATUS status;
enum wlan_vdev_state state_entry, state_exit;
enum wlan_vdev_state substate_entry, substate_exit;
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (!vdev_mlme) {
mlme_err("vdev component object is NULL");
return QDF_STATUS_E_FAILURE;
}
mlme_vdev_sm_spin_lock(vdev_mlme);
/* store entry state and sub state for prints */
state_entry = wlan_vdev_mlme_get_state(vdev);
substate_entry = wlan_vdev_mlme_get_substate(vdev);
mlme_vdev_sm_print_state_event(vdev_mlme, event);
status = mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len,
event_data);
/* Take exit state, exit substate for prints */
state_exit = wlan_vdev_mlme_get_state(vdev);
substate_exit = wlan_vdev_mlme_get_substate(vdev);
/* If no state and substate change, don't print */
if (!((state_entry == state_exit) && (substate_entry == substate_exit)))
mlme_vdev_sm_print_state(vdev_mlme);
mlme_vdev_sm_spin_unlock(vdev_mlme);
return status;
}
qdf_export_symbol(wlan_vdev_mlme_sm_deliver_evt);
QDF_STATUS wlan_vdev_mlme_sm_deliver_evt_sync(struct wlan_objmgr_vdev *vdev,
enum wlan_vdev_sm_evt event,
uint16_t event_data_len,
void *event_data)
{
struct vdev_mlme_obj *vdev_mlme;
QDF_STATUS status;
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (!vdev_mlme) {
mlme_err("vdev component object is NULL");
return QDF_STATUS_E_FAILURE;
}
status = mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len,
event_data);
return status;
}
qdf_export_symbol(wlan_vdev_mlme_sm_deliver_evt_sync);
#ifdef SM_ENG_HIST_ENABLE
void wlan_vdev_mlme_sm_history_print(struct wlan_objmgr_vdev *vdev)
{
struct vdev_mlme_obj *vdev_mlme;
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (!vdev_mlme) {
mlme_err("vdev component object is NULL");
return;
}
mlme_vdev_sm_history_print(vdev_mlme);
}
#endif
QDF_STATUS wlan_vdev_allow_connect_n_tx(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;
enum wlan_vdev_state substate;
state = wlan_vdev_mlme_get_state(vdev);
substate = wlan_vdev_mlme_get_substate(vdev);
if ((state == WLAN_VDEV_S_UP) ||
((state == WLAN_VDEV_S_SUSPEND) &&
(substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART)))
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
QDF_STATUS wlan_vdev_mlme_is_active(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;
state = wlan_vdev_mlme_get_state(vdev);
if ((state == WLAN_VDEV_S_UP) || (state == WLAN_VDEV_S_DFS_CAC_WAIT) ||
(state == WLAN_VDEV_S_SUSPEND))
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
qdf_export_symbol(wlan_vdev_mlme_is_active);
QDF_STATUS wlan_vdev_chan_config_valid(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;
enum wlan_vdev_state substate;
state = wlan_vdev_mlme_get_state(vdev);
substate = wlan_vdev_mlme_get_substate(vdev);
if (!((state == WLAN_VDEV_S_INIT) || (state == WLAN_VDEV_S_STOP)))
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
qdf_export_symbol(wlan_vdev_chan_config_valid);
QDF_STATUS wlan_vdev_mlme_is_csa_restart(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;
enum wlan_vdev_state substate;
state = wlan_vdev_mlme_get_state(vdev);
substate = wlan_vdev_mlme_get_substate(vdev);
if ((state == WLAN_VDEV_S_SUSPEND) &&
(substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART))
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
QDF_STATUS wlan_vdev_is_going_down(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;
enum wlan_vdev_state substate;
state = wlan_vdev_mlme_get_state(vdev);
substate = wlan_vdev_mlme_get_substate(vdev);
if ((state == WLAN_VDEV_S_STOP) ||
((state == WLAN_VDEV_S_SUSPEND) &&
(substate == WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN)))
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
QDF_STATUS wlan_vdev_is_restart_progress(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;
enum wlan_vdev_state substate;
state = wlan_vdev_mlme_get_state(vdev);
substate = wlan_vdev_mlme_get_substate(vdev);
if ((state == WLAN_VDEV_S_START) &&
(substate == WLAN_VDEV_SS_START_RESTART_PROGRESS))
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
QDF_STATUS wlan_vdev_is_dfs_cac_wait(struct wlan_objmgr_vdev *vdev)
{
if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_DFS_CAC_WAIT)
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
void wlan_vdev_mlme_cmd_lock(struct wlan_objmgr_vdev *vdev)
{
struct vdev_mlme_obj *vdev_mlme;
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (!vdev_mlme) {
mlme_err("vdev component object is NULL");
return;
}
mlme_vdev_cmd_mutex_acquire(vdev_mlme);
}
void wlan_vdev_mlme_cmd_unlock(struct wlan_objmgr_vdev *vdev)
{
struct vdev_mlme_obj *vdev_mlme;
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (!vdev_mlme) {
mlme_err("vdev component object is NULL");
return;
}
mlme_vdev_cmd_mutex_release(vdev_mlme);
}
QDF_STATUS wlan_vdev_mlme_is_scan_allowed(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;
state = wlan_vdev_mlme_get_state(vdev);
if ((state == WLAN_VDEV_S_INIT) || (state == WLAN_VDEV_S_UP) ||
(state == WLAN_VDEV_S_STOP))
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}