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; 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) QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp)
{ {
uint8_t sta_idx, id; 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_LINK_DROPPED_BY_REMOTE);
} }
tdls_process_unforce_link_mode(vdev);
cmddone: cmddone:
tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_DEL_PEER); tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_DEL_PEER);
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID); 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 wlan_objmgr_vdev *tdls_link_vdev;
struct tdls_rx_mgmt_frame *rx_mgmt; struct tdls_rx_mgmt_frame *rx_mgmt;
uint8_t *mac; uint8_t *mac;
bool unforce = true;
if (!user_data) { if (!user_data) {
tdls_err("discovery time out data is null"); 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)) { while (QDF_IS_STATUS_SUCCESS(status)) {
peer = qdf_container_of(p_node, struct tdls_peer, peer = qdf_container_of(p_node, struct tdls_peer,
node); 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) { if (TDLS_LINK_DISCOVERING != peer->link_status) {
status = qdf_list_peek_next(head, p_node, status = qdf_list_peek_next(head, p_node,
&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; tdls_vdev->discovery_sent_cnt = 0;
/* add tdls power save prohibited */ /* add tdls power save prohibited */
@@ -1458,6 +1474,14 @@ void tdls_disable_offchan_and_teardown_links(
QDF_STATUS status; QDF_STATUS status;
uint8_t vdev_id; uint8_t vdev_id;
bool tdls_in_progress = false; 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); status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc);
if (QDF_STATUS_SUCCESS != status) { 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_CMD_SET_SECOFFCHANOFFSET);
CASE_RETURN_STRING(TDLS_DELETE_ALL_PEERS_INDICATION); CASE_RETURN_STRING(TDLS_DELETE_ALL_PEERS_INDICATION);
CASE_RETURN_STRING(TDLS_CMD_START_BSS); CASE_RETURN_STRING(TDLS_CMD_START_BSS);
CASE_RETURN_STRING(TDLS_CMD_SET_LINK_UNFORCE);
default: default:
return "Invalid TDLS command"; return "Invalid TDLS command";
} }
@@ -582,6 +583,17 @@ QDF_STATUS tdls_handle_start_bss(struct wlan_objmgr_psoc *psoc)
} }
#endif #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 tdls_process_cmd(struct scheduler_msg *msg)
{ {
QDF_STATUS status = QDF_STATUS_SUCCESS; QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -668,6 +680,9 @@ QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
case TDLS_CMD_START_BSS: case TDLS_CMD_START_BSS:
tdls_handle_start_bss(msg->bodyptr); tdls_handle_start_bss(msg->bodyptr);
break; break;
case TDLS_CMD_SET_LINK_UNFORCE:
tdls_handle_link_unforce(msg->bodyptr);
break;
default: default:
break; break;
} }
@@ -2039,6 +2054,21 @@ void tdls_scan_complete_event_handler(struct wlan_objmgr_vdev *vdev,
tdls_post_scan_done_msg(tdls_soc); 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_check_peer_buf_capable() - Check buffer sta capable of tdls peers
* @tdls_vdev: TDLS vdev object * @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, struct scan_event *event,
void *arg); 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_scan_callback() - callback for TDLS scan operation
* @tdls_soc: tdls soc pvt object * @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); 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 QDF_STATUS
tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev) 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; return NULL;
} }
void
tdls_set_remain_links_unforce(struct wlan_objmgr_vdev *vdev)
{
}
QDF_STATUS QDF_STATUS
tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev) 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 #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}; uint8_t mlo_vdev_lst[WLAN_UMAC_MLO_MAX_VDEVS] = {-1};
struct wlan_objmgr_psoc *psoc; 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) if (!is_mlo_vdev)
return status; 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); psoc = wlan_vdev_get_psoc(req->vdev);
if (!psoc) { if (!psoc) {
tdls_err("psoc is NULL"); 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 || if (req->tdls_mgmt.frame_type == TDLS_DISCOVERY_RESPONSE ||
req->tdls_mgmt.frame_type == TDLS_DISCOVERY_REQUEST) { 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); mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
vdev_count = 1; 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); vdev_count, mlo_vdev_lst);
if (status == QDF_STATUS_SUCCESS) if (status == QDF_STATUS_SUCCESS)
req->link_active = true; 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; return status;
} }
#else #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; 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 * struct wlan_objmgr_vdev *
tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *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 * tdls_mgmt_rx_ops() - register or unregister rx callback
* @psoc: psoc object * @psoc: psoc object
@@ -150,5 +158,13 @@ tdls_process_mlo_choice_tdls_vdev(struct wlan_objmgr_vdev *vdev);
* Return: void * Return: void
*/ */
void tdls_set_no_force_vdev(struct wlan_objmgr_vdev *vdev, bool flag); 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 #endif

View File

@@ -241,6 +241,7 @@ enum tdls_feature_mode {
* @TDLS_CMD_SET_SECOFFCHANOFFSET: tdls secondary offchannel offset * @TDLS_CMD_SET_SECOFFCHANOFFSET: tdls secondary offchannel offset
* @TDLS_DELETE_ALL_PEERS_INDICATION: tdls delete all peers indication * @TDLS_DELETE_ALL_PEERS_INDICATION: tdls delete all peers indication
* @TDLS_CMD_START_BSS: SAP start indication to tdls module * @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 { enum tdls_command_type {
TDLS_CMD_TX_ACTION = 1, TDLS_CMD_TX_ACTION = 1,
@@ -267,7 +268,8 @@ enum tdls_command_type {
TDLS_CMD_SET_OFFCHANMODE, TDLS_CMD_SET_OFFCHANMODE,
TDLS_CMD_SET_SECOFFCHANOFFSET, TDLS_CMD_SET_SECOFFCHANOFFSET,
TDLS_DELETE_ALL_PEERS_INDICATION, 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) { if (!tdls_link_vdev) {
wlan_vdev_mlme_feat_ext2_cap_set(vdev, wlan_vdev_mlme_feat_ext2_cap_set(vdev,
WLAN_VDEV_FEXT2_MLO_STA_TDLS); WLAN_VDEV_FEXT2_MLO_STA_TDLS);
tdls_set_remain_links_unforce(vdev);
return true; return true;
} }