qcacmn: Add support for T2LM timer handling
Adds api's to handle t2lm timer functionality. Api's added are timer initialize, start, stop, expiry handler. Change-Id: If52453135921067d04f8349ece64c33cd524af00 CRs-Fixed: 3342822
This commit is contained in:

committed by
Madan Koyyalamudi

orang tua
93e8977721
melakukan
8759cf1c1e
@@ -23,6 +23,8 @@
|
||||
#include <wmi_unified_11be_api.h>
|
||||
#include <init_deinit_lmac.h>
|
||||
#include "target_if_mlo_mgr.h"
|
||||
#include <wlan_objmgr_peer_obj.h>
|
||||
#include <wlan_mlo_t2lm.h>
|
||||
|
||||
/**
|
||||
* target_if_mlo_link_set_active_resp_handler() - function to handle mlo link
|
||||
@@ -238,6 +240,92 @@ target_if_mlo_unregister_vdev_tid_to_link_map_event(
|
||||
wmi_handle, wmi_mlo_ap_vdev_tid_to_link_map_eventid);
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
|
||||
/**
|
||||
* target_if_fill_provisioned_links() - API to fill the provisioned links
|
||||
* @params: Pointer to T2LM params structure
|
||||
* @t2lm: Pointer to T2LM info structure
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
static inline void target_if_fill_provisioned_links(
|
||||
struct wmi_host_tid_to_link_map_params *params,
|
||||
struct wlan_t2lm_info *t2lm)
|
||||
{
|
||||
qdf_mem_copy(¶ms->t2lm_info[params->num_dir].t2lm_provisioned_links,
|
||||
&t2lm->ieee_link_map_tid,
|
||||
sizeof(uint16_t) * T2LM_MAX_NUM_TIDS);
|
||||
}
|
||||
#else
|
||||
static inline void target_if_fill_provisioned_links(
|
||||
struct wmi_host_tid_to_link_map_params *params,
|
||||
struct wlan_t2lm_info *t2lm)
|
||||
{
|
||||
qdf_mem_copy(¶ms->t2lm_info[params->num_dir].t2lm_provisioned_links,
|
||||
&t2lm->hw_link_map_tid,
|
||||
sizeof(uint16_t) * T2LM_MAX_NUM_TIDS);
|
||||
}
|
||||
#endif
|
||||
|
||||
static QDF_STATUS
|
||||
target_if_mlo_send_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_t2lm_info *t2lm)
|
||||
{
|
||||
struct wmi_unified *wmi_handle = NULL;
|
||||
struct wmi_host_tid_to_link_map_params params = {0};
|
||||
struct wlan_objmgr_pdev *pdev = NULL;
|
||||
int tid = 0;
|
||||
QDF_STATUS status;
|
||||
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
if (!pdev) {
|
||||
t2lm_err("null pdev");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
wmi_handle = lmac_get_pdev_wmi_handle(pdev);
|
||||
if (!wmi_handle) {
|
||||
t2lm_err("null wmi handle");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
params.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
|
||||
qdf_mem_copy(params.peer_macaddr, vdev->vdev_objmgr.bss_peer->macaddr,
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
|
||||
t2lm_debug("Fill T2LM WMI info for peer: " QDF_MAC_ADDR_FMT " pdev_id:%d",
|
||||
QDF_MAC_ADDR_REF(params.peer_macaddr), params.pdev_id);
|
||||
|
||||
params.t2lm_info[params.num_dir].direction = t2lm->direction;
|
||||
params.t2lm_info[params.num_dir].default_link_mapping =
|
||||
t2lm->default_link_mapping;
|
||||
|
||||
if (!params.t2lm_info[params.num_dir].default_link_mapping)
|
||||
target_if_fill_provisioned_links(¶ms, t2lm);
|
||||
|
||||
t2lm_debug("num_dir:%d direction:%d default_link_mapping:%d",
|
||||
params.num_dir, params.t2lm_info[params.num_dir].direction,
|
||||
params.t2lm_info[params.num_dir].default_link_mapping);
|
||||
|
||||
for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
|
||||
t2lm_debug("tid:%d hw_link_map:%x ieee_lin_map:%x", tid,
|
||||
params.t2lm_info[params.num_dir].t2lm_provisioned_links[tid],
|
||||
t2lm->ieee_link_map_tid[tid]);
|
||||
}
|
||||
|
||||
params.num_dir++;
|
||||
|
||||
status = wmi_send_mlo_peer_tid_to_link_map_cmd(wmi_handle, ¶ms);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
t2lm_err("Failed to send T2LM WMI command for pdev_id:%d peer_mac: " QDF_MAC_ADDR_FMT,
|
||||
params.pdev_id,
|
||||
QDF_MAC_ADDR_REF(params.peer_macaddr));
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_mlo_register_tx_ops() - lmac handler to register mlo tx ops
|
||||
* callback functions
|
||||
@@ -266,6 +354,8 @@ target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
|
||||
mlo_tx_ops->unregister_events =
|
||||
target_if_mlo_unregister_event_handler;
|
||||
mlo_tx_ops->link_set_active = target_if_mlo_link_set_active;
|
||||
mlo_tx_ops->send_tid_to_link_mapping =
|
||||
target_if_mlo_send_tid_to_link_mapping;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
@@ -1387,6 +1387,7 @@ struct wlan_lmac_if_son_rx_ops {
|
||||
* @register_events: function to register event handlers with FW
|
||||
* @unregister_events: function to de-register event handlers with FW
|
||||
* @link_set_active: function to send mlo link set active command to FW
|
||||
* @send_tid_to_link_mapping: function to send T2LM command to FW
|
||||
*/
|
||||
struct wlan_lmac_if_mlo_tx_ops {
|
||||
QDF_STATUS (*register_events)(struct wlan_objmgr_psoc *psoc);
|
||||
@@ -1396,6 +1397,8 @@ struct wlan_lmac_if_mlo_tx_ops {
|
||||
#ifdef WLAN_MLO_GLOBAL_SHMEM_SUPPORT
|
||||
struct wlan_lmac_if_global_shmem_local_ops shmem_local_ops;
|
||||
#endif
|
||||
QDF_STATUS (*send_tid_to_link_mapping)(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_t2lm_info *t2lm);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -300,6 +300,7 @@ enum wlan_t2lm_direction {
|
||||
WLAN_T2LM_INVALID_DIRECTION,
|
||||
};
|
||||
|
||||
#define T2LM_EXPECTED_DURATION_MAX_VALUE 0xFFFFFF
|
||||
/**
|
||||
* struct wlan_t2lm_info - TID-to-Link mapping information for the frames
|
||||
* transmitted on the uplink, downlink and bidirectional.
|
||||
@@ -352,11 +353,21 @@ struct wlan_mlo_t2lm_ie {
|
||||
* struct wlan_t2lm_timer - T2LM timer information
|
||||
*
|
||||
* @t2lm_timer: T2LM timer
|
||||
* @timer_interval: T2LM timer interval value
|
||||
* @timer_interval: T2LM Timer value
|
||||
* @timer_started: T2LM timer started or not
|
||||
* @t2lm_ie_index: T2LM IE index value
|
||||
* @t2lm_dev_lock: lock to access struct
|
||||
*/
|
||||
struct wlan_t2lm_timer {
|
||||
qdf_timer_t t2lm_timer;
|
||||
uint32_t timer_interval;
|
||||
bool timer_started;
|
||||
uint8_t t2lm_ie_index;
|
||||
#ifdef WLAN_MLO_USE_SPINLOCK
|
||||
qdf_spinlock_t t2lm_dev_lock;
|
||||
#else
|
||||
qdf_mutex_t t2lm_dev_lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -366,6 +377,7 @@ struct wlan_t2lm_timer {
|
||||
* @t2lm_ie: T2LM IE information
|
||||
* @t2lm_timer: T2LM timer information
|
||||
* @t2lm_dev_lock: t2lm dev context lock
|
||||
* @tsf: time sync func value received via beacon
|
||||
*/
|
||||
struct wlan_t2lm_context {
|
||||
uint8_t num_of_t2lm_ie;
|
||||
@@ -376,6 +388,7 @@ struct wlan_t2lm_context {
|
||||
#else
|
||||
qdf_mutex_t t2lm_dev_lock;
|
||||
#endif
|
||||
uint64_t tsf;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -45,6 +45,86 @@
|
||||
|
||||
#define WLAN_T2LM_MAX_NUM_LINKS 16
|
||||
|
||||
#ifdef WLAN_MLO_USE_SPINLOCK
|
||||
/**
|
||||
* t2lm_dev_lock_create - Create T2LM device mutex/spinlock
|
||||
* @t2lm_ctx: T2LM context
|
||||
*
|
||||
* Creates mutex/spinlock
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static inline void
|
||||
t2lm_dev_lock_create(struct wlan_t2lm_context *t2lm_ctx)
|
||||
{
|
||||
qdf_spinlock_create(&t2lm_ctx->t2lm_dev_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* t2lm_dev_lock_destroy - Destroy T2LM mutex/spinlock
|
||||
* @t2lm_ctx: T2LM context
|
||||
*
|
||||
* Destroy mutex/spinlock
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static inline void
|
||||
t2lm_dev_lock_destroy(struct wlan_t2lm_context *t2lm_ctx)
|
||||
{
|
||||
qdf_spinlock_destroy(&t2lm_ctx->t2lm_dev_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* t2lm_dev_lock_acquire - acquire T2LM mutex/spinlock
|
||||
* @t2lm_ctx: T2LM context
|
||||
*
|
||||
* acquire mutex/spinlock
|
||||
*
|
||||
* return: void
|
||||
*/
|
||||
static inline
|
||||
void t2lm_dev_lock_acquire(struct wlan_t2lm_context *t2lm_ctx)
|
||||
{
|
||||
qdf_spin_lock_bh(&t2lm_ctx->t2lm_dev_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* t2lm_dev_lock_release - release T2LM dev mutex/spinlock
|
||||
* @t2lm_ctx: T2LM context
|
||||
*
|
||||
* release mutex/spinlock
|
||||
*
|
||||
* return: void
|
||||
*/
|
||||
static inline
|
||||
void t2lm_dev_lock_release(struct wlan_t2lm_context *t2lm_ctx)
|
||||
{
|
||||
qdf_spin_unlock_bh(&t2lm_ctx->t2lm_dev_lock);
|
||||
}
|
||||
#else /* WLAN_MLO_USE_SPINLOCK */
|
||||
static inline
|
||||
void t2lm_dev_lock_create(struct wlan_t2lm_context *t2lm_ctx)
|
||||
{
|
||||
qdf_mutex_create(&t2lm_ctx->t2lm_dev_lock);
|
||||
}
|
||||
|
||||
static inline
|
||||
void t2lm_dev_lock_destroy(struct wlan_t2lm_context *t2lm_ctx)
|
||||
{
|
||||
qdf_mutex_destroy(&t2lm_ctx->t2lm_dev_lock);
|
||||
}
|
||||
|
||||
static inline void t2lm_dev_lock_acquire(struct wlan_t2lm_context *t2lm_ctx)
|
||||
{
|
||||
qdf_mutex_acquire(&t2lm_ctx->t2lm_dev_lock);
|
||||
}
|
||||
|
||||
static inline void t2lm_dev_lock_release(struct wlan_t2lm_context *t2lm_ctx)
|
||||
{
|
||||
qdf_mutex_release(&t2lm_ctx->t2lm_dev_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* wlan_mlo_parse_t2lm_ie() - API to parse the T2LM IE
|
||||
* @t2lm: Pointer to T2LM structure
|
||||
@@ -122,6 +202,69 @@ QDF_STATUS wlan_mlo_parse_bcn_prbresp_t2lm_ie(
|
||||
* Return: Updated frame pointer
|
||||
*/
|
||||
uint8_t *wlan_mlo_add_t2lm_info_ie(uint8_t *frm, struct wlan_t2lm_info *t2lm);
|
||||
|
||||
/**
|
||||
* wlan_mlo_t2lm_timer_init() - API to add TID-to-link mapping IE
|
||||
* @vdev: Pointer to vdev
|
||||
*
|
||||
* Return: qdf status
|
||||
*/
|
||||
QDF_STATUS
|
||||
wlan_mlo_t2lm_timer_init(struct wlan_objmgr_vdev *vdev);
|
||||
|
||||
/**
|
||||
* wlan_mlo_t2lm_timer_start() - API to start T2LM timer
|
||||
* @vdev: Pointer to vdev
|
||||
* @interval: T2LM timer interval
|
||||
* @t2lm_ie_index: T2LM IE index
|
||||
*
|
||||
* Return: qdf status
|
||||
*/
|
||||
QDF_STATUS
|
||||
wlan_mlo_t2lm_timer_start(struct wlan_objmgr_vdev *vdev,
|
||||
uint32_t interval, uint8_t t2lm_ie_index);
|
||||
|
||||
/**
|
||||
* wlan_mlo_t2lm_timer_stop() - API to stop TID-to-link mapping timer
|
||||
* @vdev: Pointer to vdev
|
||||
*
|
||||
* Return: qdf status
|
||||
*/
|
||||
QDF_STATUS
|
||||
wlan_mlo_t2lm_timer_stop(struct wlan_objmgr_vdev *vdev);
|
||||
|
||||
/**
|
||||
* wlan_mlo_t2lm_timer_expiry_handler() - API to handle t2lm timer expiry
|
||||
* @vdev: Pointer to vdev structure
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void
|
||||
wlan_mlo_t2lm_timer_expiry_handler(void *vdev);
|
||||
|
||||
/**
|
||||
* wlan_handle_t2lm_timer() - API to handle TID-to-link mapping timer
|
||||
* @vdev: Pointer to vdev
|
||||
* @ie_idx: ie index value
|
||||
*
|
||||
* Return: qdf status
|
||||
*/
|
||||
QDF_STATUS
|
||||
wlan_handle_t2lm_timer(struct wlan_objmgr_vdev *vdev, uint8_t ie_idx);
|
||||
|
||||
/**
|
||||
* wlan_process_bcn_prbrsp_t2lm_ie() - API to process the received T2LM IE from
|
||||
* beacon/probe response.
|
||||
* @vdev: Pointer to vdev
|
||||
* @rx_t2lm_ie: Received T2LM IE
|
||||
* @tsf: Local TSF value
|
||||
*
|
||||
* Return QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS wlan_process_bcn_prbrsp_t2lm_ie(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_t2lm_context *rx_t2lm_ie,
|
||||
uint64_t tsf);
|
||||
|
||||
#else
|
||||
static inline QDF_STATUS wlan_mlo_parse_t2lm_ie(
|
||||
struct wlan_t2lm_onging_negotiation_info *t2lm, uint8_t *ie)
|
||||
@@ -165,5 +308,42 @@ uint8_t *wlan_mlo_add_t2lm_info_ie(uint8_t *frm, struct wlan_t2lm_info *t2lm)
|
||||
{
|
||||
return frm;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS
|
||||
wlan_mlo_t2lm_timer_init(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
return QDF_STATUS_E_NOSUPPORT;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS
|
||||
wlan_mlo_t2lm_timer_start(struct wlan_objmgr_vdev *vdev,
|
||||
uint32_t interval, uint8_t t2lm_ie_index)
|
||||
{
|
||||
return QDF_STATUS_E_NOSUPPORT;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS
|
||||
wlan_mlo_t2lm_timer_stop(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
return QDF_STATUS_E_NOSUPPORT;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wlan_mlo_t2lm_timer_expiry_handler(void *vdev)
|
||||
{}
|
||||
|
||||
static inline QDF_STATUS
|
||||
wlan_handle_t2lm_timer(struct wlan_objmgr_vdev *vdev, uint8_t ie_idx)
|
||||
{
|
||||
return QDF_STATUS_E_NOSUPPORT;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS
|
||||
wlan_process_bcn_prbrsp_t2lm_ie(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_t2lm_context *rx_t2lm_ie,
|
||||
uint64_t tsf)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#endif /* WLAN_FEATURE_11BE */
|
||||
#endif /* _WLAN_MLO_T2LM_H_ */
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include <wlan_cm_public_struct.h>
|
||||
#include "wlan_mlo_mgr_msgq.h"
|
||||
#include <target_if_mlo_mgr.h>
|
||||
#include <wlan_mlo_t2lm.h>
|
||||
|
||||
static void mlo_global_ctx_deinit(void)
|
||||
{
|
||||
@@ -436,10 +437,12 @@ QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
|
||||
* mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default
|
||||
* values.
|
||||
* @ml_dev: Pointer to ML Dev context
|
||||
* @vdev: Pointer to vdev structure
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev)
|
||||
static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_t2lm_info *t2lm;
|
||||
|
||||
@@ -450,6 +453,8 @@ static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev)
|
||||
ml_dev->t2lm_ctx.num_of_t2lm_ie = 1;
|
||||
t2lm->direction = WLAN_T2LM_BIDI_DIRECTION;
|
||||
t2lm->default_link_mapping = 1;
|
||||
|
||||
wlan_mlo_t2lm_timer_init(vdev);
|
||||
}
|
||||
|
||||
static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
|
||||
@@ -527,7 +532,7 @@ static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
|
||||
qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node);
|
||||
ml_link_lock_release(g_mlo_ctx);
|
||||
|
||||
mlo_t2lm_ctx_init(ml_dev);
|
||||
mlo_t2lm_ctx_init(ml_dev, vdev);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <wlan_mlo_t2lm.h>
|
||||
#include <wlan_mlo_mgr_cmn.h>
|
||||
#include <qdf_util.h>
|
||||
#include <wlan_cm_api.h>
|
||||
|
||||
/**
|
||||
* wlan_mlo_parse_t2lm_info() - Parse T2LM IE fields
|
||||
@@ -621,13 +622,32 @@ static void wlan_mlo_t2lm_handle_expected_duration_expiry(
|
||||
if (!t2lm_ctx->t2lm_ie[i].t2lm.expected_duration_present)
|
||||
continue;
|
||||
|
||||
/* If two T2LM IEs are present, and expected duration of first
|
||||
* T2LM IE is expired, copy the T2LM IE from index 1 to index 0.
|
||||
* Mark mapping switch time present as false and clear the
|
||||
* mapping switch time value.
|
||||
* If one T2LM IE is present, and the expected duration is
|
||||
* expired, configure the T2LM IE with the default values.
|
||||
*/
|
||||
if (!i && t2lm_ctx->num_of_t2lm_ie == WLAN_MAX_T2LM_IE) {
|
||||
qdf_mem_copy(&t2lm_ctx->t2lm_ie[0],
|
||||
&t2lm_ctx->t2lm_ie[1],
|
||||
sizeof(struct wlan_mlo_t2lm_ie));
|
||||
t2lm_ctx->t2lm_ie[0].t2lm.mapping_switch_time_present =
|
||||
false;
|
||||
t2lm_ctx->t2lm_ie[0].t2lm.mapping_switch_time = 0;
|
||||
t2lm_debug("vdev_id:%d mark the advertised T2LM as established",
|
||||
vdev_id);
|
||||
} else {
|
||||
qdf_mem_zero(&t2lm_ctx->t2lm_ie[i],
|
||||
sizeof(struct wlan_mlo_t2lm_ie));
|
||||
t2lm_ctx->t2lm_ie[i].t2lm.direction = WLAN_T2LM_BIDI_DIRECTION;
|
||||
t2lm_ctx->t2lm_ie[i].t2lm.direction =
|
||||
WLAN_T2LM_BIDI_DIRECTION;
|
||||
t2lm_ctx->t2lm_ie[i].t2lm.default_link_mapping = 1;
|
||||
t2lm_debug("vdev_id:%d Expected duration is expired",
|
||||
vdev_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_vdev_tid_to_link_map_event(
|
||||
@@ -678,3 +698,311 @@ QDF_STATUS wlan_mlo_vdev_tid_to_link_map_event(
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
QDF_STATUS wlan_send_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_t2lm_info *t2lm)
|
||||
{
|
||||
struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
|
||||
struct wlan_objmgr_vdev *co_mld_vdev;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {NULL};
|
||||
uint16_t vdev_count = 0;
|
||||
int i = 0;
|
||||
QDF_STATUS status = QDF_STATUS_E_FAILURE;
|
||||
|
||||
psoc = wlan_vdev_get_psoc(vdev);
|
||||
if (!psoc) {
|
||||
t2lm_err("null psoc");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
|
||||
if (!mlo_tx_ops) {
|
||||
t2lm_err("tx_ops is null!");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
if (!mlo_tx_ops->send_tid_to_link_mapping) {
|
||||
t2lm_err("send_tid_to_link_mapping is null");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
mlo_get_ml_vdev_list(vdev, &vdev_count, wlan_vdev_list);
|
||||
if (!vdev_count) {
|
||||
t2lm_err("Number of VDEVs under MLD is reported as 0");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
for (i = 0; i < vdev_count; i++) {
|
||||
co_mld_vdev = wlan_vdev_list[i];
|
||||
if (!co_mld_vdev) {
|
||||
t2lm_err("co_mld_vdev is null");
|
||||
mlo_release_vdev_ref(co_mld_vdev);
|
||||
continue;
|
||||
}
|
||||
|
||||
status = mlo_tx_ops->send_tid_to_link_mapping(co_mld_vdev,
|
||||
t2lm);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
t2lm_err("Failed to send T2LM command to FW");
|
||||
mlo_release_vdev_ref(co_mld_vdev);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void wlan_mlo_t2lm_timer_expiry_handler(void *vdev)
|
||||
{
|
||||
struct wlan_objmgr_vdev *vdev_ctx = (struct wlan_objmgr_vdev *)vdev;
|
||||
|
||||
struct wlan_t2lm_timer *t2lm_timer;
|
||||
struct wlan_t2lm_context *t2lm_ctx;
|
||||
uint8_t t2lm_ie_idx;
|
||||
|
||||
if (!vdev_ctx || !vdev_ctx->mlo_dev_ctx)
|
||||
return;
|
||||
|
||||
t2lm_ctx = &vdev_ctx->mlo_dev_ctx->t2lm_ctx;
|
||||
t2lm_timer = &vdev_ctx->mlo_dev_ctx->t2lm_ctx.t2lm_timer;
|
||||
t2lm_ie_idx = t2lm_timer->t2lm_ie_index;
|
||||
if (t2lm_ie_idx >= WLAN_MAX_T2LM_IE)
|
||||
return;
|
||||
|
||||
wlan_mlo_t2lm_timer_stop(vdev_ctx);
|
||||
|
||||
if (t2lm_ctx->t2lm_ie[t2lm_ie_idx].t2lm.mapping_switch_time_present) {
|
||||
wlan_send_tid_to_link_mapping(
|
||||
vdev, &t2lm_ctx->t2lm_ie[t2lm_ie_idx].t2lm);
|
||||
wlan_mlo_t2lm_handle_mapping_switch_time_expiry(t2lm_ctx, vdev);
|
||||
wlan_handle_t2lm_timer(vdev_ctx, t2lm_timer->t2lm_ie_index);
|
||||
} else if (!t2lm_ie_idx) {
|
||||
wlan_mlo_t2lm_handle_expected_duration_expiry(t2lm_ctx, vdev);
|
||||
wlan_handle_t2lm_timer(vdev_ctx, t2lm_timer->t2lm_ie_index);
|
||||
}
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
wlan_mlo_t2lm_timer_init(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_t2lm_timer *t2lm_timer = NULL;
|
||||
|
||||
if (!vdev || !vdev->mlo_dev_ctx)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer;
|
||||
if (!t2lm_timer) {
|
||||
t2lm_err("t2lm timer ctx is null");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
t2lm_dev_lock_acquire(&vdev->mlo_dev_ctx->t2lm_ctx);
|
||||
qdf_timer_init(NULL, &t2lm_timer->t2lm_timer,
|
||||
wlan_mlo_t2lm_timer_expiry_handler,
|
||||
vdev, QDF_TIMER_TYPE_WAKE_APPS);
|
||||
|
||||
t2lm_timer->timer_started = false;
|
||||
t2lm_timer->timer_interval = 0;
|
||||
t2lm_timer->t2lm_ie_index = 0;
|
||||
t2lm_dev_lock_release(&vdev->mlo_dev_ctx->t2lm_ctx);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
wlan_mlo_t2lm_timer_start(struct wlan_objmgr_vdev *vdev,
|
||||
uint32_t interval, uint8_t t2lm_ie_index)
|
||||
{
|
||||
struct wlan_t2lm_timer *t2lm_timer;
|
||||
struct wlan_t2lm_context *t2lm_ctx;
|
||||
struct vdev_mlme_obj *vdev_mlme;
|
||||
|
||||
if (!vdev || !vdev->mlo_dev_ctx)
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
|
||||
if (interval == 0) {
|
||||
t2lm_debug("Timer interval is 0");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
|
||||
if (!vdev_mlme)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
|
||||
t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer;
|
||||
if (!t2lm_timer) {
|
||||
t2lm_err("t2lm timer ctx is null");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
t2lm_debug("t2lm timer started with interval %d", interval);
|
||||
t2lm_dev_lock_acquire(&vdev->mlo_dev_ctx->t2lm_ctx);
|
||||
if (t2lm_ctx->t2lm_ie[t2lm_ie_index].t2lm.mapping_switch_time_present)
|
||||
t2lm_timer->timer_interval =
|
||||
t2lm_ctx->t2lm_ie[t2lm_ie_index].t2lm.mapping_switch_time;
|
||||
else
|
||||
t2lm_timer->timer_interval = interval *
|
||||
vdev_mlme->proto.generic.beacon_interval * 1000;
|
||||
|
||||
t2lm_timer->t2lm_ie_index = t2lm_ie_index;
|
||||
t2lm_timer->timer_started = true;
|
||||
qdf_timer_start(&t2lm_timer->t2lm_timer, t2lm_timer->timer_interval);
|
||||
t2lm_dev_lock_release(&vdev->mlo_dev_ctx->t2lm_ctx);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
wlan_mlo_t2lm_timer_stop(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_t2lm_timer *t2lm_timer;
|
||||
|
||||
if (!vdev || !vdev->mlo_dev_ctx)
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
|
||||
t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer;
|
||||
if (!t2lm_timer) {
|
||||
t2lm_err("t2lm timer ctx is null");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
t2lm_dev_lock_acquire(&vdev->mlo_dev_ctx->t2lm_ctx);
|
||||
if (t2lm_timer->timer_started) {
|
||||
qdf_timer_stop(&t2lm_timer->t2lm_timer);
|
||||
t2lm_timer->timer_started = false;
|
||||
t2lm_timer->timer_interval = 0;
|
||||
}
|
||||
t2lm_dev_lock_release(&vdev->mlo_dev_ctx->t2lm_ctx);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_handle_t2lm_timer(struct wlan_objmgr_vdev *vdev, uint8_t ie_idx)
|
||||
{
|
||||
struct wlan_t2lm_context *t2lm_ctx;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
if (!vdev || !vdev->mlo_dev_ctx)
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
|
||||
t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
|
||||
if (!t2lm_ctx->num_of_t2lm_ie) {
|
||||
t2lm_err("No T2LM IE present");
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (ie_idx >= WLAN_MAX_T2LM_IE) {
|
||||
t2lm_err("Invalid T2LM IE index");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
if (!t2lm_ctx->t2lm_ie[ie_idx].t2lm.mapping_switch_time_present &&
|
||||
!t2lm_ctx->t2lm_ie[ie_idx].t2lm.expected_duration_present) {
|
||||
/* non-default to default mapping case */
|
||||
wlan_send_tid_to_link_mapping(vdev,
|
||||
&t2lm_ctx->t2lm_ie[ie_idx].t2lm);
|
||||
} else if (t2lm_ctx->t2lm_ie[ie_idx].t2lm.mapping_switch_time_present) {
|
||||
/* Default to non-default mapping case */
|
||||
status = wlan_mlo_t2lm_timer_start(
|
||||
vdev,
|
||||
t2lm_ctx->t2lm_ie[ie_idx].t2lm.mapping_switch_time,
|
||||
ie_idx);
|
||||
} else if (t2lm_ctx->t2lm_ie[ie_idx].t2lm.expected_duration_present) {
|
||||
wlan_send_tid_to_link_mapping(
|
||||
vdev, &t2lm_ctx->t2lm_ie[ie_idx].t2lm);
|
||||
|
||||
if (t2lm_ctx->t2lm_ie[ie_idx].t2lm.expected_duration !=
|
||||
T2LM_EXPECTED_DURATION_MAX_VALUE)
|
||||
status = wlan_mlo_t2lm_timer_start(
|
||||
vdev,
|
||||
t2lm_ctx->t2lm_ie[ie_idx].t2lm.expected_duration,
|
||||
ie_idx);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_update_mapping_switch_time_expected_dur() - API to update the mapping
|
||||
* switch time and expected duration.
|
||||
* @vdev:Pointer to vdev
|
||||
* @rx_t2lm: Pointer to received T2LM IE
|
||||
* @tsf: TSF value of beacon/probe response
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void wlan_update_mapping_switch_time_expected_dur(
|
||||
struct wlan_objmgr_vdev *vdev, struct wlan_t2lm_info *rx_t2lm,
|
||||
uint64_t tsf)
|
||||
{
|
||||
struct wlan_t2lm_context *t2lm_ctx;
|
||||
uint16_t tsf_bit25_16, ms_time;
|
||||
bool match_found = false;
|
||||
int j;
|
||||
|
||||
tsf_bit25_16 = (tsf & 0x3FF0000) >> 16;
|
||||
t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
|
||||
|
||||
for (j = 0; j < t2lm_ctx->num_of_t2lm_ie; j++) {
|
||||
/* Match not found */
|
||||
if (qdf_mem_cmp(rx_t2lm->ieee_link_map_tid,
|
||||
t2lm_ctx->t2lm_ie[j].t2lm.ieee_link_map_tid,
|
||||
sizeof(uint16_t) * T2LM_MAX_NUM_TIDS))
|
||||
continue;
|
||||
|
||||
if (t2lm_ctx->t2lm_ie[j].t2lm.mapping_switch_time_present) {
|
||||
ms_time = rx_t2lm->mapping_switch_time;
|
||||
|
||||
if (ms_time > tsf_bit25_16) {
|
||||
t2lm_ctx->t2lm_ie[j].t2lm.mapping_switch_time =
|
||||
((ms_time - tsf_bit25_16) * 1024) / 1000;
|
||||
} else {
|
||||
t2lm_ctx->t2lm_ie[j].t2lm.mapping_switch_time =
|
||||
((0xFFFF - (tsf_bit25_16 - ms_time)) * 1024) / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
if (t2lm_ctx->t2lm_ie[j].t2lm.expected_duration_present) {
|
||||
t2lm_ctx->t2lm_ie[j].t2lm.expected_duration =
|
||||
rx_t2lm->expected_duration;
|
||||
}
|
||||
|
||||
match_found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!match_found &&
|
||||
t2lm_ctx->num_of_t2lm_ie < WLAN_MAX_T2LM_IE) {
|
||||
qdf_mem_copy(&t2lm_ctx->t2lm_ie[t2lm_ctx->num_of_t2lm_ie].t2lm,
|
||||
rx_t2lm, sizeof(struct wlan_t2lm_info));
|
||||
t2lm_ctx->num_of_t2lm_ie++;
|
||||
}
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_process_bcn_prbrsp_t2lm_ie(
|
||||
struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_t2lm_context *rx_t2lm_ie, uint64_t tsf)
|
||||
{
|
||||
struct wlan_t2lm_context *t2lm_ctx;
|
||||
int i;
|
||||
|
||||
t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
|
||||
|
||||
for (i = 0; i < rx_t2lm_ie->num_of_t2lm_ie; i++) {
|
||||
wlan_update_mapping_switch_time_expected_dur(
|
||||
vdev, &rx_t2lm_ie->t2lm_ie[i].t2lm, tsf);
|
||||
}
|
||||
|
||||
if (!wlan_cm_is_vdev_connected(vdev))
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
/* Do not start the timer if STA is not in connected state */
|
||||
for (i = 0; i < t2lm_ctx->num_of_t2lm_ie; i++) {
|
||||
if (t2lm_ctx->t2lm_ie[i].t2lm.mapping_switch_time_present ||
|
||||
t2lm_ctx->t2lm_ie[i].t2lm.expected_duration_present) {
|
||||
wlan_handle_t2lm_timer(vdev, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
Reference in New Issue
Block a user