qcacmn: Configure the tdls offchannel params through IOCTL

Add support to configure tdls offchannel params
through IOCTL commands.

Change-Id: I90ba90b5ef980f837ce4759755efe190672ad911
CRs-Fixed: 2309185
This commit is contained in:
Bala Venkatesh 2018-08-30 15:28:14 +05:30 • committed by nshrivas
commit f0c03be151
8 changed files with 355 additions and 33 deletions

View file

@ -2334,3 +2334,83 @@ QDF_STATUS tdls_antenna_switch_flush_callback(struct scheduler_msg *msg)
return QDF_STATUS_SUCCESS;
}
void wlan_tdls_offchan_parms_callback(struct wlan_objmgr_vdev *vdev)
{
if (!vdev) {
tdls_err("vdev is NULL");
return;
}
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
}
int tdls_process_set_offchannel(struct tdls_set_offchannel *req)
{
int status;
struct tdls_vdev_priv_obj *tdls_vdev_obj;
struct tdls_soc_priv_obj *tdls_soc_obj;
if (tdls_get_vdev_objects(req->vdev, &tdls_vdev_obj, &tdls_soc_obj) !=
QDF_STATUS_SUCCESS) {
status = -ENOTSUPP;
goto free;
}
tdls_debug("TDLS offchannel to be configured %d", req->offchannel);
if (req->offchannel)
status = tdls_set_tdls_offchannel(tdls_soc_obj,
req->offchannel);
else
status = -ENOTSUPP;
free:
if (req->callback)
req->callback(req->vdev);
qdf_mem_free(req);
return status;
}
int tdls_process_set_offchan_mode(struct tdls_set_offchanmode *req)
{
int status;
tdls_debug("TDLS offchan mode to be configured %d", req->offchan_mode);
status = tdls_set_tdls_offchannelmode(req->vdev, req->offchan_mode);
if (req->callback)
req->callback(req->vdev);
qdf_mem_free(req);
return status;
}
int tdls_process_set_secoffchanneloffset(
struct tdls_set_secoffchanneloffset *req)
{
int status;
struct tdls_vdev_priv_obj *tdls_vdev_obj;
struct tdls_soc_priv_obj *tdls_soc_obj;
if (tdls_get_vdev_objects(req->vdev, &tdls_vdev_obj, &tdls_soc_obj) !=
QDF_STATUS_SUCCESS) {
status = -ENOTSUPP;
goto free;
}
tdls_debug("TDLS offchannel offset to be configured %d",
req->offchan_offset);
status = tdls_set_tdls_secoffchanneloffset(tdls_soc_obj,
req->offchan_offset);
free:
if (req->callback)
req->callback(req->vdev);
qdf_mem_free(req);
return status;
}

View file

@ -383,4 +383,38 @@ int tdls_set_responder(struct tdls_set_responder_req *set_req);
*/
void tdls_decrement_peer_count(struct tdls_soc_priv_obj *soc_obj);
/**
* wlan_tdls_offchan_parms_callback() - Callback to release ref count
* @vdev: vdev object
*
* Return: none
*/
void wlan_tdls_offchan_parms_callback(struct wlan_objmgr_vdev *vdev);
/**
* tdls_process_set_offchannel() - Handle set offchannel request for TDLS
* @req: TDLS set offchannel request
*
* Return: int status
*/
int tdls_process_set_offchannel(struct tdls_set_offchannel *req);
/**
* tdls_process_set_offchan_mode() - Handle set offchan mode request for TDLS
* @req: TDLS set offchannel mode request
*
* Return: int status
*/
int tdls_process_set_offchan_mode(struct tdls_set_offchanmode *req);
/**
* tdls_process_set_secoffchanneloffset() - Handle set sec offchannel
* offset request for TDLS
* @req: TDLS set secoffchannel offchannel request
*
* Return: int status
*/
int tdls_process_set_secoffchanneloffset(
struct tdls_set_secoffchanneloffset *req);
#endif

View file

@ -936,16 +936,6 @@ void tdls_ct_handler(void *user_data)
WLAN_TDLS_NB_ID);
}
/**
* tdls_set_tdls_offchannel() - set tdls off-channel number
* @tdls_soc: tdls soc object
* @offchanmode: tdls off-channel number
*
* This function sets tdls off-channel number
*
* Return: 0 on success; negative errno otherwise
*/
static
int tdls_set_tdls_offchannel(struct tdls_soc_priv_obj *tdls_soc,
int offchannel)
{
@ -964,7 +954,7 @@ int tdls_set_tdls_offchannel(struct tdls_soc_priv_obj *tdls_soc,
}
} else {
tdls_err("Either TDLS or TDLS Off-channel is not enabled");
return -ENOTSUPP;
return -ENOTSUPP;
}
tdls_notice("change tdls off channel from %d to %d",
tdls_soc->tdls_off_channel, offchannel);
@ -972,16 +962,6 @@ int tdls_set_tdls_offchannel(struct tdls_soc_priv_obj *tdls_soc,
return 0;
}
/**
* tdls_set_tdls_secoffchanneloffset() - set secondary tdls off-channel offset
* @tdls_soc: tdls soc object
* @offchanmode: tdls off-channel offset
*
* This function sets 2nd tdls off-channel offset
*
* Return: 0 on success; negative errno otherwise
*/
static
int tdls_set_tdls_secoffchanneloffset(struct tdls_soc_priv_obj *tdls_soc,
int offchanoffset)
{
@ -1022,16 +1002,6 @@ int tdls_set_tdls_secoffchanneloffset(struct tdls_soc_priv_obj *tdls_soc,
return 0;
}
/**
* tdls_set_tdls_offchannelmode() - set tdls off-channel mode
* @adapter: Pointer to the HDD adapter
* @offchanmode: tdls off-channel mode
*
* This function sets tdls off-channel mode
*
* Return: 0 on success; negative errno otherwise
*/
static
int tdls_set_tdls_offchannelmode(struct wlan_objmgr_vdev *vdev,
int offchanmode)
{
@ -1056,7 +1026,7 @@ int tdls_set_tdls_offchannelmode(struct wlan_objmgr_vdev *vdev,
return -EINVAL;
}
if (tdls_is_vdev_connected(vdev)) {
if (!tdls_is_vdev_connected(vdev)) {
tdls_err("tdls off channel req in not associated state %d",
offchanmode);
return -EPERM;

View file

@ -206,4 +206,42 @@ void tdls_disable_offchan_and_teardown_links(
QDF_STATUS tdls_delete_all_tdls_peers(struct wlan_objmgr_vdev *vdev,
struct tdls_soc_priv_obj *tdls_soc);
/**
* tdls_set_tdls_offchannel() - set tdls off-channel number
* @tdls_soc: tdls soc object
* @offchanmode: tdls off-channel number
*
* This function sets tdls off-channel number
*
* Return: 0 on success; negative errno otherwise
*/
int tdls_set_tdls_offchannel(struct tdls_soc_priv_obj *tdls_soc,
int offchannel);
/**
* tdls_set_tdls_offchannelmode() - set tdls off-channel mode
* @adapter: Pointer to the HDD adapter
* @offchannel: tdls off-channel mode
*
* This function sets tdls off-channel mode
*
* Return: 0 on success; negative errno otherwise
*/
int tdls_set_tdls_offchannelmode(struct wlan_objmgr_vdev *vdev,
int offchanmode);
/**
* tdls_set_tdls_secoffchanneloffset() - set secondary tdls off-channel offset
* @tdls_soc: tdls soc object
* @offchanoffset: tdls off-channel offset
*
* This function sets secondary tdls off-channel offset
*
* Return: 0 on success; negative errno otherwise
*/
int tdls_set_tdls_secoffchanneloffset(struct tdls_soc_priv_obj *tdls_soc,
int offchanoffset);
#endif

View file

@ -322,6 +322,15 @@ QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
case TDLS_CMD_GET_ALL_PEERS:
tdls_get_all_peers_from_list(msg->bodyptr);
break;
case TDLS_CMD_SET_OFFCHANNEL:
tdls_process_set_offchannel(msg->bodyptr);
break;
case TDLS_CMD_SET_OFFCHANMODE:
tdls_process_set_offchan_mode(msg->bodyptr);
break;
case TDLS_CMD_SET_SECOFFCHANOFFSET:
tdls_process_set_secoffchanneloffset(msg->bodyptr);
break;
default:
break;
}

View file

@ -190,6 +190,9 @@ enum tdls_feature_mode {
* @TDLS_NOTIFY_RESET_ADAPTERS: notify adapter reset
* @TDLS_CMD_GET_ALL_PEERS: get all the tdls peers from the list
* @TDLS_CMD_ANTENNA_SWITCH: dynamic tdls antenna switch
* @TDLS_CMD_SET_OFFCHANNEL: tdls offchannel
* @TDLS_CMD_SET_OFFCHANMODE: tdls offchannel mode
* @TDLS_CMD_SET_SECOFFCHANOFFSET: tdls secondary offchannel offset
*/
enum tdls_command_type {
TDLS_CMD_TX_ACTION = 1,
@ -211,7 +214,10 @@ enum tdls_command_type {
TDLS_CMD_TEARDOWN_LINKS,
TDLS_NOTIFY_RESET_ADAPTERS,
TDLS_CMD_GET_ALL_PEERS,
TDLS_CMD_ANTENNA_SWITCH
TDLS_CMD_ANTENNA_SWITCH,
TDLS_CMD_SET_OFFCHANNEL,
TDLS_CMD_SET_OFFCHANMODE,
TDLS_CMD_SET_SECOFFCHANOFFSET
};
/**
@ -582,6 +588,9 @@ typedef QDF_STATUS
/* This callback is to release vdev ref for tdls sta notify msg */
typedef void (*tdls_sta_notify_callback)(struct wlan_objmgr_vdev *vdev);
/* This callback is to release vdev ref for tdls offchan param related msg */
typedef void (*tdls_offchan_parms_callback)(struct wlan_objmgr_vdev *vdev);
/**
* struct tdls_start_params - tdls start params
* @config: tdls user config
@ -1098,4 +1107,35 @@ struct tdls_antenna_switch_request {
struct wlan_objmgr_vdev *vdev;
uint32_t mode;
};
/**
* struct tdls_set_offchannel - TDLS set offchannel
* @offchannel: Updated tdls offchannel value.
*/
struct tdls_set_offchannel {
struct wlan_objmgr_vdev *vdev;
uint16_t offchannel;
tdls_offchan_parms_callback callback;
};
/**
* struct tdls_set_offchan_mode - TDLS set offchannel mode
* @offchan_mode: Updated tdls offchannel mode value.
*/
struct tdls_set_offchanmode {
struct wlan_objmgr_vdev *vdev;
uint8_t offchan_mode;
tdls_offchan_parms_callback callback;
};
/**
* struct tdls_set_offchan_offset - TDLS set offchannel mode
* @offchan_offset: Offchan offset value.
*/
struct tdls_set_secoffchanneloffset {
struct wlan_objmgr_vdev *vdev;
uint8_t offchan_offset;
tdls_offchan_parms_callback callback;
};
#endif

View file

@ -222,4 +222,33 @@ void ucfg_tdls_update_tx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
QDF_STATUS ucfg_tdls_antenna_switch(struct wlan_objmgr_vdev *vdev,
uint32_t mode);
/**
* ucfg_set_tdls_offchannel() - Handle TDLS set offchannel
* @vdev: vdev object
* @offchannel: updated offchannel
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_set_tdls_offchannel(struct wlan_objmgr_vdev *vdev,
int offchannel);
/**
* ucfg_set_tdls_offchan_mode() - Handle TDLS set offchannel mode
* @vdev: vdev object
* @offchanmode: updated off-channel mode
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_set_tdls_offchan_mode(struct wlan_objmgr_vdev *vdev,
int offchanmode);
/**
* ucfg_set_tdls_secoffchanneloffset() - Handle TDLS set offchannel offset
* @vdev: vdev object
* @offchanoffset: tdls off-channel offset
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_set_tdls_secoffchanneloffset(struct wlan_objmgr_vdev *vdev,
int offchanoffset);
#endif

View file

@ -870,3 +870,125 @@ error:
qdf_mem_free(req);
return status;
}
QDF_STATUS ucfg_set_tdls_offchannel(struct wlan_objmgr_vdev *vdev,
int offchannel)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct scheduler_msg msg = {0, };
struct tdls_set_offchannel *req;
req = qdf_mem_malloc(sizeof(*req));
if (!req) {
tdls_err("mem allocate fail");
return QDF_STATUS_E_NOMEM;
}
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("can't get vdev");
goto free;
}
req->offchannel = offchannel;
req->vdev = vdev;
req->callback = wlan_tdls_offchan_parms_callback;
msg.bodyptr = req;
msg.callback = tdls_process_cmd;
msg.type = TDLS_CMD_SET_OFFCHANNEL;
status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("post set tdls offchannel msg fail");
goto dec_ref;
}
return status;
dec_ref:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
free:
qdf_mem_free(req);
return status;
}
QDF_STATUS ucfg_set_tdls_offchan_mode(struct wlan_objmgr_vdev *vdev,
int offchanmode)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct scheduler_msg msg = {0, };
struct tdls_set_offchanmode *req;
req = qdf_mem_malloc(sizeof(*req));
if (!req) {
tdls_err("mem allocate fail");
return QDF_STATUS_E_NOMEM;
}
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("can't get vdev");
goto free;
}
req->offchan_mode = offchanmode;
req->vdev = vdev;
req->callback = wlan_tdls_offchan_parms_callback;
msg.bodyptr = req;
msg.callback = tdls_process_cmd;
msg.type = TDLS_CMD_SET_OFFCHANMODE;
status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("post set offchanmode msg fail");
goto dec_ref;
}
return status;
dec_ref:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
free:
qdf_mem_free(req);
return status;
}
QDF_STATUS ucfg_set_tdls_secoffchanneloffset(struct wlan_objmgr_vdev *vdev,
int offchanoffset)
{
int status = QDF_STATUS_SUCCESS;
struct scheduler_msg msg = {0, };
struct tdls_set_secoffchanneloffset *req;
req = qdf_mem_malloc(sizeof(*req));
if (!req) {
tdls_err("mem allocate fail");
return QDF_STATUS_E_NOMEM;
}
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("can't get vdev");
goto free;
}
req->offchan_offset = offchanoffset;
req->vdev = vdev;
req->callback = wlan_tdls_offchan_parms_callback;
msg.bodyptr = req;
msg.callback = tdls_process_cmd;
msg.type = TDLS_CMD_SET_SECOFFCHANOFFSET;
status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("post set secoffchan offset msg fail");
goto dec_ref;
}
return status;
dec_ref:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
free:
qdf_mem_free(req);
return status;
}