Parcourir la source

qcacld-3.0: Add a new API to check 6 GHz channel information

Currently there is no support to check 6 GHz channel
information in the device console.
To address this issue add an API to fetch 6 GHz channel
information for given power type.

CRs-Fixed: 3723735
Change-Id: Ie999e0b2ebfa45ca33269d64b30bfc162cc283d6
Asutosh Mohapatra il y a 2 ans
Parent
commit
b7d2d7c56f
1 fichiers modifiés avec 101 ajouts et 0 suppressions
  1. 101 0
      core/hdd/src/wlan_hdd_ioctl.c

+ 101 - 0
core/hdd/src/wlan_hdd_ioctl.c

@@ -55,6 +55,8 @@
 #define SIOCIOCTLTX99 (SIOCDEVPRIVATE+13)
 #endif
 
+#define SIZE_OF_WIFI6E_CHAN_LIST       512
+
 /*
  * Size of Driver command strings from upper layer
  */
@@ -2646,6 +2648,102 @@ static int drv_cmd_set_wmmps(struct wlan_hdd_link_info *link_info,
 	return hdd_wmmps_helper(link_info->adapter, command);
 }
 
+#ifdef CONFIG_BAND_6GHZ
+/**
+ * drv_cmd_get_wifi6e_channels() - Handler for GET_WIFI6E_CHANNELS driver
+ *                                 command
+ * @link_info: Link info pointer in adapter
+ * @hdd_ctx: pointer to hdd context
+ * @command: command name
+ * @command_len: command buffer length
+ * @priv_data: output pointer to hold current country code
+ *
+ * Return: On success 0, negative value on error.
+ */
+static int drv_cmd_get_wifi6e_channels(struct wlan_hdd_link_info *link_info,
+				       struct hdd_context *hdd_ctx,
+				       uint8_t *command,
+				       uint8_t command_len,
+				       struct hdd_priv_data *priv_data)
+{
+	uint8_t power_type;
+	char extra[SIZE_OF_WIFI6E_CHAN_LIST] = {0};
+	int i, ret, copied_length = 0;
+	enum channel_state state;
+	struct regulatory_channel *chan_list;
+	size_t max_buf_len = QDF_MIN(priv_data->total_len,
+				     SIZE_OF_WIFI6E_CHAN_LIST);
+	QDF_STATUS status;
+
+	if (wlan_hdd_validate_context(hdd_ctx))
+		return -EINVAL;
+
+	ret = kstrtou8(command + command_len + 1, 10, &power_type);
+	if (ret) {
+		hdd_err("error %d parsing userspace 6 GHz power type parameter",
+			ret);
+		return -EINVAL;
+	}
+
+	switch (power_type) {
+	case 0:
+		power_type = REG_CLI_DEF_LPI;
+		break;
+	case 1:
+		power_type = REG_CLI_DEF_VLP;
+		break;
+	case 2:
+		power_type = REG_CLI_DEF_SP;
+		break;
+	default:
+		hdd_err("The power type : %u, is incorrect", power_type);
+		return -EINVAL;
+	}
+
+	chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*chan_list));
+	if (!chan_list)
+		return -ENOMEM;
+
+	status = wlan_reg_get_pwrmode_chan_list(hdd_ctx->pdev, chan_list,
+						power_type);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to get wifi6e channel list for given power type %u",
+			power_type);
+		ret =  qdf_status_to_os_return(status);
+		goto free;
+	}
+
+	for (i = 0; i < NUM_6GHZ_CHANNELS && copied_length < max_buf_len - 1;
+	     i++) {
+		state = chan_list[i + MIN_6GHZ_CHANNEL].state;
+		if (state == CHANNEL_STATE_INVALID ||
+		    state == CHANNEL_STATE_DISABLE)
+			continue;
+		copied_length += scnprintf(extra + copied_length,
+				max_buf_len - copied_length, "%u ",
+				chan_list[i + MIN_6GHZ_CHANNEL].chan_num);
+	}
+
+	if (copied_length == 0) {
+		hdd_err("No Channel List found for given power type %u",
+			power_type);
+		ret = -EINVAL;
+		goto free;
+	}
+
+	if (copy_to_user(priv_data->buf, &extra, copied_length + 1)) {
+		hdd_err("failed to copy data to user buffer");
+		ret = -EFAULT;
+		goto free;
+	}
+
+	hdd_debug("Power type = %u, Data = %s", power_type, extra);
+free:
+	qdf_mem_free(chan_list);
+	return ret;
+}
+#endif
+
 static inline int __drv_cmd_country(struct wlan_hdd_link_info *link_info,
 				    struct hdd_context *hdd_ctx,
 				    uint8_t *command,
@@ -7342,6 +7440,9 @@ static const struct hdd_drv_cmd hdd_drv_cmds[] = {
 	{"BTCOEXSCAN-START",          drv_cmd_dummy, false},
 	{"BTCOEXSCAN-STOP",           drv_cmd_dummy, false},
 	{"GET_SOFTAP_LINK_SPEED",     drv_cmd_get_sap_go_linkspeed, true},
+#ifdef CONFIG_BAND_6GHZ
+	{"GET_WIFI6E_CHANNELS",       drv_cmd_get_wifi6e_channels, true},
+#endif
 };
 
 /**