qcacmn: Remove TDLS component and related files from hostcmn

TDLS component used in CLD only and needn't in hostcmn. So there
is requirement to move it from hostcmn to CLD. This change removes
policy mgr related files/codes from hostcmn.

Change-Id: Ifeaf1447e74f83a17072d08c4a0ff62a13e91518
CRs-Fixed: 2361584
Этот коммит содержится в:
Wu Gao
2018-12-08 10:56:49 +08:00
коммит произвёл nshrivas
родитель 4db889dfe6
Коммит 8e0f32b161
26 изменённых файлов: 0 добавлений и 14584 удалений

Просмотреть файл

@@ -1,309 +0,0 @@
/*
* Copyright (c) 2017-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
* 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: declares driver functions interfacing with linux kernel
*/
#ifndef _WLAN_CFG80211_TDLS_H_
#define _WLAN_CFG80211_TDLS_H_
#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/completion.h>
#include <net/cfg80211.h>
#include <qca_vendor.h>
#include <wlan_tdls_public_structs.h>
#include <qdf_list.h>
#include <qdf_types.h>
#include <wlan_tdls_ucfg_api.h>
#ifdef CONVERGED_TDLS_ENABLE
#define TDLS_VDEV_MAGIC 0x54444c53 /* "TDLS" */
/**
* struct osif_tdls_vdev - OS tdls vdev private structure
* @tdls_add_peer_comp: Completion to add tdls peer
* @tdls_del_peer_comp: Completion to delete tdls peer
* @tdls_mgmt_comp: Completion to send tdls mgmt packets
* @tdls_link_establish_req_comp: Completion to establish link, sync to
* send establish params to firmware, not used today.
* @tdls_teardown_comp: Completion to teardown tdls peer
* @tdls_user_cmd_comp: tdls user command completion event
* @tdls_antenna_switch_comp: Completion to switch antenna
* @tdls_add_peer_status: Peer status after add peer
* @mgmt_tx_completion_status: Tdls mgmt frames TX completion status code
* @tdls_user_cmd_len: tdls user command written buffer length
* @tdls_antenna_switch_status: return status after antenna switch
*/
struct osif_tdls_vdev {
struct completion tdls_add_peer_comp;
struct completion tdls_del_peer_comp;
struct completion tdls_mgmt_comp;
struct completion tdls_link_establish_req_comp;
struct completion tdls_teardown_comp;
struct completion tdls_user_cmd_comp;
struct completion tdls_antenna_switch_comp;
QDF_STATUS tdls_add_peer_status;
uint32_t mgmt_tx_completion_status;
uint32_t tdls_user_cmd_len;
int tdls_antenna_switch_status;
};
/**
* enum qca_wlan_vendor_tdls_trigger_mode_vdev_map: Maps the user space TDLS
* trigger mode in the host driver.
* @WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT: TDLS Connection and
* disconnection handled by user space.
* @WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT: TDLS connection and
* disconnection controlled by host driver based on data traffic.
* @WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL: TDLS connection and
* disconnection jointly controlled by user space and host driver.
*/
enum qca_wlan_vendor_tdls_trigger_mode_vdev_map {
WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT =
QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT,
WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT =
QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT,
WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL =
((QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT |
QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT) << 1),
};
/**
* wlan_cfg80211_tdls_priv_init() - API to initialize tdls os private
* @osif_priv: vdev os private
*
* API to initialize tdls os private
*
* Return: QDF_STATUS
*/
QDF_STATUS wlan_cfg80211_tdls_priv_init(struct vdev_osif_priv *osif_priv);
/**
* wlan_cfg80211_tdls_priv_deinit() - API to deinitialize tdls os private
* @osif_priv: vdev os private
*
* API to deinitialize tdls os private
*
* Return: None
*/
void wlan_cfg80211_tdls_priv_deinit(struct vdev_osif_priv *osif_priv);
/**
* wlan_cfg80211_tdls_add_peer() - process cfg80211 add TDLS peer request
* @vdev: vdev object
* @mac: MAC address for TDLS peer
*
* Return: 0 for success; negative errno otherwise
*/
int wlan_cfg80211_tdls_add_peer(struct wlan_objmgr_vdev *vdev,
const uint8_t *mac);
/**
* wlan_cfg80211_tdls_update_peer() - process cfg80211 update TDLS peer request
* @vdev: vdev object
* @mac: MAC address for TDLS peer
* @params: Pointer to station parameters
*
* Return: 0 for success; negative errno otherwise
*/
int wlan_cfg80211_tdls_update_peer(struct wlan_objmgr_vdev *vdev,
const uint8_t *mac,
struct station_parameters *params);
/**
* wlan_cfg80211_tdls_configure_mode() - configure tdls mode
* @vdev: vdev obj manager
* @trigger_mode: tdls trgger mode
*
* Return: 0 for success; negative errno otherwise
*/
int wlan_cfg80211_tdls_configure_mode(struct wlan_objmgr_vdev *vdev,
uint32_t trigger_mode);
/**
* wlan_cfg80211_tdls_oper() - process cfg80211 operation on an TDLS peer
* @vdev: vdev object
* @peer: MAC address of the TDLS peer
* @oper: cfg80211 TDLS operation
*
* Return: 0 on success; negative errno otherwise
*/
int wlan_cfg80211_tdls_oper(struct wlan_objmgr_vdev *vdev,
const uint8_t *peer,
enum nl80211_tdls_operation oper);
/**
* wlan_cfg80211_tdls_get_all_peers() - get all the TDLS peers from the list
* @vdev: vdev object
* @buf: output buffer
* @buflen: valid length of the output error
*
* Return: length of the output buffer
*/
int wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,
char *buf, int buflen);
/**
* wlan_cfg80211_tdls_mgmt() - process tdls management frames from the supplicant
* @vdev: vdev object
* @peer: MAC address of the TDLS peer
* @action_code: type of TDLS mgmt frame to be sent
* @dialog_token: dialog token used in the frame
* @status_code: status to be incuded in the frame
* @peer_capability: peer capability information
* @buf: additional IEs to be included
* @len: length of additional Ies
* @oper: cfg80211 TDLS operation
*
* Return: 0 on success; negative errno otherwise
*/
int wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_vdev *vdev,
const uint8_t *peer,
uint8_t action_code, uint8_t dialog_token,
uint16_t status_code, uint32_t peer_capability,
const uint8_t *buf, size_t len);
/**
* wlan_tdls_antenna_switch() - process tdls antenna switch
* @vdev: vdev object
* @mode: antenna mode
*
* Return: 0 on success; -EAGAIN to retry
*/
int wlan_tdls_antenna_switch(struct wlan_objmgr_vdev *vdev, uint32_t mode);
/**
* wlan_cfg80211_tdls_event_callback() - callback for tdls module
* @userdata: user data
* @type: request callback type
* @param: passed parameter
*
* This is used by TDLS to sync with os interface
*
* Return: None
*/
void wlan_cfg80211_tdls_event_callback(void *userdata,
enum tdls_event_type type,
struct tdls_osif_indication *param);
/**
* wlan_cfg80211_tdls_rx_callback() - Callback for rx mgmt frame
* @user_data: pointer to soc object
* @rx_frame: RX mgmt frame information
*
* This callback will be used to rx frames in os interface.
*
* Return: None
*/
void wlan_cfg80211_tdls_rx_callback(void *user_data,
struct tdls_rx_mgmt_frame *rx_frame);
/**
* hdd_notify_tdls_reset_adapter() - notify reset adapter to TDLS
* @vdev: vdev object manager
*
* Notify hdd reset adapter to TDLS component
*
* Return: None
*/
void hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev);
/**
* hdd_notify_sta_connect() - notify sta connect to TDLS
* @session_id: pointer to soc object
* @tdls_chan_swit_prohibited: indicates channel switch capability
* @tdls_prohibited: indicates tdls allowed or not
* @vdev: vdev object manager
*
* Notify sta connect event to TDLS component
*
* Return: None
*/
void
hdd_notify_sta_connect(uint8_t session_id,
bool tdls_chan_swit_prohibited,
bool tdls_prohibited,
struct wlan_objmgr_vdev *vdev);
/**
* hdd_notify_sta_disconnect() - notify sta disconnect to TDLS
* @session_id: pointer to soc object
* @lfr_roam: indicate, whether disconnect due to lfr roam
* @bool user_disconnect: disconnect from user space
* @vdev: vdev object manager
*
* Notify sta disconnect event to TDLS component
*
* Return: None
*/
void hdd_notify_sta_disconnect(uint8_t session_id,
bool lfr_roam,
bool user_disconnect,
struct wlan_objmgr_vdev *vdev);
/**
* hdd_notify_teardown_tdls_links() - notify TDLS to teardown links
* @vdev: vdev object manager
*
* Notify tdls to teardown all the links, due to certain events
* in the system
*
* Return: None
*/
void hdd_notify_teardown_tdls_links(struct wlan_objmgr_vdev *vdev);
#else
static inline void
hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev)
{
}
static inline void
hdd_notify_sta_connect(uint8_t session_id,
bool tdls_chan_swit_prohibited,
bool tdls_prohibited,
struct wlan_objmgr_vdev *vdev)
{
}
static inline
void hdd_notify_sta_disconnect(uint8_t session_id,
bool lfr_roam,
bool user_disconnect,
struct wlan_objmgr_vdev *vdev)
{
}
static inline
int wlan_cfg80211_tdls_configure_mode(struct wlan_objmgr_vdev *vdev,
uint32_t trigger_mode)
{
return 0;
}
static inline
void hdd_notify_teardown_tdls_links(struct wlan_objmgr_vdev *vdev)
{
}
#endif
#endif

Просмотреть файл

@@ -1,929 +0,0 @@
/*
* Copyright (c) 2017-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
* 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: defines driver functions interfacing with linux kernel
*/
#include <qdf_list.h>
#include <qdf_status.h>
#include <linux/wireless.h>
#include <linux/netdevice.h>
#include <net/cfg80211.h>
#include <wlan_cfg80211.h>
#include <wlan_cfg80211_tdls.h>
#include <wlan_osif_priv.h>
#include <wlan_tdls_public_structs.h>
#include <wlan_tdls_ucfg_api.h>
#include <qdf_mem.h>
#include <wlan_utility.h>
#include <wlan_reg_services_api.h>
#define MAX_CHANNEL (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS)
#define TDLS_MAX_NO_OF_2_4_CHANNELS 14
static int wlan_cfg80211_tdls_validate_mac_addr(const uint8_t *mac)
{
static const uint8_t temp_mac[QDF_MAC_ADDR_SIZE] = {0};
if (!qdf_mem_cmp(mac, temp_mac, QDF_MAC_ADDR_SIZE)) {
cfg80211_debug("Invalid Mac address " QDF_MAC_ADDR_STR " cmd declined.",
QDF_MAC_ADDR_ARRAY(mac));
return -EINVAL;
}
return 0;
}
QDF_STATUS wlan_cfg80211_tdls_priv_init(struct vdev_osif_priv *osif_priv)
{
struct osif_tdls_vdev *tdls_priv;
cfg80211_debug("initialize tdls os if layer private structure");
tdls_priv = qdf_mem_malloc(sizeof(*tdls_priv));
if (!tdls_priv) {
cfg80211_err("failed to allocate memory for tdls_priv");
return QDF_STATUS_E_NOMEM;
}
init_completion(&tdls_priv->tdls_add_peer_comp);
init_completion(&tdls_priv->tdls_del_peer_comp);
init_completion(&tdls_priv->tdls_mgmt_comp);
init_completion(&tdls_priv->tdls_link_establish_req_comp);
init_completion(&tdls_priv->tdls_teardown_comp);
init_completion(&tdls_priv->tdls_user_cmd_comp);
init_completion(&tdls_priv->tdls_antenna_switch_comp);
osif_priv->osif_tdls = tdls_priv;
return QDF_STATUS_SUCCESS;
}
void wlan_cfg80211_tdls_priv_deinit(struct vdev_osif_priv *osif_priv)
{
cfg80211_debug("deinitialize tdls os if layer private structure");
if (!osif_priv) {
cfg80211_err("OS private structure of vdev is null ");
return;
}
if (osif_priv->osif_tdls)
qdf_mem_free(osif_priv->osif_tdls);
osif_priv->osif_tdls = NULL;
}
void hdd_notify_teardown_tdls_links(struct wlan_objmgr_vdev *vdev)
{
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
QDF_STATUS status;
unsigned long rc;
if (!vdev)
return;
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
reinit_completion(&tdls_priv->tdls_teardown_comp);
status = ucfg_tdls_teardown_links(vdev);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_teardown_links failed err %d", status);
return;
}
cfg80211_debug("Wait for tdls teardown completion. Timeout %u ms",
WAIT_TIME_FOR_TDLS_TEARDOWN_LINKS);
rc = wait_for_completion_timeout(
&tdls_priv->tdls_teardown_comp,
msecs_to_jiffies(WAIT_TIME_FOR_TDLS_TEARDOWN_LINKS));
if (0 == rc) {
cfg80211_err(" Teardown Completion timed out rc: %ld", rc);
return;
}
cfg80211_debug("TDLS teardown completion status %ld ", rc);
}
void hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev)
{
ucfg_tdls_notify_reset_adapter(vdev);
}
void
hdd_notify_sta_connect(uint8_t session_id,
bool tdls_chan_swit_prohibited,
bool tdls_prohibited,
struct wlan_objmgr_vdev *vdev)
{
struct tdls_sta_notify_params notify_info = {0};
QDF_STATUS status;
if (!vdev) {
cfg80211_err("vdev is NULL");
return;
}
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("can't get vdev");
return;
}
notify_info.session_id = session_id;
notify_info.vdev = vdev;
notify_info.tdls_chan_swit_prohibited = tdls_chan_swit_prohibited;
notify_info.tdls_prohibited = tdls_prohibited;
ucfg_tdls_notify_sta_connect(&notify_info);
}
void hdd_notify_sta_disconnect(uint8_t session_id,
bool lfr_roam,
bool user_disconnect,
struct wlan_objmgr_vdev *vdev)
{
struct tdls_sta_notify_params notify_info = {0};
QDF_STATUS status;
if (!vdev) {
cfg80211_err("vdev is NULL");
return;
}
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("can't get vdev");
return;
}
notify_info.session_id = session_id;
notify_info.lfr_roam = lfr_roam;
notify_info.tdls_chan_swit_prohibited = false;
notify_info.tdls_prohibited = false;
notify_info.vdev = vdev;
notify_info.user_disconnect = user_disconnect;
ucfg_tdls_notify_sta_disconnect(&notify_info);
}
int wlan_cfg80211_tdls_add_peer(struct wlan_objmgr_vdev *vdev,
const uint8_t *mac)
{
struct tdls_add_peer_params *add_peer_req;
int status;
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
unsigned long rc;
status = wlan_cfg80211_tdls_validate_mac_addr(mac);
if (status)
return status;
cfg80211_debug("Add TDLS peer " QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(mac));
add_peer_req = qdf_mem_malloc(sizeof(*add_peer_req));
if (!add_peer_req) {
cfg80211_err("Failed to allocate tdls add peer request mem");
return -EINVAL;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
add_peer_req->vdev_id = wlan_vdev_get_id(vdev);
qdf_mem_copy(add_peer_req->peer_addr, mac, QDF_MAC_ADDR_SIZE);
reinit_completion(&tdls_priv->tdls_add_peer_comp);
status = ucfg_tdls_add_peer(vdev, add_peer_req);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_add_peer returned err %d", status);
status = -EIO;
goto error;
}
rc = wait_for_completion_timeout(
&tdls_priv->tdls_add_peer_comp,
msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
if (!rc) {
cfg80211_err("timeout for tdls add peer indication %ld", rc);
status = -EPERM;
goto error;
}
if (QDF_IS_STATUS_ERROR(tdls_priv->tdls_add_peer_status)) {
cfg80211_err("tdls add peer failed, status:%d",
tdls_priv->tdls_add_peer_status);
status = -EPERM;
}
error:
qdf_mem_free(add_peer_req);
return status;
}
static bool
is_duplicate_channel(uint8_t *arr, int index, uint8_t match)
{
int i;
for (i = 0; i < index; i++) {
if (arr[i] == match)
return true;
}
return false;
}
static void
tdls_calc_channels_from_staparams(struct tdls_update_peer_params *req_info,
struct station_parameters *params)
{
int i = 0, j = 0, k = 0, no_of_channels = 0;
int num_unique_channels;
int next;
uint8_t *dest_chans;
const uint8_t *src_chans;
dest_chans = req_info->supported_channels;
src_chans = params->supported_channels;
/* Convert (first channel , number of channels) tuple to
* the total list of channels. This goes with the assumption
* that if the first channel is < 14, then the next channels
* are an incremental of 1 else an incremental of 4 till the number
* of channels.
*/
for (i = 0; i < params->supported_channels_len &&
j < WLAN_MAC_MAX_SUPP_CHANNELS; i += 2) {
int wifi_chan_index;
if (!is_duplicate_channel(dest_chans, j, src_chans[i]))
dest_chans[j] = src_chans[i];
else
continue;
wifi_chan_index = ((dest_chans[j] <= WLAN_CHANNEL_14) ? 1 : 4);
no_of_channels = src_chans[i + 1];
cfg80211_debug("i:%d,j:%d,k:%d,[%d]:%d,index:%d,chans_num: %d",
i, j, k, j,
dest_chans[j],
wifi_chan_index,
no_of_channels);
for (k = 1; k <= no_of_channels &&
j < WLAN_MAC_MAX_SUPP_CHANNELS - 1; k++) {
next = dest_chans[j] + wifi_chan_index;
if (!is_duplicate_channel(dest_chans, j + 1, next))
dest_chans[j + 1] = next;
else
continue;
cfg80211_debug("i: %d, j: %d, k: %d, [%d]: %d",
i, j, k, j + 1, dest_chans[j + 1]);
j += 1;
}
}
num_unique_channels = j + 1;
cfg80211_debug("Unique Channel List: supported_channels ");
for (i = 0; i < num_unique_channels; i++)
cfg80211_debug("[%d]: %d,", i, dest_chans[i]);
if (MAX_CHANNEL < num_unique_channels)
num_unique_channels = MAX_CHANNEL;
req_info->supported_channels_len = num_unique_channels;
cfg80211_debug("After removing duplcates supported_channels_len: %d",
req_info->supported_channels_len);
}
static void
wlan_cfg80211_tdls_extract_params(struct tdls_update_peer_params *req_info,
struct station_parameters *params)
{
int i;
cfg80211_debug("sta cap %d, uapsd_queue %d, max_sp %d",
params->capability,
params->uapsd_queues, params->max_sp);
if (!req_info) {
cfg80211_err("reg_info is NULL");
return;
}
req_info->capability = params->capability;
req_info->uapsd_queues = params->uapsd_queues;
req_info->max_sp = params->max_sp;
if (params->supported_channels_len)
tdls_calc_channels_from_staparams(req_info, params);
if (params->supported_oper_classes_len > WLAN_MAX_SUPP_OPER_CLASSES) {
cfg80211_debug("received oper classes:%d, resetting it to max supported: %d",
params->supported_oper_classes_len,
WLAN_MAX_SUPP_OPER_CLASSES);
params->supported_oper_classes_len = WLAN_MAX_SUPP_OPER_CLASSES;
}
qdf_mem_copy(req_info->supported_oper_classes,
params->supported_oper_classes,
params->supported_oper_classes_len);
req_info->supported_oper_classes_len =
params->supported_oper_classes_len;
if (params->ext_capab_len)
qdf_mem_copy(req_info->extn_capability, params->ext_capab,
sizeof(req_info->extn_capability));
if (params->ht_capa) {
req_info->htcap_present = 1;
qdf_mem_copy(&req_info->ht_cap, params->ht_capa,
sizeof(struct htcap_cmn_ie));
}
req_info->supported_rates_len = params->supported_rates_len;
/* Note : The Maximum sizeof supported_rates sent by the Supplicant is
* 32. The supported_rates array , for all the structures propogating
* till Add Sta to the firmware has to be modified , if the supplicant
* (ieee80211) is modified to send more rates.
*/
/* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
*/
if (req_info->supported_rates_len > WLAN_MAC_MAX_SUPP_RATES)
req_info->supported_rates_len = WLAN_MAC_MAX_SUPP_RATES;
if (req_info->supported_rates_len) {
qdf_mem_copy(req_info->supported_rates,
params->supported_rates,
req_info->supported_rates_len);
cfg80211_debug("Supported Rates with Length %d",
req_info->supported_rates_len);
for (i = 0; i < req_info->supported_rates_len; i++)
cfg80211_debug("[%d]: %0x", i,
req_info->supported_rates[i]);
}
if (params->vht_capa) {
req_info->vhtcap_present = 1;
qdf_mem_copy(&req_info->vht_cap, params->vht_capa,
sizeof(struct vhtcap));
}
if (params->ht_capa || params->vht_capa ||
(params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
req_info->is_qos_wmm_sta = true;
}
int wlan_cfg80211_tdls_update_peer(struct wlan_objmgr_vdev *vdev,
const uint8_t *mac,
struct station_parameters *params)
{
struct tdls_update_peer_params *req_info;
int status;
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
unsigned long rc;
status = wlan_cfg80211_tdls_validate_mac_addr(mac);
if (status)
return status;
cfg80211_debug("Update TDLS peer " QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(mac));
req_info = qdf_mem_malloc(sizeof(*req_info));
if (!req_info) {
cfg80211_err("Failed to allocate tdls add peer request mem");
return -EINVAL;
}
wlan_cfg80211_tdls_extract_params(req_info, params);
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
req_info->vdev_id = wlan_vdev_get_id(vdev);
qdf_mem_copy(req_info->peer_addr, mac, QDF_MAC_ADDR_SIZE);
reinit_completion(&tdls_priv->tdls_add_peer_comp);
status = ucfg_tdls_update_peer(vdev, req_info);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_update_peer returned err %d", status);
status = -EIO;
goto error;
}
rc = wait_for_completion_timeout(
&tdls_priv->tdls_add_peer_comp,
msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
if (!rc) {
cfg80211_err("timeout for tdls update peer indication %ld", rc);
status = -EPERM;
goto error;
}
if (QDF_IS_STATUS_ERROR(tdls_priv->tdls_add_peer_status)) {
cfg80211_err("tdls update peer failed, status:%d",
tdls_priv->tdls_add_peer_status);
status = -EPERM;
}
error:
qdf_mem_free(req_info);
return status;
}
static char *tdls_oper_to_str(enum nl80211_tdls_operation oper)
{
switch (oper) {
case NL80211_TDLS_ENABLE_LINK:
return "TDLS_ENABLE_LINK";
case NL80211_TDLS_DISABLE_LINK:
return "TDLS_DISABLE_LINK";
case NL80211_TDLS_TEARDOWN:
return "TDLS_TEARDOWN";
case NL80211_TDLS_SETUP:
return "TDLS_SETUP";
default:
return "UNKNOWN:ERR";
}
}
static enum tdls_command_type tdls_oper_to_cmd(enum nl80211_tdls_operation oper)
{
if (oper == NL80211_TDLS_ENABLE_LINK)
return TDLS_CMD_ENABLE_LINK;
else if (oper == NL80211_TDLS_DISABLE_LINK)
return TDLS_CMD_DISABLE_LINK;
else if (oper == NL80211_TDLS_TEARDOWN)
return TDLS_CMD_REMOVE_FORCE_PEER;
else if (oper == NL80211_TDLS_SETUP)
return TDLS_CMD_CONFIG_FORCE_PEER;
else
return 0;
}
int wlan_cfg80211_tdls_configure_mode(struct wlan_objmgr_vdev *vdev,
uint32_t trigger_mode)
{
enum tdls_feature_mode tdls_mode;
struct tdls_set_mode_params set_mode_params;
int status;
if (!vdev)
return -EINVAL;
switch (trigger_mode) {
case WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT:
tdls_mode = TDLS_SUPPORT_EXP_TRIG_ONLY;
return 0;
case WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL:
tdls_mode = TDLS_SUPPORT_EXT_CONTROL;
break;
case WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT:
tdls_mode = TDLS_SUPPORT_IMP_MODE;
return 0;
default:
cfg80211_err("Invalid TDLS trigger mode");
return -EINVAL;
}
cfg80211_notice("cfg80211 tdls trigger mode %d", trigger_mode);
set_mode_params.source = TDLS_SET_MODE_SOURCE_USER;
set_mode_params.tdls_mode = tdls_mode;
set_mode_params.update_last = false;
set_mode_params.vdev = vdev;
status = ucfg_tdls_set_operating_mode(&set_mode_params);
return status;
}
int wlan_cfg80211_tdls_oper(struct wlan_objmgr_vdev *vdev,
const uint8_t *peer,
enum nl80211_tdls_operation oper)
{
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
int status;
unsigned long rc;
enum tdls_command_type cmd;
status = wlan_cfg80211_tdls_validate_mac_addr(peer);
if (status)
return status;
if (NL80211_TDLS_DISCOVERY_REQ == oper) {
cfg80211_warn(
"We don't support in-driver setup/teardown/discovery");
return -ENOTSUPP;
}
cfg80211_debug("%s start", tdls_oper_to_str(oper));
cmd = tdls_oper_to_cmd(oper);
switch (oper) {
case NL80211_TDLS_ENABLE_LINK:
case NL80211_TDLS_TEARDOWN:
case NL80211_TDLS_SETUP:
status = ucfg_tdls_oper(vdev, peer, cmd);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("%s fail %d",
tdls_oper_to_str(oper), status);
status = -EIO;
goto error;
}
break;
case NL80211_TDLS_DISABLE_LINK:
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
reinit_completion(&tdls_priv->tdls_del_peer_comp);
status = ucfg_tdls_oper(vdev, peer, cmd);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_disable_link fail %d", status);
status = -EIO;
goto error;
}
rc = wait_for_completion_timeout(
&tdls_priv->tdls_del_peer_comp,
msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
if (!rc) {
cfg80211_err("timeout for tdls disable link %ld", rc);
status = -EPERM;
}
break;
default:
cfg80211_err("unsupported event %d", oper);
status = -ENOTSUPP;
}
error:
return status;
}
void wlan_cfg80211_tdls_rx_callback(void *user_data,
struct tdls_rx_mgmt_frame *rx_frame)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_vdev *vdev;
struct vdev_osif_priv *osif_priv;
struct wireless_dev *wdev;
uint16_t freq;
cfg80211_debug("user data:%pK, vdev id:%d, rssi:%d, buf:%pK, len:%d",
user_data, rx_frame->vdev_id, rx_frame->rx_rssi,
rx_frame->buf, rx_frame->frame_len);
psoc = user_data;
if (!psoc) {
cfg80211_err("psoc is null");
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
rx_frame->vdev_id, WLAN_TDLS_NB_ID);
if (!vdev) {
cfg80211_err("vdev is null");
return;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
if (!osif_priv) {
cfg80211_err("osif_priv is null");
goto fail;
}
wdev = osif_priv->wdev;
if (!wdev) {
cfg80211_err("wdev is null");
goto fail;
}
if (rx_frame->rx_chan <= TDLS_MAX_NO_OF_2_4_CHANNELS)
freq = ieee80211_channel_to_frequency(
rx_frame->rx_chan, NL80211_BAND_2GHZ);
else
freq = ieee80211_channel_to_frequency(
rx_frame->rx_chan, NL80211_BAND_5GHZ);
cfg80211_notice("Indicate frame over nl80211, vdev id:%d, idx:%d",
rx_frame->vdev_id, wdev->netdev->ifindex);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
rx_frame->buf, rx_frame->frame_len,
NL80211_RXMGMT_FLAG_ANSWERED);
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
rx_frame->buf, rx_frame->frame_len,
NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
#else
cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
rx_frame->buf, rx_frame->frame_len, GFP_ATOMIC);
#endif /* LINUX_VERSION_CODE */
fail:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
}
int wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,
char *buf, int buflen)
{
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
int32_t len;
QDF_STATUS status;
unsigned long rc;
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
reinit_completion(&tdls_priv->tdls_user_cmd_comp);
status = ucfg_tdls_get_all_peers(vdev, buf, buflen);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_get_all_peers failed err %d", status);
len = scnprintf(buf, buflen,
"\nucfg_tdls_send_mgmt failed\n");
goto error_get_tdls_peers;
}
cfg80211_debug("Wait for tdls_user_cmd_comp. Timeout %u ms",
WAIT_TIME_FOR_TDLS_USER_CMD);
rc = wait_for_completion_timeout(
&tdls_priv->tdls_user_cmd_comp,
msecs_to_jiffies(WAIT_TIME_FOR_TDLS_USER_CMD));
if (0 == rc) {
cfg80211_err("TDLS user cmd get all peers timed out rc %ld",
rc);
len = scnprintf(buf, buflen,
"\nTDLS user cmd get all peers timed out\n");
goto error_get_tdls_peers;
}
len = tdls_priv->tdls_user_cmd_len;
error_get_tdls_peers:
return len;
}
int wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_vdev *vdev,
const uint8_t *peer_mac,
uint8_t action_code, uint8_t dialog_token,
uint16_t status_code, uint32_t peer_capability,
const uint8_t *buf, size_t len)
{
struct tdls_action_frame_request mgmt_req;
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
int status;
unsigned long rc;
int max_sta_failed = 0;
struct tdls_validate_action_req chk_frame;
struct tdls_set_responder_req set_responder;
status = wlan_cfg80211_tdls_validate_mac_addr(peer_mac);
if (status)
return status;
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
/* make sure doesn't call send_mgmt() while it is pending */
if (TDLS_VDEV_MAGIC == tdls_priv->mgmt_tx_completion_status) {
cfg80211_err(QDF_MAC_ADDR_STR " action %d couldn't sent, as one is pending. return EBUSY",
QDF_MAC_ADDR_ARRAY(peer_mac), action_code);
return -EBUSY;
}
/* Reset TDLS VDEV magic */
tdls_priv->mgmt_tx_completion_status = TDLS_VDEV_MAGIC;
/*prepare the request */
/* Validate the management Request */
chk_frame.vdev = vdev;
chk_frame.action_code = action_code;
qdf_mem_copy(chk_frame.peer_mac, peer_mac, QDF_MAC_ADDR_SIZE);
chk_frame.dialog_token = dialog_token;
chk_frame.action_code = action_code;
chk_frame.status_code = status_code;
chk_frame.len = len;
chk_frame.max_sta_failed = max_sta_failed;
mgmt_req.chk_frame = &chk_frame;
mgmt_req.vdev = vdev;
mgmt_req.vdev_id = wlan_vdev_get_id(vdev);
mgmt_req.session_id = mgmt_req.vdev_id;
/* populate management req params */
qdf_mem_copy(mgmt_req.tdls_mgmt.peer_mac.bytes,
peer_mac, QDF_MAC_ADDR_SIZE);
mgmt_req.tdls_mgmt.dialog = dialog_token;
mgmt_req.tdls_mgmt.frame_type = action_code;
mgmt_req.tdls_mgmt.len = len;
mgmt_req.tdls_mgmt.peer_capability = peer_capability;
mgmt_req.tdls_mgmt.status_code = chk_frame.status_code;
/*populate the additional IE's */
mgmt_req.cmd_buf = buf;
mgmt_req.len = len;
reinit_completion(&tdls_priv->tdls_mgmt_comp);
status = ucfg_tdls_send_mgmt_frame(&mgmt_req);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_send_mgmt failed err %d", status);
status = -EIO;
tdls_priv->mgmt_tx_completion_status = false;
goto error_mgmt_req;
}
cfg80211_debug("Wait for tdls_mgmt_comp. Timeout %u ms",
WAIT_TIME_FOR_TDLS_MGMT);
rc = wait_for_completion_timeout(
&tdls_priv->tdls_mgmt_comp,
msecs_to_jiffies(WAIT_TIME_FOR_TDLS_MGMT));
if ((0 == rc) || (true != tdls_priv->mgmt_tx_completion_status)) {
cfg80211_err("%s rc %ld mgmtTxCompletionStatus %u",
!rc ? "Mgmt Tx Completion timed out" :
"Mgmt Tx Completion failed",
rc, tdls_priv->mgmt_tx_completion_status);
tdls_priv->mgmt_tx_completion_status = false;
status = -EINVAL;
goto error_mgmt_req;
}
cfg80211_debug("Mgmt Tx Completion status %ld TxCompletion %u",
rc, tdls_priv->mgmt_tx_completion_status);
if (chk_frame.max_sta_failed) {
status = max_sta_failed;
goto error_mgmt_req;
}
if (TDLS_SETUP_RESPONSE == action_code ||
TDLS_SETUP_CONFIRM == action_code) {
qdf_mem_copy(set_responder.peer_mac, peer_mac,
QDF_MAC_ADDR_SIZE);
set_responder.vdev = vdev;
if (TDLS_SETUP_RESPONSE == action_code)
set_responder.responder = false;
if (TDLS_SETUP_CONFIRM == action_code)
set_responder.responder = true;
ucfg_tdls_responder(&set_responder);
}
error_mgmt_req:
return status;
}
int wlan_tdls_antenna_switch(struct wlan_objmgr_vdev *vdev, uint32_t mode)
{
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
int ret;
unsigned long rc;
if (!vdev) {
cfg80211_err("vdev is NULL");
return -EAGAIN;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
reinit_completion(&tdls_priv->tdls_antenna_switch_comp);
ret = ucfg_tdls_antenna_switch(vdev, mode);
if (QDF_IS_STATUS_ERROR(ret)) {
cfg80211_err("ucfg_tdls_antenna_switch failed err %d", ret);
ret = -EAGAIN;
goto error;
}
rc = wait_for_completion_timeout(
&tdls_priv->tdls_antenna_switch_comp,
msecs_to_jiffies(WAIT_TIME_FOR_TDLS_ANTENNA_SWITCH));
if (!rc) {
cfg80211_err("timeout for tdls antenna switch %ld", rc);
ret = -EAGAIN;
goto error;
}
ret = tdls_priv->tdls_antenna_switch_status;
cfg80211_debug("tdls antenna switch status:%d", ret);
error:
return ret;
}
static void
wlan_cfg80211_tdls_indicate_discovery(struct tdls_osif_indication *ind)
{
struct vdev_osif_priv *osif_vdev;
osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
cfg80211_debug("Implicit TDLS, request Send Discovery request");
cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
ind->peer_mac, NL80211_TDLS_DISCOVERY_REQ,
false, GFP_KERNEL);
}
static void
wlan_cfg80211_tdls_indicate_setup(struct tdls_osif_indication *ind)
{
struct vdev_osif_priv *osif_vdev;
osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
cfg80211_debug("Indication to request TDLS setup");
cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
ind->peer_mac, NL80211_TDLS_SETUP, false,
GFP_KERNEL);
}
static void
wlan_cfg80211_tdls_indicate_teardown(struct tdls_osif_indication *ind)
{
struct vdev_osif_priv *osif_vdev;
osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
cfg80211_debug("Teardown reason %d", ind->reason);
cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
ind->peer_mac, NL80211_TDLS_TEARDOWN,
ind->reason, GFP_KERNEL);
}
void wlan_cfg80211_tdls_event_callback(void *user_data,
enum tdls_event_type type,
struct tdls_osif_indication *ind)
{
struct vdev_osif_priv *osif_vdev;
struct osif_tdls_vdev *tdls_priv;
if (!ind || !ind->vdev) {
cfg80211_err("ind: %pK", ind);
return;
}
osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
tdls_priv = osif_vdev->osif_tdls;
switch (type) {
case TDLS_EVENT_MGMT_TX_ACK_CNF:
tdls_priv->mgmt_tx_completion_status = ind->status;
complete(&tdls_priv->tdls_mgmt_comp);
break;
case TDLS_EVENT_ADD_PEER:
tdls_priv->tdls_add_peer_status = ind->status;
complete(&tdls_priv->tdls_add_peer_comp);
break;
case TDLS_EVENT_DEL_PEER:
complete(&tdls_priv->tdls_del_peer_comp);
break;
case TDLS_EVENT_DISCOVERY_REQ:
wlan_cfg80211_tdls_indicate_discovery(ind);
break;
case TDLS_EVENT_TEARDOWN_REQ:
wlan_cfg80211_tdls_indicate_teardown(ind);
break;
case TDLS_EVENT_SETUP_REQ:
wlan_cfg80211_tdls_indicate_setup(ind);
break;
case TDLS_EVENT_TEARDOWN_LINKS_DONE:
complete(&tdls_priv->tdls_teardown_comp);
break;
case TDLS_EVENT_USER_CMD:
tdls_priv->tdls_user_cmd_len = ind->status;
complete(&tdls_priv->tdls_user_cmd_comp);
break;
case TDLS_EVENT_ANTENNA_SWITCH:
tdls_priv->tdls_antenna_switch_status = ind->status;
complete(&tdls_priv->tdls_antenna_switch_comp);
default:
break;
}
}