Эх сурвалжийг харах

qca-wifi: Introduce regulatory APIs to access channel information

As part of the componentization of channel lists across WIN
components, the existing version of channel list in WIN umac is
removed. Introduce APIs in the regulatory that provide the
required information directly from the regulatory
channel lists.

Introduce the following APIs:
1. wlan_reg_get_txpow_ant_gain
    To get the txpower and antenna gain specified in the regulatory,
    for a given channel.
2. wlan_reg_get_chan_flags
    To get the channel flags (if channel DFS for example), from
    regulatory for the given channel.
3. wlan_reg_get_max_phymode_and_chwidth
    To get the maximum 80211 mode and channel width supported
    by the channel in the given regulatory.
4. wlan_reg_is_phymode_chwidth_allowed
    To check if the given 80211 mode and channel width is supported
    by the channel in the given regulatory.
5. reg_update_max_phymode_chwidth_for_pdev
    To update the maximum 80211 mode and channel width for the
    regulatory, inside regulatory object.
6. reg_modify_chan_list_for_max_chwidth
    Update the regulatory channel list with maximum bandwidth
    for each channel based on the availability of it's
    adjacent channels.

Change-Id: Idb390c10d8901d9e21d4642481168704d7e36333
Vignesh Mohan 4 жил өмнө
parent
commit
a9b8585838

+ 197 - 0
umac/regulatory/core/reg_channel.c

@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: reg_channel.c
+ * This file defines the API to access/update/modify regulatory current channel
+ * list by WIN host umac components.
+ */
+
+#include <wlan_cmn.h>
+#include <reg_services_public_struct.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <reg_priv_objs.h>
+#include <reg_services_common.h>
+#include <reg_channel.h>
+
+#ifdef CONFIG_HOST_FIND_CHAN
+
+static inline int is_11ax_supported(uint32_t wireless_modes, uint32_t phybitmap)
+{
+	return (WIRELESS_11AX_MODES & wireless_modes) &&
+		!(phybitmap & REGULATORY_PHYMODE_NO11AX);
+}
+
+static inline int is_11ac_supported(uint32_t wireless_modes, uint32_t phybitmap)
+{
+	return (WIRELESS_11AC_MODES & wireless_modes) &&
+		!(phybitmap & REGULATORY_PHYMODE_NO11AC);
+}
+
+static inline int is_11n_supported(uint32_t wireless_modes, uint32_t phybitmap)
+{
+	return (WIRELESS_11N_MODES & wireless_modes) &&
+		!(phybitmap & REGULATORY_CHAN_NO11N);
+}
+
+static inline int is_11g_supported(uint32_t wireless_modes, uint32_t phybitmap)
+{
+	return (WIRELESS_11G_MODES & wireless_modes) &&
+		!(phybitmap & REGULATORY_PHYMODE_NO11G);
+}
+
+static inline int is_11b_supported(uint32_t wireless_modes, uint32_t phybitmap)
+{
+	return (WIRELESS_11B_MODES & wireless_modes) &&
+		!(phybitmap & REGULATORY_PHYMODE_NO11B);
+}
+
+static inline int is_11a_supported(uint32_t wireless_modes, uint32_t phybitmap)
+{
+	return (WIRELESS_11A_MODES & wireless_modes) &&
+		!(phybitmap & REGULATORY_PHYMODE_NO11A);
+}
+
+void reg_update_max_phymode_chwidth_for_pdev(
+		struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
+{
+	uint32_t wireless_modes = pdev_priv_obj->wireless_modes;
+	uint32_t phybitmap = pdev_priv_obj->phybitmap;
+	enum phy_ch_width max_chwidth = CH_WIDTH_20MHZ;
+	enum reg_phymode max_phymode = REG_PHYMODE_MAX;
+
+	if (is_11ax_supported(wireless_modes, phybitmap)) {
+		max_phymode = REG_PHYMODE_11AX;
+		if (wireless_modes & WIRELESS_160_MODES)
+			max_chwidth = CH_WIDTH_160MHZ;
+		else if (wireless_modes & WIRELESS_80_MODES)
+			max_chwidth = CH_WIDTH_80MHZ;
+		else if (wireless_modes & WIRELESS_40_MODES)
+			max_chwidth = CH_WIDTH_40MHZ;
+	} else if (is_11ac_supported(wireless_modes, phybitmap)) {
+		max_phymode = REG_PHYMODE_11AC;
+		if (wireless_modes & WIRELESS_160_MODES)
+			max_chwidth = CH_WIDTH_160MHZ;
+		else if (wireless_modes & WIRELESS_80_MODES)
+			max_chwidth = CH_WIDTH_80MHZ;
+		else if (wireless_modes & WIRELESS_40_MODES)
+			max_chwidth = CH_WIDTH_40MHZ;
+	} else if (is_11n_supported(wireless_modes, phybitmap)) {
+		max_phymode = REG_PHYMODE_11N;
+		if (wireless_modes & WIRELESS_40_MODES)
+			max_chwidth = CH_WIDTH_40MHZ;
+	} else if (is_11g_supported(wireless_modes, phybitmap)) {
+		max_phymode = REG_PHYMODE_11G;
+	} else if (is_11b_supported(wireless_modes, phybitmap)) {
+		max_phymode = REG_PHYMODE_11B;
+	} else if (is_11a_supported(wireless_modes, phybitmap)) {
+		max_phymode = REG_PHYMODE_11A;
+	} else {
+		reg_err("Device does not support any wireless_mode! %0x",
+			wireless_modes);
+	}
+
+	pdev_priv_obj->max_phymode = max_phymode;
+	pdev_priv_obj->max_chwidth = max_chwidth;
+}
+
+void reg_modify_chan_list_for_max_chwidth(
+		struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
+		struct regulatory_channel *cur_chan_list)
+{
+	int i;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		struct ch_params chan_params;
+
+		if (cur_chan_list[i].chan_flags & REGULATORY_CHAN_DISABLED)
+			continue;
+
+		chan_params.ch_width = pdev_priv_obj->max_chwidth;
+
+		/*
+		 * Correct the max bandwidths if they were not taken care of
+		 * while parsing the reg rules.
+		 */
+		reg_set_channel_params_for_freq(pdev_priv_obj->pdev_ptr,
+						cur_chan_list[i].center_freq,
+						0,
+						&chan_params);
+
+		if (chan_params.ch_width != CH_WIDTH_INVALID)
+			cur_chan_list[i].max_bw =
+				qdf_min(cur_chan_list[i].max_bw,
+					reg_get_bw_value(chan_params.ch_width));
+	}
+}
+
+static uint32_t convregphymode2wirelessmodes[REG_PHYMODE_MAX] = {
+	0xFFFFFFFF,                  /* REG_PHYMODE_INVALID */
+	WIRELESS_11B_MODES,          /* REG_PHYMODE_11B     */
+	WIRELESS_11G_MODES,          /* REG_PHYMODE_11G     */
+	WIRELESS_11A_MODES,          /* REG_PHYMODE_11A     */
+	WIRELESS_11N_MODES,          /* REG_PHYMODE_11N     */
+	WIRELESS_11AC_MODES,         /* REG_PHYMODE_11AC    */
+	WIRELESS_11AX_MODES,         /* REG_PHYMODE_11AX    */
+};
+
+static int reg_is_phymode_in_wireless_modes(enum reg_phymode phy_in,
+					    uint32_t wireless_modes)
+{
+	uint32_t sup_wireless_modes = convregphymode2wirelessmodes[phy_in];
+
+	return sup_wireless_modes & wireless_modes;
+}
+
+bool reg_is_phymode_chwidth_allowed(
+		struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
+		enum reg_phymode phy_in,
+		enum phy_ch_width ch_width,
+		qdf_freq_t freq)
+{
+	uint32_t phymode_bitmap, wireless_modes;
+	uint16_t i, bw = reg_get_bw_value(ch_width);
+
+	if (ch_width == CH_WIDTH_INVALID)
+		return false;
+
+	phymode_bitmap = pdev_priv_obj->phybitmap;
+	wireless_modes = pdev_priv_obj->wireless_modes;
+
+	if (reg_is_phymode_unallowed(phy_in, phymode_bitmap) ||
+	    !reg_is_phymode_in_wireless_modes(phy_in, wireless_modes))
+		return false;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (pdev_priv_obj->cur_chan_list[i].center_freq != freq)
+			continue;
+
+		if (pdev_priv_obj->cur_chan_list[i].state ==
+		    CHANNEL_STATE_DISABLE)
+			return false;
+
+		if (bw < pdev_priv_obj->cur_chan_list[i].min_bw ||
+		    bw > pdev_priv_obj->cur_chan_list[i].max_bw)
+			return false;
+
+		return true;
+	}
+
+	return false;
+}
+
+#endif

+ 180 - 0
umac/regulatory/core/reg_channel.h

@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: reg_channel.h
+ * This file provides prototypes of the channel list APIs in addition to
+ * predefined macros.
+ */
+
+#ifndef __REG_CHANNEL_H_
+#define __REG_CHANNEL_H_
+
+#ifdef CONFIG_HOST_FIND_CHAN
+
+/**
+ * enum HOST_REGDMN_MODE:
+ * @HOST_REGDMN_MODE_11A: 11a channels
+ * @HOST_REGDMN_MODE_TURBO: 11a turbo-only channels
+ * @HOST_REGDMN_MODE_11B: 11b channels
+ * @HOST_REGDMN_MODE_PUREG: 11g channels (OFDM only)
+ * @HOST_REGDMN_MODE_11G: historical
+ * @HOST_REGDMN_MODE_108G: 11g+Turbo channels
+ * @HOST_REGDMN_MODE_108A: 11a+Turbo channels
+ * @HOST_REGDMN_MODE_11AC_VHT20_2G: 2GHz, VHT20
+ * @HOST_REGDMN_MODE_XR: XR channels
+ * @HOST_REGDMN_MODE_11A_HALF_RATE: 11a half rate channels
+ * @HOST_REGDMN_MODE_11A_QUARTER_RATE: 11a quarter rate channels
+ * @HOST_REGDMN_MODE_11NG_HT20: 11ng HT20 channels
+ * @HOST_REGDMN_MODE_11NA_HT20: 11na HT20 channels
+ * @HOST_REGDMN_MODE_11NG_HT40PLUS: 11ng HT40+ channels
+ * @HOST_REGDMN_MODE_11NG_HT40MINUS: 11ng HT40- channels
+ * @HOST_REGDMN_MODE_11NA_HT40PLUS: 11na HT40+ channels
+ * @HOST_REGDMN_MODE_11NA_HT40MINUS: 11na HT40- channels
+ * @HOST_REGDMN_MODE_11AC_VHT20: 5GHz, VHT20
+ * @HOST_REGDMN_MODE_11AC_VHT40PLUS: 5GHz, VHT40+ channels
+ * @HOST_REGDMN_MODE_11AC_VHT40MINUS: 5GHz, VHT40- channels
+ * @HOST_REGDMN_MODE_11AC_VHT80: 5GHz, VHT80 channels
+ * @HOST_REGDMN_MODE_11AC_VHT160: 5GHz, VHT160 channels
+ * @HOST_REGDMN_MODE_11AC_VHT80_80: 5GHz, VHT80+80 channels
+ * @HOST_REGDMN_MODE_11AXG_HE20: 11ax 2.4GHz, HE20 channels
+ * @HOST_REGDMN_MODE_11AXA_HE20: 11ax 5GHz, HE20 channels
+ * @HOST_REGDMN_MODE_11AXG_HE40PLUS: 11ax 2.4GHz, HE40+ channels
+ * @HOST_REGDMN_MODE_11AXG_HE40MINUS: 11ax 2.4GHz, HE40- channels
+ * @HOST_REGDMN_MODE_11AXA_HE40PLUS: 11ax 5GHz, HE40+ channels
+ * @HOST_REGDMN_MODE_11AXA_HE40MINUS: 11ax 5GHz, HE40- channels
+ * @HOST_REGDMN_MODE_11AXA_HE80: 11ax 5GHz, HE80 channels
+ * @HOST_REGDMN_MODE_11AXA_HE160: 11ax 5GHz, HE160 channels
+ * @HOST_REGDMN_MODE_11AXA_HE80_80: 11ax 5GHz, HE80+80 channels
+ */
+enum {
+	HOST_REGDMN_MODE_11A = 0x00000001,
+	HOST_REGDMN_MODE_TURBO = 0x00000002,
+	HOST_REGDMN_MODE_11B = 0x00000004,
+	HOST_REGDMN_MODE_PUREG = 0x00000008,
+	HOST_REGDMN_MODE_11G = 0x00000008,
+	HOST_REGDMN_MODE_108G = 0x00000020,
+	HOST_REGDMN_MODE_108A = 0x00000040,
+	HOST_REGDMN_MODE_11AC_VHT20_2G = 0x00000080,
+	HOST_REGDMN_MODE_XR = 0x00000100,
+	HOST_REGDMN_MODE_11A_HALF_RATE = 0x00000200,
+	HOST_REGDMN_MODE_11A_QUARTER_RATE = 0x00000400,
+	HOST_REGDMN_MODE_11NG_HT20 = 0x00000800,
+	HOST_REGDMN_MODE_11NA_HT20 = 0x00001000,
+	HOST_REGDMN_MODE_11NG_HT40PLUS = 0x00002000,
+	HOST_REGDMN_MODE_11NG_HT40MINUS = 0x00004000,
+	HOST_REGDMN_MODE_11NA_HT40PLUS = 0x00008000,
+	HOST_REGDMN_MODE_11NA_HT40MINUS = 0x00010000,
+	HOST_REGDMN_MODE_11AC_VHT20 = 0x00020000,
+	HOST_REGDMN_MODE_11AC_VHT40PLUS = 0x00040000,
+	HOST_REGDMN_MODE_11AC_VHT40MINUS = 0x00080000,
+	HOST_REGDMN_MODE_11AC_VHT80 = 0x00100000,
+	HOST_REGDMN_MODE_11AC_VHT160 = 0x00200000,
+	HOST_REGDMN_MODE_11AC_VHT80_80 = 0x00400000,
+	HOST_REGDMN_MODE_11AXG_HE20 = 0x00800000,
+	HOST_REGDMN_MODE_11AXA_HE20 = 0x01000000,
+	HOST_REGDMN_MODE_11AXG_HE40PLUS = 0x02000000,
+	HOST_REGDMN_MODE_11AXG_HE40MINUS = 0x04000000,
+	HOST_REGDMN_MODE_11AXA_HE40PLUS = 0x08000000,
+	HOST_REGDMN_MODE_11AXA_HE40MINUS = 0x10000000,
+	HOST_REGDMN_MODE_11AXA_HE80 = 0x20000000,
+	HOST_REGDMN_MODE_11AXA_HE160 = 0x40000000,
+	HOST_REGDMN_MODE_11AXA_HE80_80 = 0x80000000,
+	HOST_REGDMN_MODE_ALL = 0xffffffff
+};
+
+#define WIRELESS_11AX_MODES  (HOST_REGDMN_MODE_11AXG_HE20 \
+			      | HOST_REGDMN_MODE_11AXG_HE40PLUS \
+			      | HOST_REGDMN_MODE_11AXG_HE40MINUS \
+			      | HOST_REGDMN_MODE_11AXA_HE20 \
+			      | HOST_REGDMN_MODE_11AXA_HE40PLUS \
+			      | HOST_REGDMN_MODE_11AXA_HE40MINUS \
+			      | HOST_REGDMN_MODE_11AXA_HE80 \
+			      | HOST_REGDMN_MODE_11AXA_HE160 \
+			      | HOST_REGDMN_MODE_11AXA_HE80_80)
+
+#define WIRELESS_11AC_MODES  (HOST_REGDMN_MODE_11AC_VHT20 \
+			      | HOST_REGDMN_MODE_11AC_VHT40PLUS \
+			      | HOST_REGDMN_MODE_11AC_VHT40MINUS \
+			      | HOST_REGDMN_MODE_11AC_VHT80 \
+			      | HOST_REGDMN_MODE_11AC_VHT160 \
+			      | HOST_REGDMN_MODE_11AC_VHT80_80)
+
+#define WIRELESS_11N_MODES   (HOST_REGDMN_MODE_11NG_HT20 \
+			      | HOST_REGDMN_MODE_11NA_HT20 \
+			      | HOST_REGDMN_MODE_11NG_HT40PLUS \
+			      | HOST_REGDMN_MODE_11NG_HT40MINUS \
+			      | HOST_REGDMN_MODE_11NA_HT40PLUS \
+			      | HOST_REGDMN_MODE_11NA_HT40MINUS)
+
+#define WIRELESS_11G_MODES   (HOST_REGDMN_MODE_PUREG \
+			      | HOST_REGDMN_MODE_11G \
+			      | HOST_REGDMN_MODE_108G)
+
+#define WIRELESS_11B_MODES   (HOST_REGDMN_MODE_11B)
+
+#define WIRELESS_11A_MODES   (HOST_REGDMN_MODE_11A \
+			      | HOST_REGDMN_MODE_TURBO \
+			      | HOST_REGDMN_MODE_108A \
+			      | HOST_REGDMN_MODE_11A_HALF_RATE \
+			      | HOST_REGDMN_MODE_11A_QUARTER_RATE)
+
+#define WIRELESS_40_MODES    (HOST_REGDMN_MODE_11NG_HT40PLUS \
+			      | HOST_REGDMN_MODE_11NG_HT40MINUS \
+			      | HOST_REGDMN_MODE_11NA_HT40PLUS \
+			      | HOST_REGDMN_MODE_11NA_HT40MINUS \
+			      | HOST_REGDMN_MODE_11AC_VHT40PLUS \
+			      | HOST_REGDMN_MODE_11AC_VHT40MINUS \
+			      | HOST_REGDMN_MODE_11AXG_HE40PLUS \
+			      | HOST_REGDMN_MODE_11AXG_HE40MINUS \
+			      | HOST_REGDMN_MODE_11AXA_HE40PLUS \
+			      | HOST_REGDMN_MODE_11AXA_HE40MINUS)
+
+#define WIRELESS_80_MODES    (HOST_REGDMN_MODE_11AC_VHT80 \
+			      | HOST_REGDMN_MODE_11AXA_HE80)
+
+#define WIRELESS_160_MODES   (HOST_REGDMN_MODE_11AC_VHT160 \
+			      | HOST_REGDMN_MODE_11AXA_HE160)
+
+/**
+ * reg_is_phymode_chwidth_allowed() - Check if requested phymode is allowed
+ * @pdev_priv_obj: Pointer to regulatory pdev private object.
+ * @phy_in: phymode that the user requested.
+ * @ch_width: Channel width that the user requested.
+ * @primary_freq: Input primary frequency.
+ *
+ * Return: true if phymode is allowed, else false.
+ */
+bool reg_is_phymode_chwidth_allowed(
+		struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
+		enum reg_phymode phy_in,
+		enum phy_ch_width ch_width,
+		qdf_freq_t primary_freq);
+
+#else
+static inline bool reg_is_phymode_chwidth_allowed(
+		struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
+		enum reg_phymode phy_in,
+		enum phy_ch_width ch_width,
+		qdf_freq_t primary_freq);
+{
+	return false;
+}
+
+#endif /* CONFIG_HOST_FIND_CHAN */
+
+#endif /* __REG_CHANNEL_H_ */

+ 124 - 0
umac/regulatory/dispatcher/inc/wlan_reg_channel_api.h

@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_reg_channel_api.h
+ * This file provides prototypes of the routines needed for the
+ * external components to utilize the services provided by the
+ * regulatory component with respect to channel list access.
+ */
+
+#ifndef __WLAN_REG_CHANNEL_API_H
+#define __WLAN_REG_CHANNEL_API_H
+
+#include <reg_services_public_struct.h>
+
+#ifdef CONFIG_HOST_FIND_CHAN
+
+#define WLAN_CHAN_DFS              0x0002  /* DFS set on primary segment */
+#define WLAN_CHAN_DFS_CFREQ2       0x0004  /* DFS set on secondary segment */
+#define WLAN_CHAN_DISALLOW_ADHOC   0x0040  /* ad-hoc is not allowed */
+#define WLAN_CHAN_PSC              0x0400  /* 6GHz PSC frequency */
+
+/**
+ * wlan_reg_is_phymode_chwidth_allowed() - Check if requested phymode is allowed
+ * @pdev: pdev pointer.
+ * @phy_in: phymode that the user requested.
+ * @ch_width: Channel width that the user requested.
+ *
+ * Return: true if phymode is allowed, else false.
+ */
+bool wlan_reg_is_phymode_chwidth_allowed(struct wlan_objmgr_pdev *pdev,
+					 enum reg_phymode phy_in,
+					 enum phy_ch_width ch_width,
+					 qdf_freq_t primary_freq);
+
+/**
+ * wlan_reg_get_max_phymode_and_chwidth() - Find the maximum regmode and
+ * channel width combo supported by the device.
+ * @phy_in: Maximum reg_phymode.
+ * @ch_width: Maximum channel width.
+ * @primary_freq: Input primary frequency.
+ *
+ * Return QDF_STATUS_SUCCESS if a combination is found, else return failure.
+ */
+QDF_STATUS wlan_reg_get_max_phymode_and_chwidth(struct wlan_objmgr_pdev *pdev,
+						enum reg_phymode *phy_in,
+						enum phy_ch_width *ch_width);
+
+/**
+ * wlan_reg_get_txpow_ant_gain() - Find the tx power and antenna gain for
+ * the given frequency.
+ * @pdev: pdev pointer.
+ * @freq: Given frequency.
+ * @txpower: tx power to be filled.
+ * @ant_gain: Antenna gain to be filled.
+ *
+ */
+void wlan_reg_get_txpow_ant_gain(struct wlan_objmgr_pdev *pdev,
+				 qdf_freq_t freq,
+				 uint32_t *txpower,
+				 uint8_t *ant_gain);
+
+/**
+ * wlan_reg_get_chan_flags() - Find the channel flags for freq1 and freq2.
+ * @pdev: pdev pointer.
+ * @freq1: Frequency in primary segment.
+ * @freq2: Frequency in secondary segment.
+ * @flags: Flags to be filled.
+ *
+ */
+void wlan_reg_get_chan_flags(struct wlan_objmgr_pdev *pdev,
+			     qdf_freq_t freq1,
+			     qdf_freq_t freq2,
+			     uint16_t *flags);
+#else
+static inline bool
+wlan_reg_is_phymode_chwidth_allowed(struct wlan_objmgr_pdev *pdev,
+				    enum reg_phymode phy_in,
+				    enum phy_ch_width ch_width,
+				    qdf_freq_t primary_freq)
+{
+	return false;
+}
+
+static inline QDF_STATUS
+wlan_reg_get_max_phymode_and_chwidth(struct wlan_objmgr_pdev *pdev,
+				     enum reg_phymode *phy_in,
+				     enum phy_ch_width *ch_width)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+
+static inline void
+wlan_reg_get_txpow_ant_gain(struct wlan_objmgr_pdev *pdev,
+			    qdf_freq_t freq,
+			    uint32_t *txpower,
+			    uint8_t *ant_gain)
+{
+}
+
+static inline void
+wlan_reg_get_chan_flags(struct wlan_objmgr_pdev *pdev,
+			qdf_freq_t freq1,
+			qdf_freq_t freq2,
+			uint16_t *flags)
+{
+}
+#endif /* CONFIG_HOST_FIND_CHAN */
+
+#endif /* __WLAN_REG_CHANNEL_API_H */

+ 135 - 0
umac/regulatory/dispatcher/src/wlan_reg_channel_api.c

@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * @file wlan_reg_channel_api.c
+ * @brief contains regulatory channel access functions
+ */
+
+#include <qdf_status.h>
+#include <qdf_types.h>
+#include <qdf_module.h>
+#include <wlan_cmn.h>
+#include <wlan_reg_channel_api.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <reg_priv_objs.h>
+#include <reg_services_common.h>
+#include <reg_channel.h>
+#include <wlan_reg_services_api.h>
+
+#ifdef CONFIG_HOST_FIND_CHAN
+bool wlan_reg_is_phymode_chwidth_allowed(struct wlan_objmgr_pdev *pdev,
+					 enum reg_phymode phy_in,
+					 enum phy_ch_width ch_width,
+					 qdf_freq_t primary_freq)
+{
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+
+	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
+		reg_err("reg pdev priv obj is NULL");
+		return false;
+	}
+
+	return reg_is_phymode_chwidth_allowed(pdev_priv_obj, phy_in, ch_width,
+					      primary_freq);
+}
+
+QDF_STATUS wlan_reg_get_max_phymode_and_chwidth(struct wlan_objmgr_pdev *pdev,
+						enum reg_phymode *phy_in,
+						enum phy_ch_width *ch_width)
+{
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+
+	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
+		reg_err("reg pdev priv obj is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	*phy_in = pdev_priv_obj->max_phymode;
+	*ch_width = pdev_priv_obj->max_chwidth;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+void wlan_reg_get_txpow_ant_gain(struct wlan_objmgr_pdev *pdev,
+				 qdf_freq_t freq,
+				 uint32_t *txpower,
+				 uint8_t *ant_gain)
+{
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+	struct regulatory_channel *cur_chan_list;
+	int i;
+
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+
+	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
+		reg_err("reg pdev priv obj is NULL");
+		return;
+	}
+
+	cur_chan_list = pdev_priv_obj->cur_chan_list;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (cur_chan_list[i].center_freq == freq) {
+			*txpower = cur_chan_list[i].tx_power;
+			*ant_gain = cur_chan_list[i].ant_gain;
+		}
+	}
+}
+
+void wlan_reg_get_chan_flags(struct wlan_objmgr_pdev *pdev,
+			     qdf_freq_t freq1,
+			     qdf_freq_t freq2,
+			     uint16_t *flags)
+{
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+	struct regulatory_channel *cur_chan_list;
+	int i;
+
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+
+	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
+		reg_err("reg pdev priv obj is NULL");
+		return;
+	}
+
+	cur_chan_list = pdev_priv_obj->cur_chan_list;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (cur_chan_list[i].center_freq == freq1 &&
+		    cur_chan_list[i].chan_flags & REGULATORY_CHAN_RADAR) {
+			*flags |= WLAN_CHAN_DFS;
+			*flags |= WLAN_CHAN_DISALLOW_ADHOC;
+		}
+
+		if (cur_chan_list[i].center_freq == freq2 &&
+		    cur_chan_list[i].chan_flags & REGULATORY_CHAN_RADAR) {
+			*flags |= WLAN_CHAN_DFS_CFREQ2;
+			*flags |= WLAN_CHAN_DISALLOW_ADHOC;
+		}
+	}
+
+	if (WLAN_REG_IS_6GHZ_PSC_CHAN_FREQ(freq1))
+		*flags |= WLAN_CHAN_PSC;
+}
+
+#endif /* CONFIG_HOST_FIND_CHAN */