diff --git a/umac/tdls/core/src/wlan_tdls_cmds_process.c b/umac/tdls/core/src/wlan_tdls_cmds_process.c index 8570484c2de4..90805709fc6a 100644 --- a/umac/tdls/core/src/wlan_tdls_cmds_process.c +++ b/umac/tdls/core/src/wlan_tdls_cmds_process.c @@ -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; +} diff --git a/umac/tdls/core/src/wlan_tdls_cmds_process.h b/umac/tdls/core/src/wlan_tdls_cmds_process.h index 938e96671608..da14cfa6ab9f 100644 --- a/umac/tdls/core/src/wlan_tdls_cmds_process.h +++ b/umac/tdls/core/src/wlan_tdls_cmds_process.h @@ -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 diff --git a/umac/tdls/core/src/wlan_tdls_ct.c b/umac/tdls/core/src/wlan_tdls_ct.c index b3f28a458648..4e0b4cdbb531 100644 --- a/umac/tdls/core/src/wlan_tdls_ct.c +++ b/umac/tdls/core/src/wlan_tdls_ct.c @@ -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; diff --git a/umac/tdls/core/src/wlan_tdls_ct.h b/umac/tdls/core/src/wlan_tdls_ct.h index 04926b9bba33..6c8dbf680f04 100644 --- a/umac/tdls/core/src/wlan_tdls_ct.h +++ b/umac/tdls/core/src/wlan_tdls_ct.h @@ -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 diff --git a/umac/tdls/core/src/wlan_tdls_main.c b/umac/tdls/core/src/wlan_tdls_main.c index d9bb025e1d04..66ebc7edb56e 100644 --- a/umac/tdls/core/src/wlan_tdls_main.c +++ b/umac/tdls/core/src/wlan_tdls_main.c @@ -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; } diff --git a/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h b/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h index c8dd05f53ecc..3ecf2dfd26d9 100644 --- a/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h +++ b/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h @@ -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 diff --git a/umac/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h b/umac/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h index 1135c48e2dec..3d6570772c64 100644 --- a/umac/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h +++ b/umac/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h @@ -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 diff --git a/umac/tdls/dispatcher/src/wlan_tdls_ucfg_api.c b/umac/tdls/dispatcher/src/wlan_tdls_ucfg_api.c index 4d0c64bcc459..5b76f0e80afb 100644 --- a/umac/tdls/dispatcher/src/wlan_tdls_ucfg_api.c +++ b/umac/tdls/dispatcher/src/wlan_tdls_ucfg_api.c @@ -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; +}