qcacld-3.0: Set unforce mode for link

TDLS for MLO, it forces link active when sending TDLS discovery
Request, it needs to unforce the link when:
There is no discovery response on that link; or
The remain links except the link which is TDLS link; or
The link for TDLS but no more TDLS connection.

CRs-Fixed: 3623332
Change-Id: Ie9fb0d210952531744bba397c1a34f4d8f1f14fb
This commit is contained in:
Paul Zhang
2023-09-26 19:51:17 +08:00
committed by Rahul Choudhary
parent 721acdbab2
commit 59d68775f9
8 changed files with 165 additions and 7 deletions

View File

@@ -1661,6 +1661,48 @@ QDF_STATUS tdls_process_add_peer_rsp(struct tdls_add_sta_rsp *rsp)
return QDF_STATUS_E_INVAL;
}
static void tdls_process_unforce_link_mode(struct wlan_objmgr_vdev *vdev)
{
struct tdls_vdev_priv_obj *tdls_vdev;
struct tdls_peer *peer;
qdf_list_t *head;
qdf_list_node_t *p_node;
QDF_STATUS status;
bool unforce = true;
int i;
tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
if (!tdls_vdev)
return;
for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
head = &tdls_vdev->peer_list[i];
status = qdf_list_peek_front(head, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
peer = qdf_container_of(p_node, struct tdls_peer, node);
tdls_debug("Peer: " QDF_MAC_ADDR_FMT "link status %d, vdev id %d",
QDF_MAC_ADDR_REF(peer->peer_mac.bytes),
peer->link_status, wlan_vdev_get_id(vdev));
if (peer->link_status == TDLS_LINK_CONNECTED ||
peer->link_status == TDLS_LINK_CONNECTING) {
unforce = false;
goto unforce_exit;
}
status = qdf_list_peek_next(head, p_node, &p_node);
}
}
unforce_exit:
if (unforce) {
tdls_debug("try to set vdev %d to unforce",
wlan_vdev_get_id(vdev));
tdls_set_link_unforce(vdev);
}
}
QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp)
{
uint8_t sta_idx, id;
@@ -1734,6 +1776,8 @@ QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp)
TDLS_LINK_DROPPED_BY_REMOTE);
}
tdls_process_unforce_link_mode(vdev);
cmddone:
tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_DEL_PEER);
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);

View File

@@ -97,6 +97,7 @@ void tdls_discovery_timeout_peer_cb(void *user_data)
struct wlan_objmgr_vdev *tdls_link_vdev;
struct tdls_rx_mgmt_frame *rx_mgmt;
uint8_t *mac;
bool unforce = true;
if (!user_data) {
tdls_err("discovery time out data is null");
@@ -163,6 +164,15 @@ void tdls_discovery_timeout_peer_cb(void *user_data)
while (QDF_IS_STATUS_SUCCESS(status)) {
peer = qdf_container_of(p_node, struct tdls_peer,
node);
tdls_debug("Peer: " QDF_MAC_ADDR_FMT "link status %d, vdev id %d",
QDF_MAC_ADDR_REF(peer->peer_mac.bytes),
peer->link_status, wlan_vdev_get_id(vdev));
if (peer->link_status != TDLS_LINK_DISCOVERING &&
peer->link_status != TDLS_LINK_IDLE)
unforce = false;
if (TDLS_LINK_DISCOVERING != peer->link_status) {
status = qdf_list_peek_next(head, p_node,
&p_node);
@@ -176,6 +186,12 @@ void tdls_discovery_timeout_peer_cb(void *user_data)
}
}
if (wlan_vdev_mlme_is_mlo_vdev(vdev) && unforce) {
tdls_debug("try to set vdev %d to unforce",
wlan_vdev_get_id(vdev));
tdls_set_link_unforce(vdev);
}
tdls_vdev->discovery_sent_cnt = 0;
/* add tdls power save prohibited */
@@ -1458,6 +1474,14 @@ void tdls_disable_offchan_and_teardown_links(
QDF_STATUS status;
uint8_t vdev_id;
bool tdls_in_progress = false;
bool is_mlo_vdev;
is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
if (is_mlo_vdev) {
tdls_debug("try to set vdev %d to unforce",
wlan_vdev_get_id(vdev));
tdls_set_link_unforce(vdev);
}
status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc);
if (QDF_STATUS_SUCCESS != status) {

View File

@@ -80,6 +80,7 @@ static char *tdls_get_cmd_type_str(enum tdls_command_type cmd_type)
CASE_RETURN_STRING(TDLS_CMD_SET_SECOFFCHANOFFSET);
CASE_RETURN_STRING(TDLS_DELETE_ALL_PEERS_INDICATION);
CASE_RETURN_STRING(TDLS_CMD_START_BSS);
CASE_RETURN_STRING(TDLS_CMD_SET_LINK_UNFORCE);
default:
return "Invalid TDLS command";
}
@@ -582,6 +583,17 @@ QDF_STATUS tdls_handle_start_bss(struct wlan_objmgr_psoc *psoc)
}
#endif
static void tdls_handle_link_unforce(struct wlan_objmgr_vdev *vdev)
{
struct tdls_action_frame_request req = {0};
req.vdev = vdev;
req.tdls_mgmt.frame_type = TDLS_MAX_ACTION_CODE;
tdls_debug("set vdev %d unforce", wlan_vdev_get_id(vdev));
tdls_set_link_mode(&req);
}
QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -668,6 +680,9 @@ QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
case TDLS_CMD_START_BSS:
tdls_handle_start_bss(msg->bodyptr);
break;
case TDLS_CMD_SET_LINK_UNFORCE:
tdls_handle_link_unforce(msg->bodyptr);
break;
default:
break;
}
@@ -2039,6 +2054,21 @@ void tdls_scan_complete_event_handler(struct wlan_objmgr_vdev *vdev,
tdls_post_scan_done_msg(tdls_soc);
}
void tdls_set_link_unforce(struct wlan_objmgr_vdev *vdev)
{
QDF_STATUS status;
struct scheduler_msg msg = {0};
msg.callback = tdls_process_cmd;
msg.type = TDLS_CMD_SET_LINK_UNFORCE;
msg.bodyptr = vdev;
status = scheduler_post_message(QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_OS_IF, &msg);
if (QDF_IS_STATUS_ERROR(status))
tdls_err("failed to set tdls link mode");
}
/**
* tdls_check_peer_buf_capable() - Check buffer sta capable of tdls peers
* @tdls_vdev: TDLS vdev object

View File

@@ -811,6 +811,14 @@ void tdls_scan_complete_event_handler(struct wlan_objmgr_vdev *vdev,
struct scan_event *event,
void *arg);
/**
* tdls_set_link_unforce() - set link unforce
* @vdev: vdev object
*
* Return: void
*/
void tdls_set_link_unforce(struct wlan_objmgr_vdev *vdev);
/**
* tdls_scan_callback() - callback for TDLS scan operation
* @tdls_soc: tdls soc pvt object

View File

@@ -87,6 +87,26 @@ tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev)
return wlan_mlo_get_tdls_link_vdev(vdev);
}
void
tdls_set_remain_links_unforce(struct wlan_objmgr_vdev *vdev)
{
struct wlan_mlo_dev_context *mlo_dev_ctx;
struct wlan_objmgr_vdev *mlo_vdev;
int i;
/* TDLS link is selected, unforce link for other vdevs */
mlo_dev_ctx = vdev->mlo_dev_ctx;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
if (!mlo_vdev || mlo_vdev == vdev)
continue;
tdls_debug("try to set vdev %d to unforce",
wlan_vdev_get_id(mlo_vdev));
tdls_set_link_unforce(mlo_vdev);
}
}
QDF_STATUS
tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev)
{
@@ -425,6 +445,11 @@ tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev)
return NULL;
}
void
tdls_set_remain_links_unforce(struct wlan_objmgr_vdev *vdev)
{
}
QDF_STATUS
tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev)
{
@@ -852,7 +877,7 @@ tdls_send_mgmt_serialize_callback(struct wlan_serialization_command *cmd,
}
#ifdef WLAN_FEATURE_11BE_MLO
static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
{
uint8_t mlo_vdev_lst[WLAN_UMAC_MLO_MAX_VDEVS] = {-1};
struct wlan_objmgr_psoc *psoc;
@@ -865,10 +890,6 @@ static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
if (!is_mlo_vdev)
return status;
mlo_tdls_vdev = wlan_mlo_get_tdls_link_vdev(req->vdev);
if (mlo_tdls_vdev)
return status;
psoc = wlan_vdev_get_psoc(req->vdev);
if (!psoc) {
tdls_err("psoc is NULL");
@@ -877,6 +898,10 @@ static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
if (req->tdls_mgmt.frame_type == TDLS_DISCOVERY_RESPONSE ||
req->tdls_mgmt.frame_type == TDLS_DISCOVERY_REQUEST) {
mlo_tdls_vdev = wlan_mlo_get_tdls_link_vdev(req->vdev);
if (mlo_tdls_vdev)
return status;
mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
vdev_count = 1;
@@ -886,12 +911,20 @@ static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
vdev_count, mlo_vdev_lst);
if (status == QDF_STATUS_SUCCESS)
req->link_active = true;
} else if (req->tdls_mgmt.frame_type == TDLS_MAX_ACTION_CODE) {
mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
vdev_count = 1;
status =
policy_mgr_mlo_sta_set_link(psoc,
MLO_LINK_FORCE_REASON_TDLS,
MLO_LINK_FORCE_MODE_NO_FORCE,
vdev_count, mlo_vdev_lst);
}
return status;
}
#else
static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
{
return QDF_STATUS_SUCCESS;
}

View File

@@ -99,6 +99,14 @@ tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev);
struct wlan_objmgr_vdev *
tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev);
/**
* tdls_set_remain_links_unforce() - unforce links
* @vdev: vdev object
*
* Return: void
*/
void tdls_set_remain_links_unforce(struct wlan_objmgr_vdev *vdev);
/**
* tdls_mgmt_rx_ops() - register or unregister rx callback
* @psoc: psoc object
@@ -150,5 +158,13 @@ tdls_process_mlo_choice_tdls_vdev(struct wlan_objmgr_vdev *vdev);
* Return: void
*/
void tdls_set_no_force_vdev(struct wlan_objmgr_vdev *vdev, bool flag);
/**
* tdls_set_link_mode() - force active or unfore link for MLO case
* @req: the pointer of tdls_action_frame_request
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req);
#endif

View File

@@ -241,6 +241,7 @@ enum tdls_feature_mode {
* @TDLS_CMD_SET_SECOFFCHANOFFSET: tdls secondary offchannel offset
* @TDLS_DELETE_ALL_PEERS_INDICATION: tdls delete all peers indication
* @TDLS_CMD_START_BSS: SAP start indication to tdls module
* @TDLS_CMD_SET_LINK_UNFORCE: tdls to unforce link for MLO case
*/
enum tdls_command_type {
TDLS_CMD_TX_ACTION = 1,
@@ -267,7 +268,8 @@ enum tdls_command_type {
TDLS_CMD_SET_OFFCHANMODE,
TDLS_CMD_SET_SECOFFCHANOFFSET,
TDLS_DELETE_ALL_PEERS_INDICATION,
TDLS_CMD_START_BSS
TDLS_CMD_START_BSS,
TDLS_CMD_SET_LINK_UNFORCE
};
/**

View File

@@ -528,6 +528,7 @@ bool ucfg_tdls_link_vdev_is_matching(struct wlan_objmgr_vdev *vdev)
if (!tdls_link_vdev) {
wlan_vdev_mlme_feat_ext2_cap_set(vdev,
WLAN_VDEV_FEXT2_MLO_STA_TDLS);
tdls_set_remain_links_unforce(vdev);
return true;
}