Jelajahi Sumber

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
Paul Zhang 1 tahun lalu
induk
melakukan
d8e7d9c0cc

+ 0 - 4
core/hdd/src/wlan_hdd_hostapd.c

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

+ 3 - 3
core/hdd/src/wlan_hdd_main.c

@@ -14625,6 +14625,9 @@ int hdd_start_ap_adapter(struct hdd_adapter *adapter, bool rtnl_held)
 	hdd_register_hl_netdev_fc_timer(adapter,
 					hdd_tx_resume_timer_expired_handler);
 
+	if (cds_is_driver_recovering())
+		hdd_medium_assess_ssr_reinit();
+
 	hdd_exit();
 	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");
 
-	if (reinit)
-		hdd_medium_assess_init();
 	wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
 	set_bit(SOFTAP_BSS_STARTED, &link_info->link_flags);
 	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);
 		hdd_err("SAP Start Success");
-		hdd_medium_assess_init();
 		set_bit(SOFTAP_BSS_STARTED, &link_info->link_flags);
 		if (hapd_state->bss_state == BSS_START) {
 			policy_mgr_incr_active_session(hdd_ctx->psoc,

+ 196 - 188
core/hdd/src/wlan_hdd_medium_assess.c

@@ -71,7 +71,8 @@
 
 #define MEDIUM_ASSESS_TIMER_INTERVAL 1000 /* 1000ms */
 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];
 unsigned long stime;
 
@@ -377,9 +378,12 @@ void hdd_medium_assess_ssr_enable_flag(void)
 {
 	uint8_t i;
 
-	ssr_flag = 1;
+	ssr_flag = true;
 	for (i = 0; i < WLAN_UMAC_MAX_RP_PID; 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)
@@ -409,6 +413,167 @@ void hdd_medium_assess_stop_timer(uint8_t pdev_id, struct hdd_context *hdd_ctx)
 	}
 }
 
+/**
+ * hdd_congestion_notification_calculation() - medium assess congestion
+ * calculation.
+ * @info: structure hdd_medium_assess_info
+ *
+ * Return: None
+ */
+static void
+hdd_congestion_notification_calculation(struct hdd_medium_assess_info *info)
+{
+	struct medium_assess_data *h_data, *t_data;
+	int32_t h_index, t_index;
+	uint32_t rx_clear_count_delta, tx_frame_count_delta;
+	uint32_t cycle_count_delta, my_rx_count_delta;
+	uint32_t congestion = 0;
+	uint64_t diff;
+
+	h_index = info->index - 1;
+	if (h_index < 0)
+		h_index = MEDIUM_ASSESS_NUM - 1;
+
+	if (h_index >= info->config.interval)
+		t_index = h_index - info->config.interval;
+	else
+		t_index = MEDIUM_ASSESS_NUM - info->config.interval - h_index;
+
+	if (h_index < 0 || h_index >= MEDIUM_ASSESS_NUM ||
+	    t_index < 0 || t_index >= MEDIUM_ASSESS_NUM) {
+		hdd_err("medium assess index is not valid.");
+		return;
+	}
+
+	h_data = &info->data[h_index];
+	t_data = &info->data[t_index];
+
+	if (!(h_data->part1_valid || h_data->part2_valid ||
+	      t_data->part1_valid || t_data->part2_valid)) {
+		hdd_err("medium assess data is not valid.");
+		return;
+	}
+
+	if (h_data->rx_clear_count >= t_data->rx_clear_count) {
+		rx_clear_count_delta = h_data->rx_clear_count -
+						t_data->rx_clear_count;
+	} else {
+		rx_clear_count_delta = U32_MAX - t_data->rx_clear_count;
+		rx_clear_count_delta += h_data->rx_clear_count;
+	}
+
+	if (h_data->tx_frame_count >= t_data->tx_frame_count) {
+		tx_frame_count_delta = h_data->tx_frame_count -
+						t_data->tx_frame_count;
+	} else {
+		tx_frame_count_delta = U32_MAX - t_data->tx_frame_count;
+		tx_frame_count_delta += h_data->tx_frame_count;
+	}
+
+	if (h_data->my_rx_count >= t_data->my_rx_count) {
+		my_rx_count_delta = h_data->my_rx_count - t_data->my_rx_count;
+	} else {
+		my_rx_count_delta = U32_MAX - t_data->my_rx_count;
+		my_rx_count_delta += h_data->my_rx_count;
+	}
+
+	if (h_data->cycle_count >= t_data->cycle_count) {
+		cycle_count_delta = h_data->cycle_count - t_data->cycle_count;
+	} else {
+		cycle_count_delta = U32_MAX - t_data->cycle_count;
+		cycle_count_delta += h_data->cycle_count;
+	}
+
+	if (rx_clear_count_delta > tx_frame_count_delta &&
+	    rx_clear_count_delta - tx_frame_count_delta > my_rx_count_delta) {
+		diff = rx_clear_count_delta - tx_frame_count_delta
+		       - my_rx_count_delta;
+		if (cycle_count_delta)
+			congestion = qdf_do_div(diff * 100, cycle_count_delta);
+
+		if (congestion > 100)
+			congestion = 100;
+	}
+
+	hdd_debug("pdev: %d, rx_c %u, tx %u myrx %u cycle %u congestion: %u",
+		  info->pdev_id, rx_clear_count_delta, tx_frame_count_delta,
+		  my_rx_count_delta, cycle_count_delta, congestion);
+	if (congestion >= info->config.threshold)
+		hdd_congestion_notification_report(info->vdev_id, congestion);
+}
+
+/**
+ * hdd_congestion_notification_report_multi() - medium assess report
+ * multi interface.
+ * @pdev_id: pdev id
+ *
+ * Return: None
+ */
+static void hdd_congestion_notification_report_multi(uint8_t pdev_id)
+{
+	struct hdd_medium_assess_info *info;
+
+	info = &medium_assess_info[pdev_id];
+	info->count++;
+	if (info->count % info->config.interval == 0)
+		hdd_congestion_notification_calculation(info);
+}
+
+/**
+ * hdd_medium_assess_expire_handler() - timer callback
+ * @arg: argument
+ *
+ * Return: None
+ */
+static void hdd_medium_assess_expire_handler(void *arg)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct request_info info = {0};
+	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	struct wlan_hdd_link_info *link_info;
+	uint8_t vdev_id = INVALID_VDEV_ID, pdev_id;
+	uint8_t index, i;
+
+	if (wlan_hdd_validate_context(hdd_ctx))
+		return;
+
+	for (i = 0; i < WLAN_UMAC_MAX_RP_PID; i++)
+		if (medium_assess_info[i].config.interval != 0) {
+			vdev_id = medium_assess_info[i].vdev_id;
+			pdev_id = medium_assess_info[i].pdev_id;
+			hdd_congestion_notification_report_multi(pdev_id);
+
+			/* ensure events are reveived at the 'same' time */
+			index = medium_assess_info[i].index;
+			medium_assess_info[i].data[index].part1_valid = false;
+			medium_assess_info[i].data[index].part2_valid = false;
+		}
+
+	if (vdev_id == INVALID_VDEV_ID)
+		return;
+
+	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
+	if (!link_info) {
+		hdd_err("Failed to find adapter of vdev %d", vdev_id);
+		return;
+	}
+
+	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_CP_STATS_ID);
+	if (!vdev)
+		return;
+
+	info.vdev_id = vdev_id;
+	info.pdev_id = WMI_HOST_PDEV_ID_SOC;
+	info.u.congestion_notif_cb = hdd_congestion_notification_cb;
+	stime = jiffies + msecs_to_jiffies(40);
+	ucfg_mc_cp_stats_send_stats_request(vdev,
+					    TYPE_CONGESTION_STATS,
+					    &info);
+	hdd_objmgr_put_vdev_by_user(vdev, WLAN_CP_STATS_ID);
+	qdf_mc_timer_start(&hdd_medium_assess_timer,
+			   MEDIUM_ASSESS_TIMER_INTERVAL);
+}
+
 /**
  * hdd_medium_assess_congestion_report() - congestion report
  * @hdd_ctx: pointer to HDD context
@@ -453,6 +618,12 @@ static int hdd_medium_assess_congestion_report(struct hdd_context *hdd_ctx,
 		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]) {
@@ -482,8 +653,22 @@ static int hdd_medium_assess_congestion_report(struct hdd_context *hdd_ctx,
 		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) {
+		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);
@@ -584,200 +769,23 @@ int hdd_cfg80211_medium_assess(struct wiphy *wiphy,
 	return errno;
 }
 
-/**
- * hdd_congestion_notification_calculation() - medium assess congestion
- * calculation.
- * @info: structure hdd_medium_assess_info
- *
- * Return: None
- */
-static void
-hdd_congestion_notification_calculation(struct hdd_medium_assess_info *info)
-{
-	struct medium_assess_data *h_data, *t_data;
-	int32_t h_index, t_index;
-	uint32_t rx_clear_count_delta, tx_frame_count_delta;
-	uint32_t cycle_count_delta, my_rx_count_delta;
-	uint32_t congestion = 0;
-	uint64_t diff;
-
-	h_index = info->index - 1;
-	if (h_index < 0)
-		h_index = MEDIUM_ASSESS_NUM - 1;
-
-	if (h_index >= info->config.interval)
-		t_index = h_index - info->config.interval;
-	else
-		t_index = MEDIUM_ASSESS_NUM - info->config.interval - h_index;
-
-	if (h_index < 0 || h_index >= MEDIUM_ASSESS_NUM ||
-	    t_index < 0 || t_index >= MEDIUM_ASSESS_NUM) {
-		hdd_err("medium assess index is not valid.");
-		return;
-	}
-
-	h_data = &info->data[h_index];
-	t_data = &info->data[t_index];
-
-	if (!(h_data->part1_valid || h_data->part2_valid ||
-	      t_data->part1_valid || t_data->part2_valid)) {
-		hdd_err("medium assess data is not valid.");
-		return;
-	}
-
-	if (h_data->rx_clear_count >= t_data->rx_clear_count) {
-		rx_clear_count_delta = h_data->rx_clear_count -
-						t_data->rx_clear_count;
-	} else {
-		rx_clear_count_delta = U32_MAX - t_data->rx_clear_count;
-		rx_clear_count_delta += h_data->rx_clear_count;
-	}
-
-	if (h_data->tx_frame_count >= t_data->tx_frame_count) {
-		tx_frame_count_delta = h_data->tx_frame_count -
-						t_data->tx_frame_count;
-	} else {
-		tx_frame_count_delta = U32_MAX - t_data->tx_frame_count;
-		tx_frame_count_delta += h_data->tx_frame_count;
-	}
-
-	if (h_data->my_rx_count >= t_data->my_rx_count) {
-		my_rx_count_delta = h_data->my_rx_count - t_data->my_rx_count;
-	} else {
-		my_rx_count_delta = U32_MAX - t_data->my_rx_count;
-		my_rx_count_delta += h_data->my_rx_count;
-	}
-
-	if (h_data->cycle_count >= t_data->cycle_count) {
-		cycle_count_delta = h_data->cycle_count - t_data->cycle_count;
-	} else {
-		cycle_count_delta = U32_MAX - t_data->cycle_count;
-		cycle_count_delta += h_data->cycle_count;
-	}
-
-	if (rx_clear_count_delta > tx_frame_count_delta &&
-	    rx_clear_count_delta - tx_frame_count_delta > my_rx_count_delta) {
-		diff = rx_clear_count_delta - tx_frame_count_delta
-		       - my_rx_count_delta;
-		if (cycle_count_delta)
-			congestion = qdf_do_div(diff * 100, cycle_count_delta);
-
-		if (congestion > 100)
-			congestion = 100;
-	}
-
-	hdd_debug("pdev: %d, rx_c %u, tx %u myrx %u cycle %u congestion: %u",
-		  info->pdev_id, rx_clear_count_delta, tx_frame_count_delta,
-		  my_rx_count_delta, cycle_count_delta, congestion);
-	if (congestion >= info->config.threshold)
-		hdd_congestion_notification_report(info->vdev_id, congestion);
-}
-
-/**
- * hdd_congestion_notification_report_multi() - medium assess report
- * multi interface.
- * @pdev_id: pdev id
- *
- * Return: None
- */
-static void hdd_congestion_notification_report_multi(uint8_t pdev_id)
-{
-	struct hdd_medium_assess_info *info;
-
-	info = &medium_assess_info[pdev_id];
-	info->count++;
-	if (info->count % info->config.interval == 0)
-		hdd_congestion_notification_calculation(info);
-}
-
-/**
- * hdd_medium_assess_expire_handler() - timer callback
- * @arg: argument
- *
- * Return: None
- */
-static void hdd_medium_assess_expire_handler(void *arg)
-{
-	struct wlan_objmgr_vdev *vdev;
-	struct request_info info = {0};
-	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
-	struct wlan_hdd_link_info *link_info;
-	uint8_t vdev_id = INVALID_VDEV_ID, pdev_id;
-	uint8_t index, i;
-
-	if (wlan_hdd_validate_context(hdd_ctx))
-		return;
-
-	for (i = 0; i < WLAN_UMAC_MAX_RP_PID; i++)
-		if (medium_assess_info[i].config.interval != 0) {
-			vdev_id = medium_assess_info[i].vdev_id;
-			pdev_id = medium_assess_info[i].pdev_id;
-			hdd_congestion_notification_report_multi(pdev_id);
-
-			/* ensure events are reveived at the 'same' time */
-			index = medium_assess_info[i].index;
-			medium_assess_info[i].data[index].part1_valid = false;
-			medium_assess_info[i].data[index].part2_valid = false;
-		}
-
-	if (vdev_id == INVALID_VDEV_ID)
-		return;
-
-	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
-	if (!link_info) {
-		hdd_err("Failed to find adapter of vdev %d", vdev_id);
-		return;
-	}
-
-	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_CP_STATS_ID);
-	if (!vdev)
-		return;
-
-	info.vdev_id = vdev_id;
-	info.pdev_id = WMI_HOST_PDEV_ID_SOC;
-	info.u.congestion_notif_cb = hdd_congestion_notification_cb;
-	stime = jiffies + msecs_to_jiffies(40);
-	ucfg_mc_cp_stats_send_stats_request(vdev,
-					    TYPE_CONGESTION_STATS,
-					    &info);
-	hdd_objmgr_put_vdev_by_user(vdev, WLAN_CP_STATS_ID);
-	qdf_mc_timer_start(&hdd_medium_assess_timer,
-			   MEDIUM_ASSESS_TIMER_INTERVAL);
-}
-
-void hdd_medium_assess_init(void)
+void hdd_medium_assess_ssr_reinit(void)
 {
 	QDF_STATUS status;
 
-	if (!timer_enable) {
-		hdd_debug("medium assess init timer");
+	if (timer_enable && ssr_flag) {
+		hdd_debug("medium assess init timer in ssr");
 		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");
+			hdd_debug("medium assess init timer failed in ssr");
 			return;
 		}
 
-		if (ssr_flag) {
-			ssr_flag = 0;
-			qdf_mc_timer_start(&hdd_medium_assess_timer,
-					   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);
+		ssr_flag = false;
+		qdf_mc_timer_start(&hdd_medium_assess_timer,
+				   MEDIUM_ASSESS_TIMER_INTERVAL);
 	}
 }

+ 3 - 11
core/hdd/src/wlan_hdd_medium_assess.h

@@ -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
  */
-void hdd_medium_assess_init(void);
-
-/**
- * hdd_medium_assess_deinit() - medium assess deinit timer
- *
- * Return: none
- */
-void hdd_medium_assess_deinit(void);
+void hdd_medium_assess_ssr_reinit(void);
 
 /**
  * hdd_medium_assess_stop_timer() - medium assess reset and stop timer
@@ -135,8 +128,7 @@ void hdd_medium_assess_ssr_enable_flag(void);
 #else
 #define FEATURE_MEDIUM_ASSESS_VENDOR_COMMANDS
 #define FEATURE_MEDIUM_ASSESS_VENDOR_EVENTS
-static inline void hdd_medium_assess_init(void) {}
-static inline void hdd_medium_assess_deinit(void) {}
+static inline void hdd_medium_assess_ssr_reinit(void) {}
 static inline void hdd_medium_assess_stop_timer(uint8_t pdev_id,
 						struct hdd_context *hdd_ctx) {}
 static inline void hdd_medium_assess_ssr_enable_flag(void) {}