|
@@ -15253,6 +15253,104 @@ nla_policy get_chain_rssi_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
|
|
|
.len = QDF_MAC_ADDR_SIZE},
|
|
|
};
|
|
|
|
|
|
+static const struct nla_policy
|
|
|
+get_chan_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX + 1] = {
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK] = {.type = NLA_U32},
|
|
|
+};
|
|
|
+
|
|
|
+static const struct nla_policy
|
|
|
+get_usable_channel_policy[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1] = {
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID] = {
|
|
|
+ .type = NLA_U32
|
|
|
+ },
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK] = {
|
|
|
+ .type = NLA_U32
|
|
|
+ },
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK] = {
|
|
|
+ .type = NLA_U32
|
|
|
+ },
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK] = {
|
|
|
+ .type = NLA_U32
|
|
|
+ },
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO] = {
|
|
|
+ .type = NLA_NESTED
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * __wlan_hdd_cfg80211_get_usable_channel() - get chain rssi
|
|
|
+ * @wiphy: wiphy pointer
|
|
|
+ * @wdev: pointer to struct wireless_dev
|
|
|
+ * @data: pointer to incoming NL vendor data
|
|
|
+ * @data_len: length of @data
|
|
|
+ *
|
|
|
+ * Return: 0 on success; error number otherwise.
|
|
|
+ */
|
|
|
+static int __wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
|
|
|
+ struct wireless_dev *wdev,
|
|
|
+ const void *data,
|
|
|
+ int data_len)
|
|
|
+{
|
|
|
+ struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
|
|
|
+ struct get_usable_chan_req_params req_msg = {0};
|
|
|
+ struct get_usable_chan_res_params res_msg[NUM_CHANNELS];
|
|
|
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1];
|
|
|
+ int retval;
|
|
|
+ uint32_t count;
|
|
|
+ QDF_STATUS status;
|
|
|
+
|
|
|
+ retval = wlan_hdd_validate_context(hdd_ctx);
|
|
|
+ if (0 != retval)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ if (wlan_cfg80211_nla_parse(
|
|
|
+ tb, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX,
|
|
|
+ data, data_len, get_usable_channel_policy)) {
|
|
|
+ hdd_err("Invalid ATTR");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]) {
|
|
|
+ hdd_err("band mask not present");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ req_msg.band_mask =
|
|
|
+ nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]);
|
|
|
+
|
|
|
+ if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]) {
|
|
|
+ hdd_err("iface mode mask not present");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ req_msg.iface_mode_mask = nla_get_u32(
|
|
|
+ tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]);
|
|
|
+
|
|
|
+ if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]) {
|
|
|
+ hdd_err("usable channels filter mask not present");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ req_msg.filter_mask =
|
|
|
+ nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]);
|
|
|
+
|
|
|
+ hdd_debug("get usable channel list for band %d mode %d filter %d",
|
|
|
+ req_msg.band_mask, req_msg.iface_mode_mask,
|
|
|
+ req_msg.filter_mask);
|
|
|
+
|
|
|
+ status = wlan_reg_get_usable_channel(hdd_ctx->pdev, req_msg,
|
|
|
+ res_msg, &count);
|
|
|
+ if (QDF_STATUS_SUCCESS != status) {
|
|
|
+ hdd_err("get usable channel failed %d", status);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ hdd_debug("usable channel count : %d", count);
|
|
|
+
|
|
|
+ return qdf_status_to_os_return(status);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
|
|
|
* @wiphy: wiphy pointer
|
|
@@ -15341,6 +15439,35 @@ static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * wlan_hdd_cfg80211_get_usable_channel() - get chain rssi
|
|
|
+ * @wiphy: wiphy pointer
|
|
|
+ * @wdev: pointer to struct wireless_dev
|
|
|
+ * @data: pointer to incoming NL vendor data
|
|
|
+ * @data_len: length of @data
|
|
|
+ *
|
|
|
+ * Return: 0 on success; error number otherwise.
|
|
|
+ */
|
|
|
+static int wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
|
|
|
+ struct wireless_dev *wdev,
|
|
|
+ const void *data,
|
|
|
+ int data_len)
|
|
|
+{
|
|
|
+ int errno;
|
|
|
+ struct osif_vdev_sync *vdev_sync;
|
|
|
+
|
|
|
+ errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
|
|
|
+ if (errno)
|
|
|
+ return errno;
|
|
|
+
|
|
|
+ errno = __wlan_hdd_cfg80211_get_usable_channel(wiphy, wdev,
|
|
|
+ data, data_len);
|
|
|
+
|
|
|
+ osif_vdev_sync_op_stop(vdev_sync);
|
|
|
+
|
|
|
+ return errno;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
|
|
|
* @wiphy: wiphy pointer
|
|
@@ -16178,6 +16305,16 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
|
|
|
vendor_command_policy(get_chain_rssi_policy,
|
|
|
QCA_WLAN_VENDOR_ATTR_MAX)
|
|
|
},
|
|
|
+ {
|
|
|
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
|
|
|
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS,
|
|
|
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
|
|
|
+ WIPHY_VENDOR_CMD_NEED_NETDEV |
|
|
|
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
|
|
|
+ .doit = wlan_hdd_cfg80211_get_usable_channel,
|
|
|
+ vendor_command_policy(get_usable_channel_policy,
|
|
|
+ QCA_WLAN_VENDOR_ATTR_MAX)
|
|
|
+ },
|
|
|
|
|
|
FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
|
|
|
FEATURE_NAN_VENDOR_COMMANDS
|