mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-30 18:07:52 +00:00 
			
		
		
		
	Wifi-3309: Fix Tx power reporting
- AP was not reporting the Channel Tx power currently set in the firmware. This patch reads the Tx power from debugFS stats and reports it to cloud through Wifi_Radio_State table Signed-off-by: Yashvardhan <yashvardhan@netexperience.com>
This commit is contained in:
		| @@ -6,6 +6,7 @@ | |||||||
| #include <libubox/blobmsg.h> | #include <libubox/blobmsg.h> | ||||||
|  |  | ||||||
| #define min(a,b) (((a) < (b)) ? (a) : (b)) | #define min(a,b) (((a) < (b)) ? (a) : (b)) | ||||||
|  | #define ATH_DRIVER_NAME_LEN 16 | ||||||
|  |  | ||||||
| struct mode_map { | struct mode_map { | ||||||
| 	int fiveg; | 	int fiveg; | ||||||
| @@ -44,4 +45,5 @@ extern char* get_max_channel_bw_channel(int channel_freq, const char* htmode); | |||||||
| int phy_find_hwmon_helper(char *dir, char *file, char *hwmon); | int phy_find_hwmon_helper(char *dir, char *file, char *hwmon); | ||||||
| extern double dBm_to_mwatts(double dBm); | extern double dBm_to_mwatts(double dBm); | ||||||
| extern double mWatts_to_dBm(double mW); | extern double mWatts_to_dBm(double mW); | ||||||
|  | extern int phy_get_ath_driver_name(char *phy, char *ath_driver); | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -216,6 +216,76 @@ static void update_channel_max_power(char* phy, struct schema_Wifi_Radio_State * | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int get_channel_tx_power_debugfs(char *stats_path, int *tx_power) | ||||||
|  | { | ||||||
|  | 	bool found = false; | ||||||
|  | 	char str[512]; | ||||||
|  | 	FILE * fp = NULL; | ||||||
|  | 	int txpower = -1; | ||||||
|  | 	int ret = -1; | ||||||
|  |  | ||||||
|  | 	fp = fopen(stats_path, "r"); | ||||||
|  | 	if (!fp) { | ||||||
|  | 		LOGE("%s: Failed to get tx power, stats file does not exist", __func__); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const char *substr = "Channel TX power"; | ||||||
|  |  | ||||||
|  | 	while(fgets(str, 512, fp)) { | ||||||
|  | 		if((strstr(str, substr)) != NULL) { | ||||||
|  | 			char * plast = NULL, * pcur = str; | ||||||
|  | 			while ((pcur = strtok( pcur, " "))) { | ||||||
|  | 				plast = pcur; | ||||||
|  | 				pcur = NULL; | ||||||
|  | 			} | ||||||
|  | 			txpower = atoi(plast); | ||||||
|  | 			found = true; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (!found) { | ||||||
|  | 		LOGE("%s: Unable to find Tx Power in stats", __func__); | ||||||
|  | 	} else { | ||||||
|  | 		/* txpower is set as 2 units per dBm in FW */ | ||||||
|  | 		*tx_power = txpower/2; | ||||||
|  | 		ret = 0; | ||||||
|  | 	} | ||||||
|  | 	if (fp) | ||||||
|  | 		fclose(fp); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int get_channel_tx_power(char* phy, int *tx_power) | ||||||
|  | { | ||||||
|  | 	char ath_driver[ATH_DRIVER_NAME_LEN] = {'\0'}; | ||||||
|  | 	char stats_path[128]; | ||||||
|  |  | ||||||
|  | 	if (phy_get_ath_driver_name(phy, ath_driver)) { | ||||||
|  | 		LOGE("%s: Failed to get ATH driver name", __func__); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	if (!strncmp(ath_driver, "ath10k", ATH_DRIVER_NAME_LEN)) { | ||||||
|  | 		snprintf(stats_path, sizeof(stats_path), | ||||||
|  | 				"/sys/kernel/debug/ieee80211/%s/%s/fw_stats", phy, | ||||||
|  | 				ath_driver); | ||||||
|  | 	} else if (!strncmp(ath_driver, "ath11k", ATH_DRIVER_NAME_LEN)) { | ||||||
|  | 		snprintf(stats_path, sizeof(stats_path), | ||||||
|  | 				"/sys/kernel/debug/ieee80211/%s/%s/fw_stats/pdev_stats", phy, | ||||||
|  | 				ath_driver); | ||||||
|  | 	} else { | ||||||
|  | 		LOGE("%s: Unknown ATH driver", __func__); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (get_channel_tx_power_debugfs(stats_path, tx_power)) { | ||||||
|  | 		LOGE("%s: Failed to get Channel Tx Power", __func__); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| const struct uci_blob_param_list wifi_device_param = { | const struct uci_blob_param_list wifi_device_param = { | ||||||
| 	.n_params = __WDEV_ATTR_MAX, | 	.n_params = __WDEV_ATTR_MAX, | ||||||
| 	.params = wifi_device_policy, | 	.params = wifi_device_policy, | ||||||
| @@ -227,6 +297,7 @@ static bool radio_state_update(struct uci_section *s, struct schema_Wifi_Radio_C | |||||||
| 	struct schema_Wifi_Radio_State  rstate; | 	struct schema_Wifi_Radio_State  rstate; | ||||||
| 	char phy[6]; | 	char phy[6]; | ||||||
| 	int antenna; | 	int antenna; | ||||||
|  | 	int tx_power = -1; | ||||||
| 	uint32_t chan = 0; | 	uint32_t chan = 0; | ||||||
|  |  | ||||||
| 	LOGT("%s: get state", s->e.name); | 	LOGT("%s: get state", s->e.name); | ||||||
| @@ -267,13 +338,14 @@ static bool radio_state_update(struct uci_section *s, struct schema_Wifi_Radio_C | |||||||
| 	else | 	else | ||||||
| 		SCHEMA_SET_INT(rstate.enabled, 1); | 		SCHEMA_SET_INT(rstate.enabled, 1); | ||||||
|  |  | ||||||
| 	if (tb[WDEV_ATTR_TXPOWER]) { | 	if (!get_channel_tx_power(phy, &tx_power)) { | ||||||
| 		SCHEMA_SET_INT(rstate.tx_power, blobmsg_get_u32(tb[WDEV_ATTR_TXPOWER])); | 		SCHEMA_SET_INT(rstate.tx_power, tx_power); | ||||||
| 		/* 0 means max in UCI, 32 is max in OVSDB */ | 	} else { | ||||||
| 		if (rstate.tx_power == 0) | 		LOGE("%s: Failed to update Channel Tx Power", __func__); | ||||||
| 			rstate.tx_power = 32; | 		/* Set Tx Power to max OVSDB value */ | ||||||
| 	} else |  | ||||||
| 		SCHEMA_SET_INT(rstate.tx_power, 32); | 		SCHEMA_SET_INT(rstate.tx_power, 32); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	if (tb[WDEV_ATTR_BEACON_INT]) | 	if (tb[WDEV_ATTR_BEACON_INT]) | ||||||
| 		SCHEMA_SET_INT(rstate.bcn_int, blobmsg_get_u32(tb[WDEV_ATTR_BEACON_INT])); | 		SCHEMA_SET_INT(rstate.bcn_int, blobmsg_get_u32(tb[WDEV_ATTR_BEACON_INT])); | ||||||
|   | |||||||
| @@ -418,6 +418,22 @@ int phy_lookup(char *name) | |||||||
| 	return atoi(buf); | 	return atoi(buf); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int phy_get_ath_driver_name(char *phy, char *ath_driver) | ||||||
|  | { | ||||||
|  | 	glob_t gl; | ||||||
|  | 	char path[128]; | ||||||
|  | 	snprintf(path, sizeof(path), | ||||||
|  | 			"/sys/kernel/debug/ieee80211/%s/[ath]*", phy); | ||||||
|  | 	if (glob(path, GLOB_NOSORT | GLOB_MARK, NULL, &gl)) | ||||||
|  | 		return -1; | ||||||
|  | 	if (gl.gl_pathc) { | ||||||
|  | 		memset(ath_driver, '\0', ATH_DRIVER_NAME_LEN); | ||||||
|  | 		strncpy(ath_driver, basename(gl.gl_pathv[0]), ATH_DRIVER_NAME_LEN - 1); | ||||||
|  | 	} | ||||||
|  | 	globfree(&gl); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| int vif_get_mac(char *vap, char *mac) | int vif_get_mac(char *vap, char *mac) | ||||||
| { | { | ||||||
| 	int sz = ETH_ALEN * 3; | 	int sz = ETH_ALEN * 3; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Yashvardhan
					Yashvardhan