qcacld-3.0: Init medium assess timer

Currently the medium assess timer is initialized and destroyed
when SAP start or stop. Since the timer is shared by SAPs, it
causes timer leak issue with the complexity of SAP + SAP
concurrency.

To resolve this issue, initialize and destroy the timer when
vendor command is issued.

Change-Id: I2e6a7e92e5d7053712c1825669d002982e2051d6
CRs-Fixed: 3584388
This commit is contained in:
Paul Zhang
2023-08-11 21:18:21 +08:00
committed by Rahul Choudhary
parent 08aee1da75
commit d8e7d9c0cc
4 changed files with 214 additions and 218 deletions

View File

@@ -2372,8 +2372,6 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
if (QDF_IS_STATUS_SUCCESS(qdf_status)) if (QDF_IS_STATUS_SUCCESS(qdf_status))
hdd_medium_assess_stop_timer(pdev_id, hdd_ctx); hdd_medium_assess_stop_timer(pdev_id, hdd_ctx);
hdd_medium_assess_deinit();
/* clear the reason code in case BSS is stopped /* clear the reason code in case BSS is stopped
* in another place * in another place
*/ */
@@ -6967,7 +6965,6 @@ int wlan_hdd_cfg80211_start_bss(struct wlan_hdd_link_info *link_info,
hdd_set_connection_in_progress(false); hdd_set_connection_in_progress(false);
policy_mgr_process_force_scc_for_nan(hdd_ctx->psoc); policy_mgr_process_force_scc_for_nan(hdd_ctx->psoc);
ret = 0; ret = 0;
hdd_medium_assess_init();
goto free; goto free;
error: error:
@@ -7148,7 +7145,6 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
hdd_place_marker(adapter, "STOP with FAILURE", hdd_place_marker(adapter, "STOP with FAILURE",
NULL); NULL);
hdd_sap_indicate_disconnect_for_sta(adapter); hdd_sap_indicate_disconnect_for_sta(adapter);
hdd_medium_assess_deinit();
QDF_ASSERT(0); QDF_ASSERT(0);
} }
} }

View File

@@ -14625,6 +14625,9 @@ int hdd_start_ap_adapter(struct hdd_adapter *adapter, bool rtnl_held)
hdd_register_hl_netdev_fc_timer(adapter, hdd_register_hl_netdev_fc_timer(adapter,
hdd_tx_resume_timer_expired_handler); hdd_tx_resume_timer_expired_handler);
if (cds_is_driver_recovering())
hdd_medium_assess_ssr_reinit();
hdd_exit(); hdd_exit();
return 0; return 0;
@@ -18016,8 +18019,6 @@ void wlan_hdd_start_sap(struct wlan_hdd_link_info *link_info, bool reinit)
} }
hdd_info("SAP Start Success"); hdd_info("SAP Start Success");
if (reinit)
hdd_medium_assess_init();
wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL); wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
set_bit(SOFTAP_BSS_STARTED, &link_info->link_flags); set_bit(SOFTAP_BSS_STARTED, &link_info->link_flags);
if (hostapd_state->bss_state == BSS_START) { if (hostapd_state->bss_state == BSS_START) {
@@ -20773,7 +20774,6 @@ void hdd_restart_sap(struct wlan_hdd_link_info *link_info)
} }
wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL); wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
hdd_err("SAP Start Success"); hdd_err("SAP Start Success");
hdd_medium_assess_init();
set_bit(SOFTAP_BSS_STARTED, &link_info->link_flags); set_bit(SOFTAP_BSS_STARTED, &link_info->link_flags);
if (hapd_state->bss_state == BSS_START) { if (hapd_state->bss_state == BSS_START) {
policy_mgr_incr_active_session(hdd_ctx->psoc, policy_mgr_incr_active_session(hdd_ctx->psoc,

View File

@@ -71,7 +71,8 @@
#define MEDIUM_ASSESS_TIMER_INTERVAL 1000 /* 1000ms */ #define MEDIUM_ASSESS_TIMER_INTERVAL 1000 /* 1000ms */
static qdf_mc_timer_t hdd_medium_assess_timer; static qdf_mc_timer_t hdd_medium_assess_timer;
static uint8_t timer_enable, ssr_flag; static bool ssr_flag;
static bool timer_enable;
struct hdd_medium_assess_info medium_assess_info[WLAN_UMAC_MAX_RP_PID]; struct hdd_medium_assess_info medium_assess_info[WLAN_UMAC_MAX_RP_PID];
unsigned long stime; unsigned long stime;
@@ -377,9 +378,12 @@ void hdd_medium_assess_ssr_enable_flag(void)
{ {
uint8_t i; uint8_t i;
ssr_flag = 1; ssr_flag = true;
for (i = 0; i < WLAN_UMAC_MAX_RP_PID; i++) for (i = 0; i < WLAN_UMAC_MAX_RP_PID; i++)
hdd_congestion_reset_data(i); hdd_congestion_reset_data(i);
if (timer_enable)
qdf_mc_timer_destroy(&hdd_medium_assess_timer);
} }
void hdd_medium_assess_stop_timer(uint8_t pdev_id, struct hdd_context *hdd_ctx) void hdd_medium_assess_stop_timer(uint8_t pdev_id, struct hdd_context *hdd_ctx)
@@ -409,181 +413,6 @@ void hdd_medium_assess_stop_timer(uint8_t pdev_id, struct hdd_context *hdd_ctx)
} }
} }
/**
* hdd_medium_assess_congestion_report() - congestion report
* @hdd_ctx: pointer to HDD context
* @adapter: pointer to adapter
* @tb: list of attributes
*
* Return: success(0) or reason code for failure
*/
static int hdd_medium_assess_congestion_report(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter,
struct nlattr **tb)
{
QDF_STATUS status;
struct wlan_objmgr_vdev *vdev;
uint8_t enable, threshold, interval = 0;
uint8_t pdev_id, vdev_id;
int errno = 0;
if (!tb[CONGESTION_REPORT_ENABLE]) {
hdd_err_rl("Congestion report enable is not present");
return -EINVAL;
}
vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_CP_STATS_ID);
if (!vdev)
return -EINVAL;
vdev_id = adapter->deflink->vdev_id;
status = policy_mgr_get_mac_id_by_session_id(hdd_ctx->psoc, vdev_id,
&pdev_id);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("get mac id failed");
goto out;
}
medium_assess_info[pdev_id].vdev_id = vdev_id;
medium_assess_info[pdev_id].pdev_id = pdev_id;
enable = nla_get_u8(tb[CONGESTION_REPORT_ENABLE]);
switch (enable) {
case REPORT_DISABLE:
hdd_debug("medium assess disable: pdev_id %d, vdev_id: %d",
pdev_id, vdev_id);
hdd_medium_assess_stop_timer(pdev_id, hdd_ctx);
break;
case REPORT_ENABLE:
if (!tb[CONGESTION_REPORT_THRESHOLD]) {
hdd_err_rl("Congestion threshold is not present");
errno = -EINVAL;
goto out;
}
threshold = nla_get_u8(tb[CONGESTION_REPORT_THRESHOLD]);
if (threshold > MAX_CONGESTION_THRESHOLD) {
hdd_err_rl("Invalid threshold %d", threshold);
errno = -EINVAL;
goto out;
}
if (tb[CONGESTION_REPORT_INTERVAL]) {
interval = nla_get_u8(tb[CONGESTION_REPORT_INTERVAL]);
if (interval >= MEDIUM_ASSESS_NUM)
interval = MEDIUM_ASSESS_NUM - 1;
} else {
interval = 1;
}
medium_assess_info[pdev_id].config.threshold = threshold;
medium_assess_info[pdev_id].config.interval = interval;
medium_assess_info[pdev_id].index = 0;
medium_assess_info[pdev_id].count = 0;
hdd_congestion_reset_data(pdev_id);
hdd_debug("medium assess enable: pdev_id %d, vdev_id: %d",
pdev_id, vdev_id);
if (qdf_mc_timer_get_current_state(&hdd_medium_assess_timer) ==
QDF_TIMER_STATE_STOPPED) {
hdd_debug("medium assess atimer start");
qdf_mc_timer_start(&hdd_medium_assess_timer,
MEDIUM_ASSESS_TIMER_INTERVAL);
}
break;
default:
hdd_err_rl("Invalid enable: %d", enable);
errno = -EINVAL;
break;
}
out:
hdd_objmgr_put_vdev_by_user(vdev, WLAN_CP_STATS_ID);
return errno;
}
/**
* __hdd_cfg80211_medium_assess() - medium assess
* @wiphy: pointer to wireless phy
* @wdev: wireless device
* @data: data
* @data_len: data length
*
* Return: success(0) or reason code for failure
*/
static int __hdd_cfg80211_medium_assess(struct wiphy *wiphy,
struct wireless_dev *wdev,
const void *data,
int data_len)
{
struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
struct net_device *dev = wdev->netdev;
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
enum QDF_GLOBAL_MODE driver_mode = hdd_get_conparam();
struct nlattr *tb[MEDIUM_ASSESS_MAX + 1];
uint8_t type;
int errno;
hdd_enter_dev(dev);
if (driver_mode == QDF_GLOBAL_FTM_MODE ||
driver_mode == QDF_GLOBAL_MONITOR_MODE) {
hdd_err_rl("Command not allowed in FTM / Monitor mode");
return -EPERM;
}
errno = wlan_hdd_validate_context(hdd_ctx);
if (errno)
return errno;
errno = wlan_cfg80211_nla_parse(tb, MEDIUM_ASSESS_MAX, data, data_len,
hdd_medium_assess_policy);
if (errno) {
hdd_err_rl("Invalid ATTR");
return errno;
}
if (!tb[MEDIUM_ASSESS_TYPE]) {
hdd_err_rl("Medium assess type is not present");
return -EINVAL;
}
type = nla_get_u8(tb[MEDIUM_ASSESS_TYPE]);
switch (type) {
case QCA_WLAN_MEDIUM_ASSESS_CCA:
errno = hdd_medium_assess_cca(hdd_ctx, adapter, tb);
break;
case QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT:
errno = hdd_medium_assess_congestion_report(hdd_ctx, adapter,
tb);
break;
default:
hdd_err_rl("Invalid medium assess type: %d", type);
return -EINVAL;
}
hdd_exit();
return errno;
}
int hdd_cfg80211_medium_assess(struct wiphy *wiphy,
struct wireless_dev *wdev,
const void *data,
int data_len)
{
struct osif_vdev_sync *vdev_sync;
int errno;
errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
if (errno)
return errno;
errno = __hdd_cfg80211_medium_assess(wiphy, wdev, data, data_len);
osif_vdev_sync_op_stop(vdev_sync);
return errno;
}
/** /**
* hdd_congestion_notification_calculation() - medium assess congestion * hdd_congestion_notification_calculation() - medium assess congestion
* calculation. * calculation.
@@ -745,39 +574,218 @@ static void hdd_medium_assess_expire_handler(void *arg)
MEDIUM_ASSESS_TIMER_INTERVAL); MEDIUM_ASSESS_TIMER_INTERVAL);
} }
void hdd_medium_assess_init(void) /**
* hdd_medium_assess_congestion_report() - congestion report
* @hdd_ctx: pointer to HDD context
* @adapter: pointer to adapter
* @tb: list of attributes
*
* Return: success(0) or reason code for failure
*/
static int hdd_medium_assess_congestion_report(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter,
struct nlattr **tb)
{
QDF_STATUS status;
struct wlan_objmgr_vdev *vdev;
uint8_t enable, threshold, interval = 0;
uint8_t pdev_id, vdev_id;
int errno = 0;
if (!tb[CONGESTION_REPORT_ENABLE]) {
hdd_err_rl("Congestion report enable is not present");
return -EINVAL;
}
vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_CP_STATS_ID);
if (!vdev)
return -EINVAL;
vdev_id = adapter->deflink->vdev_id;
status = policy_mgr_get_mac_id_by_session_id(hdd_ctx->psoc, vdev_id,
&pdev_id);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("get mac id failed");
goto out;
}
medium_assess_info[pdev_id].vdev_id = vdev_id;
medium_assess_info[pdev_id].pdev_id = pdev_id;
enable = nla_get_u8(tb[CONGESTION_REPORT_ENABLE]);
switch (enable) {
case REPORT_DISABLE:
hdd_debug("medium assess disable: pdev_id %d, vdev_id: %d",
pdev_id, vdev_id);
hdd_medium_assess_stop_timer(pdev_id, hdd_ctx);
if (timer_enable &&
(qdf_mc_timer_get_current_state(&hdd_medium_assess_timer) ==
QDF_TIMER_STATE_STOPPED)) {
qdf_mc_timer_destroy(&hdd_medium_assess_timer);
timer_enable = false;
}
break;
case REPORT_ENABLE:
if (!tb[CONGESTION_REPORT_THRESHOLD]) {
hdd_err_rl("Congestion threshold is not present");
errno = -EINVAL;
goto out;
}
threshold = nla_get_u8(tb[CONGESTION_REPORT_THRESHOLD]);
if (threshold > MAX_CONGESTION_THRESHOLD) {
hdd_err_rl("Invalid threshold %d", threshold);
errno = -EINVAL;
goto out;
}
if (tb[CONGESTION_REPORT_INTERVAL]) {
interval = nla_get_u8(tb[CONGESTION_REPORT_INTERVAL]);
if (interval >= MEDIUM_ASSESS_NUM)
interval = MEDIUM_ASSESS_NUM - 1;
} else {
interval = 1;
}
medium_assess_info[pdev_id].config.threshold = threshold;
medium_assess_info[pdev_id].config.interval = interval;
medium_assess_info[pdev_id].index = 0;
medium_assess_info[pdev_id].count = 0;
hdd_congestion_reset_data(pdev_id);
hdd_debug("medium assess enable: pdev_id %d, vdev_id: %d",
pdev_id, vdev_id);
if (!timer_enable) {
status =
qdf_mc_timer_init(&hdd_medium_assess_timer,
QDF_TIMER_TYPE_SW,
hdd_medium_assess_expire_handler,
NULL);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_debug("medium assess init timer failed");
errno = -EINVAL;
goto out;
}
timer_enable = true;
}
if (qdf_mc_timer_get_current_state(&hdd_medium_assess_timer) !=
QDF_TIMER_STATE_RUNNING) {
hdd_debug("medium assess atimer start");
qdf_mc_timer_start(&hdd_medium_assess_timer,
MEDIUM_ASSESS_TIMER_INTERVAL);
}
break;
default:
hdd_err_rl("Invalid enable: %d", enable);
errno = -EINVAL;
break;
}
out:
hdd_objmgr_put_vdev_by_user(vdev, WLAN_CP_STATS_ID);
return errno;
}
/**
* __hdd_cfg80211_medium_assess() - medium assess
* @wiphy: pointer to wireless phy
* @wdev: wireless device
* @data: data
* @data_len: data length
*
* Return: success(0) or reason code for failure
*/
static int __hdd_cfg80211_medium_assess(struct wiphy *wiphy,
struct wireless_dev *wdev,
const void *data,
int data_len)
{
struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
struct net_device *dev = wdev->netdev;
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
enum QDF_GLOBAL_MODE driver_mode = hdd_get_conparam();
struct nlattr *tb[MEDIUM_ASSESS_MAX + 1];
uint8_t type;
int errno;
hdd_enter_dev(dev);
if (driver_mode == QDF_GLOBAL_FTM_MODE ||
driver_mode == QDF_GLOBAL_MONITOR_MODE) {
hdd_err_rl("Command not allowed in FTM / Monitor mode");
return -EPERM;
}
errno = wlan_hdd_validate_context(hdd_ctx);
if (errno)
return errno;
errno = wlan_cfg80211_nla_parse(tb, MEDIUM_ASSESS_MAX, data, data_len,
hdd_medium_assess_policy);
if (errno) {
hdd_err_rl("Invalid ATTR");
return errno;
}
if (!tb[MEDIUM_ASSESS_TYPE]) {
hdd_err_rl("Medium assess type is not present");
return -EINVAL;
}
type = nla_get_u8(tb[MEDIUM_ASSESS_TYPE]);
switch (type) {
case QCA_WLAN_MEDIUM_ASSESS_CCA:
errno = hdd_medium_assess_cca(hdd_ctx, adapter, tb);
break;
case QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT:
errno = hdd_medium_assess_congestion_report(hdd_ctx, adapter,
tb);
break;
default:
hdd_err_rl("Invalid medium assess type: %d", type);
return -EINVAL;
}
hdd_exit();
return errno;
}
int hdd_cfg80211_medium_assess(struct wiphy *wiphy,
struct wireless_dev *wdev,
const void *data,
int data_len)
{
struct osif_vdev_sync *vdev_sync;
int errno;
errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
if (errno)
return errno;
errno = __hdd_cfg80211_medium_assess(wiphy, wdev, data, data_len);
osif_vdev_sync_op_stop(vdev_sync);
return errno;
}
void hdd_medium_assess_ssr_reinit(void)
{ {
QDF_STATUS status; QDF_STATUS status;
if (!timer_enable) { if (timer_enable && ssr_flag) {
hdd_debug("medium assess init timer"); hdd_debug("medium assess init timer in ssr");
status = qdf_mc_timer_init(&hdd_medium_assess_timer, status = qdf_mc_timer_init(&hdd_medium_assess_timer,
QDF_TIMER_TYPE_SW, QDF_TIMER_TYPE_SW,
hdd_medium_assess_expire_handler, hdd_medium_assess_expire_handler,
NULL); NULL);
if (QDF_IS_STATUS_ERROR(status)) { if (QDF_IS_STATUS_ERROR(status)) {
hdd_debug("medium assess init timer failed"); hdd_debug("medium assess init timer failed in ssr");
return; return;
} }
if (ssr_flag) { ssr_flag = false;
ssr_flag = 0; qdf_mc_timer_start(&hdd_medium_assess_timer,
qdf_mc_timer_start(&hdd_medium_assess_timer, MEDIUM_ASSESS_TIMER_INTERVAL);
MEDIUM_ASSESS_TIMER_INTERVAL);
}
}
timer_enable += 1;
}
void hdd_medium_assess_deinit(void)
{
timer_enable -= 1;
if (!timer_enable) {
hdd_debug("medium assess deinit timer");
if (qdf_mc_timer_get_current_state(&hdd_medium_assess_timer) ==
QDF_TIMER_STATE_RUNNING)
qdf_mc_timer_stop(&hdd_medium_assess_timer);
qdf_mc_timer_destroy(&hdd_medium_assess_timer);
} }
} }

View File

@@ -104,18 +104,11 @@ int hdd_cfg80211_medium_assess(struct wiphy *wiphy,
}, },
/** /**
* hdd_medium_assess_init() - medium assess init timer * hdd_medium_assess_ssr_reinit() - medium assess reinit timer in ssr
* *
* Return: none * Return: none
*/ */
void hdd_medium_assess_init(void); void hdd_medium_assess_ssr_reinit(void);
/**
* hdd_medium_assess_deinit() - medium assess deinit timer
*
* Return: none
*/
void hdd_medium_assess_deinit(void);
/** /**
* hdd_medium_assess_stop_timer() - medium assess reset and stop timer * hdd_medium_assess_stop_timer() - medium assess reset and stop timer
@@ -135,8 +128,7 @@ void hdd_medium_assess_ssr_enable_flag(void);
#else #else
#define FEATURE_MEDIUM_ASSESS_VENDOR_COMMANDS #define FEATURE_MEDIUM_ASSESS_VENDOR_COMMANDS
#define FEATURE_MEDIUM_ASSESS_VENDOR_EVENTS #define FEATURE_MEDIUM_ASSESS_VENDOR_EVENTS
static inline void hdd_medium_assess_init(void) {} static inline void hdd_medium_assess_ssr_reinit(void) {}
static inline void hdd_medium_assess_deinit(void) {}
static inline void hdd_medium_assess_stop_timer(uint8_t pdev_id, static inline void hdd_medium_assess_stop_timer(uint8_t pdev_id,
struct hdd_context *hdd_ctx) {} struct hdd_context *hdd_ctx) {}
static inline void hdd_medium_assess_ssr_enable_flag(void) {} static inline void hdd_medium_assess_ssr_enable_flag(void) {}