qcacmn: Add os_if changes for tdls management

Add os interface changes to send tdls management
frames to tdls component

Change-Id: Ib675e4b089a88ad618f918d9992a777c7221b34c
CRs-Fixed: 2034220
This commit is contained in:
Kabilan Kannan 2017-03-26 18:52:47 -07:00 • committed by Sandeep Puligilla
commit e81cb8eac8
16 changed files with 1085 additions and 20 deletions

View file

@ -33,6 +33,9 @@
#include <qdf_types.h>
#include <wlan_tdls_ucfg_api.h>
#define TDLS_VDEV_MAGIC 0x54444c53 /* "TDLS" */
/**
* struct osif_tdls_vdev - OS tdls vdev private structure
* @tdls_add_peer_comp: Completion to add tdls peer
@ -52,6 +55,26 @@ struct osif_tdls_vdev {
uint32_t mgmt_tx_completion_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
@ -96,6 +119,17 @@ int wlan_cfg80211_tdls_update_peer(struct wlan_objmgr_pdev *pdev,
struct net_device *dev,
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
* @pdev: pdev object
@ -110,6 +144,27 @@ int wlan_cfg80211_tdls_oper(struct wlan_objmgr_pdev *pdev,
const uint8_t *peer,
enum nl80211_tdls_operation oper);
/**
* wlan_cfg80211_tdls_mgmt() - process tdls management frames from the supplicant
* @pdev: pdev object
* @dev: net device
* @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: lenght of additional Ies
* @oper: cfg80211 TDLS operation
*
* Return: 0 on success; negative errno otherwise
*/
int wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_pdev *pdev,
struct net_device *dev, 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_cfg80211_tdls_event_callback() - callback for tdls module
* @userdata: user data
@ -123,4 +178,17 @@ int wlan_cfg80211_tdls_oper(struct wlan_objmgr_pdev *pdev,
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);
#endif

View file

@ -36,6 +36,9 @@
#define MAX_CHANNEL (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS)
#define TDLS_MAX_NO_OF_2_4_CHANNELS 14
QDF_STATUS wlan_cfg80211_tdls_priv_init(struct vdev_osif_priv *osif_priv)
{
struct osif_tdls_vdev *tdls_priv;
@ -370,6 +373,41 @@ static enum tdls_command_type tdls_oper_to_cmd(enum nl80211_tdls_operation oper)
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_IMP_MODE;
break;
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;
break;
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_pdev *pdev,
struct net_device *dev,
const uint8_t *peer,
@ -442,6 +480,196 @@ 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:%p, vdev id:%d, rssi:%d, buf:%p, 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;
}
wlan_vdev_obj_lock(vdev);
osif_priv = wlan_vdev_get_ospriv(vdev);
wlan_vdev_obj_unlock(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_mgmt(struct wlan_objmgr_pdev *pdev,
struct net_device *dev, 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 wlan_objmgr_vdev *vdev;
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;
vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev(pdev,
dev->dev_addr,
WLAN_OSIF_ID);
if (vdev == NULL) {
cfg80211_err("vdev object is NULL");
return -EIO;
}
wlan_vdev_obj_lock(vdev);
osif_priv = wlan_vdev_get_ospriv(vdev);
wlan_vdev_obj_unlock(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_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY",
QDF_MAC_ADDR_ARRAY(peer_mac), action_code);
wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
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_info("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_info("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:
wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
return status;
}
static void
wlan_cfg80211_tdls_indicate_discovery(struct tdls_osif_indication *ind)
{
@ -504,6 +732,10 @@ void wlan_cfg80211_tdls_event_callback(void *user_data,
wlan_vdev_obj_unlock(ind->vdev);
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);

View file

@ -309,17 +309,18 @@ enum wnm_actioncode {
* @TDLS_DISCOVERY_REQUEST: tdls discovery request frame
*/
enum tdls_actioncode {
TDLS_SETUP_REQUEST,
TDLS_SETUP_RESPONSE,
TDLS_SETUP_CONFIRM,
TDLS_TEARDOWN,
TDLS_PEER_TRAFFIC_INDICATION,
TDLS_CHANNEL_SWITCH_REQUEST,
TDLS_CHANNEL_SWITCH_RESPONSE,
TDLS_PEER_PSM_REQUEST,
TDLS_PEER_PSM_RESPONSE,
TDLS_PEER_TRAFFIC_RESPONSE,
TDLS_DISCOVERY_REQUEST,
TDLS_SETUP_REQUEST = 0,
TDLS_SETUP_RESPONSE = 1,
TDLS_SETUP_CONFIRM = 2,
TDLS_TEARDOWN = 3,
TDLS_PEER_TRAFFIC_INDICATION = 4,
TDLS_CHANNEL_SWITCH_REQUEST = 5,
TDLS_CHANNEL_SWITCH_RESPONSE = 6,
TDLS_PEER_PSM_REQUEST = 7,
TDLS_PEER_PSM_RESPONSE = 8,
TDLS_PEER_TRAFFIC_RESPONSE = 9,
TDLS_DISCOVERY_REQUEST = 10,
TDLS_DISCOVERY_RESPONSE = 14,
};
/**

View file

@ -133,6 +133,7 @@ struct wlan_objmgr_peer_mlme {
uint32_t max_rate;
uint16_t seq_num;
enum wlan_peer_state state;
bool is_authenticated;
};
/**
@ -732,6 +733,25 @@ static inline void wlan_peer_mlme_set_state(
peer->peer_mlme.state = state;
}
/**
* wlan_peer_mlme_set_auth_state() - peer mlme auth state
* @peer: PEER object
* @is_authenticated: true or false
*
* API to update the current peer auth state
*
* Caller need to acquire lock with wlan_peer_obj_lock()
*
* Return: void
*/
static inline void wlan_peer_mlme_set_auth_state(
struct wlan_objmgr_peer *peer,
bool is_authenticated)
{
/* This API is invoked with lock acquired, do not add log prints */
peer->peer_mlme.is_authenticated = is_authenticated;
}
/**
* wlan_peer_mlme_get_state() - peer mlme state
* @peer: PEER object
@ -749,6 +769,23 @@ static inline enum wlan_peer_state wlan_peer_mlme_get_state(
return peer->peer_mlme.state;
}
/**
* wlan_peer_mlme_get_auth_state() - peer mlme auth state
* @peer: PEER object
*
* API to get peer auth state
*
* Caller need to acquire lock with wlan_peer_obj_lock()
*
* Return: auth state true/false
*/
static inline bool wlan_peer_mlme_get_auth_state(
struct wlan_objmgr_peer *peer)
{
/* This API is invoked with lock acquired, do not add log prints */
return peer->peer_mlme.is_authenticated;
}
/**
* wlan_peer_mlme_get_next_seq_num() - get peer mlme next sequence number
* @peer: PEER object

View file

@ -569,6 +569,244 @@ tdls_add_peer_serialize_callback(struct wlan_serialization_command *cmd,
return status;
}
void tdls_reset_nss(struct tdls_soc_priv_obj *tdls_soc,
uint8_t action_code)
{
if (!tdls_soc)
return;
if (TDLS_TEARDOWN != action_code ||
tdls_soc->tdls_nss_switch_in_progress)
return;
if (tdls_soc->tdls_teardown_peers_cnt != 0)
tdls_soc->tdls_teardown_peers_cnt--;
if (tdls_soc->tdls_teardown_peers_cnt == 0) {
if (tdls_soc->tdls_nss_transition_mode ==
TDLS_NSS_TRANSITION_S_1x1_to_2x2) {
/* TDLS NSS switch is fully completed, so
* reset the flags.
*/
tdls_notice("TDLS NSS switch is fully completed");
tdls_soc->tdls_nss_switch_in_progress = false;
tdls_soc->tdls_nss_teardown_complete = false;
} else {
/* TDLS NSS switch is not yet completed, but
* tdls teardown is completed for all the
* peers.
*/
tdls_notice("teardown done & NSS switch in progress");
tdls_soc->tdls_nss_teardown_complete = true;
}
}
}
/**
* tdls_set_cap() - set TDLS capability type
* @tdls_vdev: tdls vdev object
* @mac: peer mac address
* @cap: TDLS capability type
*
* Return: 0 if successful or negative errno otherwise
*/
int tdls_set_cap(struct tdls_vdev_priv_obj *tdls_vdev, const uint8_t *mac,
enum tdls_peer_capab cap)
{
struct tdls_peer *curr_peer;
curr_peer = tdls_get_peer(tdls_vdev, mac);
if (curr_peer == NULL) {
tdls_err("curr_peer is NULL");
return -EINVAL;
}
curr_peer->tdls_support = cap;
return 0;
}
static int tdls_validate_setup_frames(struct tdls_soc_priv_obj *tdls_soc,
struct tdls_validate_action_req *tdls_validate)
{
/* supplicant still sends tdls_mgmt(SETUP_REQ)
* even after we return error code at
* 'add_station()'. Hence we have this check
* again in addition to add_station(). Anyway,
* there is no harm to double-check.
*/
if (TDLS_SETUP_REQUEST == tdls_validate->action_code) {
tdls_err(QDF_MAC_ADDRESS_STR " TDLS Max peer already connected. action (%d) declined. Num of peers (%d), Max allowed (%d).",
QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
tdls_validate->action_code,
tdls_soc->connected_peer_count,
tdls_soc->max_num_tdls_sta);
return -EINVAL;
}
/* maximum reached. tweak to send
* error code to peer and return error
* code to supplicant
*/
tdls_validate->status_code = QDF_STATUS_E_RESOURCES;
tdls_err(QDF_MAC_ADDRESS_STR " TDLS Max peer already connected, send response status (%d). Num of peers (%d), Max allowed (%d).",
QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
tdls_validate->action_code,
tdls_soc->connected_peer_count,
tdls_soc->max_num_tdls_sta);
tdls_validate->max_sta_failed = -EPERM;
return 0;
}
int tdls_validate_mgmt_request(struct tdls_validate_action_req *tdls_validate)
{
struct tdls_vdev_priv_obj *tdls_vdev;
struct tdls_soc_priv_obj *tdls_soc;
struct tdls_peer *curr_peer;
struct tdls_peer *temp_peer;
QDF_STATUS status;
if (!tdls_validate || !tdls_validate->vdev)
return -EINVAL;
if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(tdls_validate->vdev,
&tdls_vdev,
&tdls_soc))
return -ENOTSUPP;
/*
* STA or P2P client should be connected and authenticated before
* sending any TDLS frames
*/
if (!tdls_is_vdev_connected(tdls_validate->vdev) ||
!tdls_is_vdev_authenticated(tdls_validate->vdev)) {
tdls_err("STA is not connected or not authenticated.");
return -EAGAIN;
}
/* other than teardown frame, mgmt frames are not sent if disabled */
if (TDLS_TEARDOWN != tdls_validate->action_code) {
if (!tdls_check_is_tdls_allowed(tdls_validate->vdev)) {
tdls_err("TDLS not allowed, reject MGMT, action = %d",
tdls_validate->action_code);
return -EPERM;
}
/* if tdls_mode is disabled, then decline the peer's request */
if (TDLS_SUPPORT_DISABLED == tdls_soc->tdls_current_mode ||
TDLS_SUPPORT_SUSPENDED == tdls_soc->tdls_current_mode) {
tdls_notice(QDF_MAC_ADDRESS_STR
" TDLS mode is disabled. action %d declined.",
QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
tdls_validate->action_code);
return -ENOTSUPP;
}
if (tdls_soc->tdls_nss_switch_in_progress) {
tdls_err("nss switch in progress, action %d declined "
QDF_MAC_ADDRESS_STR,
tdls_validate->action_code,
QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac));
return -EAGAIN;
}
}
if (TDLS_IS_SETUP_ACTION(tdls_validate->action_code)) {
if (NULL != tdls_is_progress(tdls_vdev,
tdls_validate->peer_mac, true)) {
tdls_err("setup is ongoing. action %d declined for "
QDF_MAC_ADDRESS_STR,
tdls_validate->action_code,
QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac));
return -EPERM;
}
}
/*
* Discard TDLS Discovery request and setup confirm if violates
* ACM rules
*/
if ((TDLS_DISCOVERY_REQUEST == tdls_validate->action_code ||
TDLS_SETUP_CONFIRM == tdls_validate->action_code)) {
/* call hdd_wmm_is_acm_allowed() */
if (!tdls_soc->tdls_wmm_cb(&tdls_vdev->vdev)) {
tdls_err("admission ctrl set to VI, action %d declined",
tdls_validate->action_code);
return -EPERM;
}
}
if (TDLS_SETUP_REQUEST == tdls_validate->action_code ||
TDLS_SETUP_RESPONSE == tdls_validate->action_code) {
if (tdls_soc->max_num_tdls_sta <=
tdls_soc->connected_peer_count) {
status = tdls_validate_setup_frames(tdls_soc,
tdls_validate);
if (QDF_STATUS_SUCCESS != status)
return status;
/* fall through to send setup resp
* with failure status code
*/
} else {
curr_peer =
tdls_find_peer(tdls_vdev,
tdls_validate->peer_mac);
if (curr_peer) {
if (TDLS_IS_LINK_CONNECTED(curr_peer)) {
tdls_err(QDF_MAC_ADDRESS_STR " already connected action %d declined.",
QDF_MAC_ADDR_ARRAY(
tdls_validate->peer_mac),
tdls_validate->action_code);
return -EPERM;
}
}
}
}
tdls_notice("tdls_mgmt" QDF_MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %zu",
QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
tdls_validate->action_code, tdls_validate->dialog_token,
tdls_validate->status_code, tdls_validate->len);
/*Except teardown responder will not be used so just make 0 */
tdls_validate->responder = 0;
if (TDLS_TEARDOWN == tdls_validate->action_code) {
temp_peer = tdls_find_peer(tdls_vdev, tdls_validate->peer_mac);
if (!temp_peer) {
tdls_err(QDF_MAC_ADDRESS_STR " peer doesn't exist",
QDF_MAC_ADDR_ARRAY(
tdls_validate->peer_mac));
return -EPERM;
}
if (TDLS_IS_LINK_CONNECTED(temp_peer))
tdls_validate->responder = temp_peer->is_responder;
else {
tdls_err(QDF_MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, tdls_validate->len = %zu",
QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
temp_peer->link_status,
tdls_validate->dialog_token,
tdls_validate->status_code,
tdls_validate->len);
return -EPERM;
}
}
/* For explicit trigger of DIS_REQ come out of BMPS for
* successfully receiving DIS_RSP from peer.
*/
if ((TDLS_SETUP_RESPONSE == tdls_validate->action_code) ||
(TDLS_SETUP_CONFIRM == tdls_validate->action_code) ||
(TDLS_DISCOVERY_RESPONSE == tdls_validate->action_code) ||
(TDLS_DISCOVERY_REQUEST == tdls_validate->action_code)) {
/* Fw will take care if PS offload is enabled. */
if (TDLS_DISCOVERY_REQUEST != tdls_validate->action_code)
tdls_set_cap(tdls_vdev, tdls_validate->peer_mac,
TDLS_CAP_SUPPORTED);
}
return 0;
}
QDF_STATUS tdls_process_add_peer(struct tdls_add_peer_request *req)
{
struct wlan_serialization_command cmd = {0,};
@ -1000,6 +1238,105 @@ error:
return status;
}
/**
* tdls_process_send_mgmt_rsp() - handle response for send mgmt
* @rsp: TDLS send mgmt response
*
* Return: QDF_STATUS_SUCCESS for success; other values if failed
*/
QDF_STATUS tdls_process_send_mgmt_rsp(struct tdls_send_mgmt_rsp *rsp)
{
struct wlan_objmgr_vdev *vdev;
struct wlan_objmgr_psoc *psoc;
struct tdls_vdev_priv_obj *tdls_vdev;
struct tdls_soc_priv_obj *tdls_soc = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct tdls_osif_indication ind;
psoc = rsp->psoc;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, rsp->session_id,
WLAN_TDLS_SB_ID);
if (!vdev) {
tdls_err("invalid vdev");
status = QDF_STATUS_E_INVAL;
qdf_mem_free(rsp);
return status;
}
tdls_soc = wlan_psoc_get_tdls_soc_obj(psoc);
tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
if (!tdls_soc || !tdls_vdev) {
tdls_err("soc object:%p, vdev object:%p", tdls_soc, tdls_vdev);
status = QDF_STATUS_E_FAILURE;
}
tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_SEND_MGMT);
if (legacy_result_success == rsp->status_code)
goto free_rsp;
tdls_err("send mgmt failed. status code(=%d)", rsp->status_code);
status = QDF_STATUS_E_FAILURE;
if (tdls_soc && tdls_soc->tdls_event_cb) {
ind.vdev = vdev;
ind.status = rsp->status_code;
tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data,
TDLS_EVENT_MGMT_TX_ACK_CNF, &ind);
}
free_rsp:
qdf_mem_free(rsp);
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
return status;
}
/**
* tdls_send_mgmt_tx_completion() - process tx completion
* @tx_complete: TDLS mgmt completion info
*
* Return: QDF_STATUS_SUCCESS for success; other values if failed
*/
QDF_STATUS tdls_send_mgmt_tx_completion(
struct tdls_mgmt_tx_completion_ind *tx_complete)
{
struct wlan_objmgr_vdev *vdev;
struct wlan_objmgr_psoc *psoc;
struct tdls_vdev_priv_obj *tdls_vdev;
struct tdls_soc_priv_obj *tdls_soc = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct tdls_osif_indication ind;
psoc = tx_complete->psoc;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
tx_complete->session_id,
WLAN_TDLS_SB_ID);
if (!vdev) {
tdls_err("invalid vdev");
status = QDF_STATUS_E_INVAL;
goto free_tx_complete;
}
tdls_soc = wlan_psoc_get_tdls_soc_obj(psoc);
tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
if (!tdls_soc || !tdls_vdev) {
tdls_err("soc object:%p, vdev object:%p", tdls_soc, tdls_vdev);
status = QDF_STATUS_E_FAILURE;
}
if (tdls_soc && tdls_soc->tdls_event_cb) {
ind.vdev = vdev;
ind.status = tx_complete->tx_complete_status;
tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data,
TDLS_EVENT_MGMT_TX_ACK_CNF, &ind);
}
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
free_tx_complete:
qdf_mem_free(tx_complete);
return status;
}
/**
* tdls_add_peer_rsp() - handle response for add TDLS peer
* @rsp: TDLS add peer response
@ -1139,10 +1476,12 @@ QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp)
tdls_debug(QDF_MAC_ADDRESS_STR " status is %d",
QDF_MAC_ADDR_ARRAY(macaddr),
curr_peer->link_status);
wlan_vdev_obj_lock(vdev);
id = wlan_vdev_get_id(vdev);
wlan_vdev_obj_unlock(vdev);
if (TDLS_IS_CONNECTED(curr_peer)) {
if (TDLS_IS_LINK_CONNECTED(curr_peer)) {
soc_obj->tdls_dereg_tl_peer(
soc_obj->tdls_tl_peer_data,
id, curr_peer->sta_id);
@ -1464,6 +1803,10 @@ static QDF_STATUS tdls_config_force_peer(
tdls_set_callback(peer, req->callback);
tdls_set_ct_mode(soc_obj->soc);
if (soc_obj->enable_tdls_connection_tracker)
tdls_implicit_enable(vdev_obj);
return status;
error:
qdf_mem_free(peer_update_param);
@ -1605,8 +1948,10 @@ QDF_STATUS tdls_process_remove_force_peer(struct tdls_oper_request *req)
qdf_mem_free(peer_update_param);
goto error;
}
tdls_set_ct_mode(soc_obj->soc);
if (!soc_obj->enable_tdls_connection_tracker)
tdls_implicit_disable(vdev_obj);
/*TODO set tdls connection tracker state*/
error:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
qdf_mem_free(req);

View file

@ -25,6 +25,11 @@
#ifndef _WLAN_TDLS_CMDS_PROCESS_H_
#define _WLAN_TDLS_CMDS_PROCESS_H_
#define TDLS_IS_SETUP_ACTION(action) \
((TDLS_SETUP_REQUEST <= action) && \
(TDLS_SETUP_CONFIRM >= action))
/**
* enum tdls_add_oper - add peer type
* @TDLS_OPER_NONE: none
@ -37,6 +42,53 @@ enum tdls_add_oper {
TDLS_OPER_UPDATE
};
/**
* enum legacy_result_code - defined to comply with tSirResultCodes, need refine
* when mlme converged.
* @legacy_result_success: success
* @legacy_result_max: max result value
*/
enum legacy_result_code {
legacy_result_success,
legacy_result_max = 0x7FFFFFFF
};
/**
* struct tdls_send_mgmt_rsp - TDLS Response struct PE --> TDLS module
* same as struct tSirSmeRsp
* @message_type: message type eWNI_SME_TDLS_SEND_MGMT_RSP
* @length: message length
* @session_id: session id
* @transaction_id: transaction id
* @status_code: status code as tSirResultCodes
* @psoc: soc object
*/
struct tdls_send_mgmt_rsp {
uint16_t message_type;
uint16_t length;
uint8_t session_id;
uint16_t transaction_id;
enum legacy_result_code status_code;
struct wlan_objmgr_psoc *psoc;
};
/**
* struct tdls_mgmt_tx_completion_ind - TDLS TX completion PE --> TDLS module
* same as struct sSirMgmtTxCompletionInd
* @message_type: message type eWNI_SME_MGMT_FRM_TX_COMPLETION_IND
* @length: message length
* @session_id: session id
* @tx_complete_status: tx complete status
* @psoc: soc object
*/
struct tdls_mgmt_tx_completion_ind {
uint16_t message_type;
uint16_t length;
uint8_t session_id; /* Session ID */
uint32_t tx_complete_status;
struct wlan_objmgr_psoc *psoc;
};
/**
* struct tdls_add_sta_req - TDLS request struct TDLS module --> PE
* same as struct tSirTdlsAddStaReq;
@ -213,6 +265,52 @@ QDF_STATUS tdls_pe_del_peer(struct tdls_del_peer_request *req);
*/
QDF_STATUS tdls_process_add_peer_rsp(struct tdls_add_sta_rsp *rsp);
/**
* tdls_reset_nss() - reset tdls nss parameters
* @tdls_soc: TDLS soc object
* @action_code: action code
*
* Return: None
*/
void tdls_reset_nss(struct tdls_soc_priv_obj *tdls_soc,
uint8_t action_code);
/**
* tdls_set_cap() - set TDLS capability type
* @tdls_vdev: tdls vdev object
* @mac: peer mac address
* @cap: TDLS capability type
*
* Return: 0 if successful or negative errno otherwise
*/
int tdls_set_cap(struct tdls_vdev_priv_obj *tdls_vdev, const uint8_t *mac,
enum tdls_peer_capab cap);
/**
* tdls_validate_mgmt_request() -validate mgmt request
* @tdls_validate: action frame request
*
* Return: 0 for success or -EINVAL otherwise
*/
int tdls_validate_mgmt_request(struct tdls_validate_action_req *tdls_validate);
/**
* tdls_process_send_mgmt_rsp() - handle response for send mgmt
* @rsp: TDLS send mgmt response
*
* Return: QDF_STATUS_SUCCESS for success; other values if failed
*/
QDF_STATUS tdls_process_send_mgmt_rsp(struct tdls_send_mgmt_rsp *rsp);
/**
* tdls_send_mgmt_tx_completion() - process tx completion
* @tx_complete: TDLS mgmt completion info
*
* Return: QDF_STATUS_SUCCESS for success; other values if failed
*/
QDF_STATUS tdls_send_mgmt_tx_completion(
struct tdls_mgmt_tx_completion_ind *tx_complete);
/**
* tdls_process_add_peer_rsp() - handle response for delete TDLS peer
* @rsp: TDLS delete peer response

View file

@ -52,6 +52,27 @@ bool tdls_is_vdev_connected(struct wlan_objmgr_vdev *vdev)
return true;
}
bool tdls_is_vdev_authenticated(struct wlan_objmgr_vdev *vdev)
{
struct wlan_objmgr_peer *peer;
bool is_authenticated = false;
wlan_vdev_obj_lock(vdev);
peer = wlan_vdev_get_bsspeer(vdev);
wlan_vdev_obj_unlock(vdev);
if (!peer) {
tdls_err("peer is null");
return false;
}
wlan_peer_obj_lock(peer);
is_authenticated = wlan_peer_mlme_get_auth_state(peer);
wlan_peer_obj_unlock(peer);
return is_authenticated;
}
/**
* tdls_peer_reset_discovery_processed() - reset discovery status
* @tdls_vdev: TDLS vdev object

View file

@ -155,4 +155,21 @@ void tdls_discovery_timeout_peer_cb(void *user_data);
* Return: Void
*/
void tdls_implicit_disable(struct tdls_vdev_priv_obj *tdls_vdev);
/**
* tdls_is_vdev_connected() -check the vdev connection
* @vdev: vdev oobject
*
* Return: true or false
*/
bool tdls_is_vdev_connected(struct wlan_objmgr_vdev *vdev);
/**
* tdls_is_vdev_authenticated() -check the vdev authentication state
* @vdev: vdev oobject
*
* Return: true or false
*/
bool tdls_is_vdev_authenticated(struct wlan_objmgr_vdev *vdev);
#endif

View file

@ -30,6 +30,8 @@
#include "wlan_tdls_tgt_api.h"
#include "wlan_policy_mgr_public_struct.h"
#include "wlan_policy_mgr_api.h"
#include "wlan_scan_ucfg_api.h"
/* Global tdls soc pvt object
* this is useful for some functions which does not receive either vdev or psoc

View file

@ -34,6 +34,7 @@
#include <wlan_tdls_public_structs.h>
#include <scheduler_api.h>
#include "wlan_serialization_api.h"
#include "wlan_tdls_mgmt.h"
/* Bit mask flag for tdls_option to FW */
#define ENA_TDLS_OFFCHAN (1 << 0) /* TDLS Off Channel support */
@ -74,7 +75,7 @@
#define tdls_alert(format, args...) \
tdls_logfl(QDF_TRACE_LEVEL_FATAL, format, ## args)
#define TDLS_IS_CONNECTED(peer) \
#define TDLS_IS_LINK_CONNECTED(peer) \
((TDLS_LINK_CONNECTED == (peer)->link_status) || \
(TDLS_LINK_TEARING == (peer)->link_status))
@ -203,6 +204,10 @@ struct tdls_soc_priv_obj {
enum tdls_nss_transition_state tdls_nss_transition_mode;
int32_t tdls_teardown_peers_cnt;
struct tdls_set_state_info set_state_info;
tdls_rx_callback tdls_rx_cb;
void *tdls_rx_cb_data;
tdls_wmm_check tdls_wmm_cb;
void *tdls_wmm_cb_data;
tdls_tx_ack_cnf_callback tdls_tx_cnf_cb;
void *tx_ack_cnf_cb_data;
tdls_evt_callback tdls_event_cb;

View file

@ -113,7 +113,6 @@ static QDF_STATUS tdls_process_rx_mgmt(
tdls_set_rssi(tdls_vdev, mac, rx_mgmt->rx_rssi);
}
if (rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET] ==
TDLS_ACTION_FRAME) {
action_frame_type =
@ -127,7 +126,7 @@ static QDF_STATUS tdls_process_rx_mgmt(
}
}
/* tdls_soc_obj->tdls_rx_cb ==> wlan_tdls_rx_callback() */
/* tdls_soc_obj->tdls_rx_cb ==> wlan_cfg80211_tdls_rx_callback() */
if (tdls_soc_obj && tdls_soc_obj->tdls_rx_cb)
tdls_soc_obj->tdls_rx_cb(tdls_soc_obj->tdls_rx_cb_data,
rx_mgmt);
@ -157,7 +156,6 @@ QDF_STATUS tdls_process_rx_frame(struct scheduler_msg *msg)
if (vdev) {
tdls_debug("tdls rx mgmt frame received");
tdls_vdev = wlan_objmgr_vdev_get_comp_private_obj(vdev,
WLAN_UMAC_COMP_TDLS);
if (tdls_vdev)
@ -175,6 +173,7 @@ QDF_STATUS tdls_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
bool isregister)
{
struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info[3];
QDF_STATUS status;
int num_of_entries;

View file

@ -28,6 +28,24 @@
/* default tdls serialize timeout is set to 10 secs */
#define TDLS_DEFAULT_SERIALIZE_CMD_TIMEOUT 10000
#define TDLS_PUBLIC_ACTION_FRAME_OFFSET 24
#define TDLS_PUBLIC_ACTION_FRAME 4
#define TDLS_PUBLIC_ACTION_DISC_RESP 14
#define TDLS_ACTION_FRAME 12
#define TDLS_80211_PEER_ADDR_OFFSET (TDLS_PUBLIC_ACTION_FRAME + \
QDF_MAC_ADDR_SIZE)
#define TDLS_ACTION_FRAME_TYPE_MAX 11
/**
* struct tdls_rx_mgmt_event - tdls rx mgmt frame event
* @tdls_soc_obj: tdls soc private object
* @rx_mgmt: tdls rx mgmt frame structure
*/
struct tdls_rx_mgmt_event {
struct tdls_soc_priv_obj *tdls_soc_obj;
struct tdls_rx_mgmt_frame *rx_mgmt;
};
/*
* struct tdls_send_mgmt_request - tdls management request
* @message_type: type of pe message
@ -70,5 +88,26 @@ struct tdls_send_mgmt_request {
*/
QDF_STATUS tdls_process_mgmt_req(
struct tdls_action_frame_request *tdls_mgmt_req);
/**
* tdls_mgmt_rx_ops() - register or unregister rx callback
* @psoc: psoc object
* @isregister: register if true, unregister if false
*
* This function registers or unregisters rx callback to mgmt txrx
* component.
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
bool isregister);
/**
* tdls_process_rx_frame() - process tdls rx frames
* @msg: scheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_process_rx_frame(struct scheduler_msg *msg);
#endif

View file

@ -29,6 +29,8 @@
#include <qdf_mc_timer.h>
#include <wlan_cmn.h>
#include <wlan_cmn_ieee80211.h>
#include <wlan_objmgr_psoc_obj.h>
#define WLAN_TDLS_STA_MAX_NUM 8
#define WLAN_TDLS_STA_P_UAPSD_OFFCHAN_MAX_NUM 1
@ -59,7 +61,7 @@
#define WAIT_TIME_TDLS_LINK_ESTABLISH_REQ 1500
/** Maximum time(ms) to wait for tdls mgmt to complete **/
#define WAIT_TIME_TDLS_MGMT 11000
#define WAIT_TIME_FOR_TDLS_MGMT 11000
#define TDLS_TEARDOWN_PEER_UNREACHABLE 25
#define TDLS_TEARDOWN_PEER_UNSPEC_REASON 26
@ -252,7 +254,7 @@ enum tdls_event_msg_type {
TDLS_SHOULD_DISCOVER = 0,
TDLS_SHOULD_TEARDOWN,
TDLS_PEER_DISCONNECTED,
TDLS_CONNECTION_TRACKER_NOTIFY,
TDLS_CONNECTION_TRACKER_NOTIFY
};
/**

View file

@ -67,6 +67,22 @@ QDF_STATUS tgt_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
QDF_STATUS tgt_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc,
struct sta_uapsd_trig_params *params);
/**
* tgt_tdls_send_mgmt_rsp() - process tdls mgmt response
* @pmsg: sheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_send_mgmt_rsp(struct scheduler_msg *pmsg);
/**
* tgt_tdls_send_mgmt_tx_completion() -process tx completion message
* @pmsg: sheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_send_mgmt_tx_completion(struct scheduler_msg *pmsg);
/**
* tgt_tdls_del_peer_rsp() - handle TDLS del peer response
* @pmsg: sheduler msg
@ -111,4 +127,23 @@ QDF_STATUS tgt_tdls_unregister_ev_handler(struct wlan_objmgr_psoc *psoc);
QDF_STATUS
tgt_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
struct tdls_event_info *info);
/**
* tgt_tdls_mgmt_frame_rx_cb() - callback for rx mgmt frame
* @psoc: soc context
* @peer: peer context
* @buf: rx buffer
* @mgmt_rx_params: mgmt rx parameters
* @frm_type: frame type
*
* This function gets called from mgmt tx/rx component when rx mgmt
* received.
*
* Return: QDF_STATUS_SUCCESS
*/
QDF_STATUS tgt_tdls_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_peer *peer, qdf_nbuf_t buf,
struct mgmt_rx_event_params *mgmt_rx_params,
enum mgmt_frame_type frm_type);
#endif

View file

@ -87,6 +87,36 @@ QDF_STATUS tgt_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tgt_tdls_send_mgmt_tx_completion(struct scheduler_msg *pmsg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!pmsg || !pmsg->bodyptr) {
tdls_err("msg: 0x%p", pmsg);
QDF_ASSERT(0);
return QDF_STATUS_E_NULL_VALUE;
}
status = tdls_send_mgmt_tx_completion(pmsg->bodyptr);
return status;
}
QDF_STATUS tgt_tdls_send_mgmt_rsp(struct scheduler_msg *pmsg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!pmsg || !pmsg->bodyptr) {
tdls_err("msg: 0x%p", pmsg);
QDF_ASSERT(0);
return QDF_STATUS_E_NULL_VALUE;
}
status = tdls_process_send_mgmt_rsp(pmsg->bodyptr);
return status;
}
QDF_STATUS tgt_tdls_add_peer_rsp(struct scheduler_msg *pmsg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
@ -183,3 +213,124 @@ tgt_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
return status;
}
static
QDF_STATUS tgt_tdls_mgmt_frame_process_rx_cb(
struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_peer *peer,
qdf_nbuf_t buf,
struct mgmt_rx_event_params *mgmt_rx_params,
enum mgmt_frame_type frm_type)
{
struct tdls_rx_mgmt_frame *rx_mgmt;
struct tdls_rx_mgmt_event *rx_mgmt_event;
struct tdls_soc_priv_obj *tdls_soc_obj;
struct scheduler_msg msg;
struct wlan_objmgr_vdev *vdev;
uint32_t vdev_id;
uint8_t *pdata;
QDF_STATUS status;
tdls_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_TDLS);
if (!tdls_soc_obj) {
tdls_err("tdls ctx is NULL, drop this frame");
return QDF_STATUS_E_FAILURE;
}
if (!peer) {
vdev = tdls_get_vdev(psoc, WLAN_TDLS_SB_ID);
if (!vdev) {
tdls_err("current tdls vdev is null, can't get vdev id");
return QDF_STATUS_E_FAILURE;
}
wlan_vdev_obj_lock(vdev);
vdev_id = wlan_vdev_get_id(vdev);
wlan_vdev_obj_unlock(vdev);
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
} else {
wlan_peer_obj_lock(peer);
vdev = wlan_peer_get_vdev(peer);
wlan_peer_obj_unlock(peer);
if (!vdev) {
tdls_err("vdev is NULL in peer, drop this frame");
return QDF_STATUS_E_FAILURE;
}
wlan_vdev_obj_lock(vdev);
vdev_id = wlan_vdev_get_id(vdev);
wlan_vdev_obj_unlock(vdev);
}
rx_mgmt_event = qdf_mem_malloc(sizeof(*rx_mgmt_event));
if (!rx_mgmt_event) {
tdls_err("Failed to allocate rx mgmt event");
return QDF_STATUS_E_NOMEM;
}
rx_mgmt = qdf_mem_malloc(sizeof(*rx_mgmt) +
mgmt_rx_params->buf_len);
if (!rx_mgmt) {
tdls_err("Failed to allocate rx mgmt frame");
qdf_mem_free(rx_mgmt_event);
return QDF_STATUS_E_NOMEM;
}
pdata = (uint8_t *)qdf_nbuf_data(buf);
rx_mgmt->frame_len = mgmt_rx_params->buf_len;
rx_mgmt->rx_chan = mgmt_rx_params->channel;
rx_mgmt->vdev_id = vdev_id;
rx_mgmt->frm_type = frm_type;
rx_mgmt->rx_rssi = mgmt_rx_params->rssi;
rx_mgmt_event->rx_mgmt = rx_mgmt;
rx_mgmt_event->tdls_soc_obj = tdls_soc_obj;
qdf_mem_copy(rx_mgmt->buf, pdata, mgmt_rx_params->buf_len);
msg.type = TDLS_EVENT_RX_MGMT;
msg.bodyptr = rx_mgmt_event;
msg.callback = tdls_process_rx_frame;
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
qdf_nbuf_free(buf);
return status;
}
QDF_STATUS tgt_tdls_mgmt_frame_rx_cb(
struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_peer *peer,
qdf_nbuf_t buf,
struct mgmt_rx_event_params *mgmt_rx_params,
enum mgmt_frame_type frm_type)
{
QDF_STATUS status;
tdls_debug("psoc:%p, peer:%p, type:%d", psoc, peer, frm_type);
if (!buf) {
tdls_err("rx frame buff is null buf:%p", buf);
return QDF_STATUS_E_INVAL;
}
if (!mgmt_rx_params || !psoc) {
tdls_err("input is NULL mgmt_rx_params:%p psoc:%p, peer:%p",
mgmt_rx_params, psoc, peer);
status = QDF_STATUS_E_INVAL;
goto release_nbuf;
}
status = wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_SB_ID);
if (QDF_STATUS_SUCCESS != status)
goto release_nbuf;
status = tgt_tdls_mgmt_frame_process_rx_cb(psoc, peer, buf,
mgmt_rx_params, frm_type);
wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
if (QDF_STATUS_SUCCESS != status)
release_nbuf:
qdf_nbuf_free(buf);
return status;
}

View file

@ -194,6 +194,12 @@ QDF_STATUS ucfg_tdls_update_config(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_E_FAILURE;
}
soc_obj->tdls_rx_cb = req->tdls_rx_cb;
soc_obj->tdls_rx_cb_data = req->tdls_rx_cb_data;
soc_obj->tdls_wmm_cb = req->tdls_wmm_cb;
soc_obj->tdls_wmm_cb_data = req->tdls_wmm_cb_data;
soc_obj->tdls_event_cb = req->tdls_event_cb;
soc_obj->tdls_evt_cb_data = req->tdls_evt_cb_data;
@ -256,9 +262,14 @@ QDF_STATUS ucfg_tdls_psoc_enable(struct wlan_objmgr_psoc *psoc)
tdls_scan_serialization_comp_info_cb);
if (QDF_STATUS_SUCCESS != status) {
tdls_err("Serialize scan cmd register failed ");
status = QDF_STATUS_E_FAILURE;
return status;
}
/* register callbacks with tx/rx mgmt */
status = tdls_mgmt_rx_ops(psoc, true);
if (status != QDF_STATUS_SUCCESS)
tdls_err("Failed to register mgmt rx callback, status:%d",
status);
return status;
}
@ -647,4 +658,6 @@ void ucfg_tdls_update_tx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
tdls_update_tx_pkt_cnt(vdev, mac_addr);
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
}