|
@@ -12861,6 +12861,108 @@ static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
|
|
|
return errno;
|
|
|
}
|
|
|
|
|
|
+static uint32_t
|
|
|
+wlan_reg_wifi_band_bitmap_to_vendor_bitmap(uint32_t reg_wifi_band_bitmap)
|
|
|
+{
|
|
|
+ uint32_t vendor_mask = 0;
|
|
|
+
|
|
|
+ if (reg_wifi_band_bitmap & BIT(REG_BAND_2G))
|
|
|
+ vendor_mask |= QCA_SETBAND_2G;
|
|
|
+ if (reg_wifi_band_bitmap & BIT(REG_BAND_5G))
|
|
|
+ vendor_mask |= QCA_SETBAND_5G;
|
|
|
+ if (reg_wifi_band_bitmap & BIT(REG_BAND_6G))
|
|
|
+ vendor_mask |= QCA_SETBAND_6G;
|
|
|
+
|
|
|
+ return vendor_mask;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *__wlan_hdd_cfg80211_getband() - get band
|
|
|
+ * @wiphy: Pointer to wireless phy
|
|
|
+ * @wdev: Pointer to wireless device
|
|
|
+ * @data: Pointer to data
|
|
|
+ * @data_len: Length of @data
|
|
|
+ *
|
|
|
+ * Return: 0 on success, negative errno on failure
|
|
|
+ */
|
|
|
+static int __wlan_hdd_cfg80211_getband(struct wiphy *wiphy,
|
|
|
+ struct wireless_dev *wdev,
|
|
|
+ const void *data, int data_len)
|
|
|
+{
|
|
|
+ struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
|
|
|
+ struct sk_buff *skb;
|
|
|
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
|
|
|
+ int ret;
|
|
|
+ uint32_t reg_wifi_band_bitmap, vendor_band_mask;
|
|
|
+
|
|
|
+ hdd_enter();
|
|
|
+
|
|
|
+ ret = wlan_hdd_validate_context(hdd_ctx);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
|
|
|
+ sizeof(uint32_t) +
|
|
|
+ NLA_HDRLEN);
|
|
|
+
|
|
|
+ if (!skb) {
|
|
|
+ hdd_err("cfg80211_vendor_event_alloc failed");
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ status = ucfg_reg_get_band(hdd_ctx->pdev, ®_wifi_band_bitmap);
|
|
|
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
|
|
|
+ hdd_err("failed to get band");
|
|
|
+ goto failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ vendor_band_mask = wlan_reg_wifi_band_bitmap_to_vendor_bitmap(
|
|
|
+ reg_wifi_band_bitmap);
|
|
|
+
|
|
|
+ if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SETBAND_MASK,
|
|
|
+ vendor_band_mask)) {
|
|
|
+ hdd_err("nla put failure");
|
|
|
+ goto failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ cfg80211_vendor_cmd_reply(skb);
|
|
|
+
|
|
|
+ hdd_exit();
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+failure:
|
|
|
+ kfree_skb(skb);
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * wlan_hdd_cfg80211_getband() - Wrapper to getband
|
|
|
+ * @wiphy: wiphy structure pointer
|
|
|
+ * @wdev: Wireless device structure pointer
|
|
|
+ * @data: Pointer to the data received
|
|
|
+ * @data_len: Length of @data
|
|
|
+ *
|
|
|
+ * Return: 0 on success; errno on failure
|
|
|
+ */
|
|
|
+static int wlan_hdd_cfg80211_getband(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_getband(wiphy, wdev, data, data_len);
|
|
|
+
|
|
|
+ osif_vdev_sync_op_stop(vdev_sync);
|
|
|
+
|
|
|
+ return errno;
|
|
|
+}
|
|
|
+
|
|
|
static const struct
|
|
|
nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
|
|
|
[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
|
|
@@ -15128,6 +15230,15 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
|
|
|
.doit = wlan_hdd_cfg80211_setband,
|
|
|
vendor_command_policy(setband_policy, QCA_WLAN_VENDOR_ATTR_MAX)
|
|
|
},
|
|
|
+ {
|
|
|
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
|
|
|
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GETBAND,
|
|
|
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
|
|
|
+ WIPHY_VENDOR_CMD_NEED_NETDEV |
|
|
|
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
|
|
|
+ .doit = wlan_hdd_cfg80211_getband,
|
|
|
+ vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
|
|
|
+ },
|
|
|
{
|
|
|
.info.vendor_id = QCA_NL80211_VENDOR_ID,
|
|
|
.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
|