qcacmn: Add an API wlan_reg_get_opclass_details

Add an API wlan_reg_get_opclass_details, to get the operating class
table details from the regulatory component. Also, add a new structure
regdmn_ap_cap_opclass_t in the regulatory component, to fill members
of the mapapcap_t structure.

Change-Id: I8b6a3867a766038663c10ce2f01a8b7d310c7375
CRs-Fixed: 2580505
This commit is contained in:
Hariharan Basuthkar 2019-11-19 21:55:50 +05:30 • committed by nshrivas
commit 8e28cdda42
7 changed files with 282 additions and 2 deletions

View file

@ -590,8 +590,8 @@ uint16_t reg_chan_opclass_to_freq(uint8_t chan,
op_class_tbl->channels[i]); i++) {
if (op_class_tbl->channels[i] == chan) {
chan = op_class_tbl->channels[i];
return (op_class_tbl->start_freq +
(chan * FREQ_TO_CHAN_SCALE));
return op_class_tbl->start_freq +
(chan * FREQ_TO_CHAN_SCALE);
}
}
reg_err_rl("Channel not found");
@ -602,4 +602,122 @@ uint16_t reg_chan_opclass_to_freq(uint8_t chan,
reg_err_rl("Invalid opclass given as input");
return 0;
}
static void
reg_get_op_class_tbl_by_chan_map(const struct
reg_dmn_op_class_map_t **op_class_tbl)
{
if (channel_map == channel_map_us)
*op_class_tbl = us_op_class;
else if (channel_map == channel_map_eu)
*op_class_tbl = euro_op_class;
else if (channel_map == channel_map_china)
*op_class_tbl = us_op_class;
else if (channel_map == channel_map_jp)
*op_class_tbl = japan_op_class;
else
*op_class_tbl = global_op_class;
}
/**
* reg_get_channels_from_opclassmap()- Get channels from the opclass map
* @pdev: Pointer to pdev
* @reg_ap_cap: Pointer to reg_ap_cap
* @index: Pointer to index of reg_ap_cap
* @op_class_tbl: Pointer to op_class_tbl
* @is_opclass_operable: Set true if opclass is operable, else set false
*
* Populate channels from opclass map to reg_ap_cap as supported and
* non-supported channels.
*
* Return: void.
*/
static void
reg_get_channels_from_opclassmap(
struct wlan_objmgr_pdev *pdev,
struct regdmn_ap_cap_opclass_t *reg_ap_cap,
uint8_t index,
const struct reg_dmn_op_class_map_t *op_class_tbl,
bool *is_opclass_operable)
{
uint8_t op_cls_chan;
qdf_freq_t search_freq;
bool is_freq_present;
uint8_t chan_idx = 0, n_sup_chans = 0, n_unsup_chans = 0;
while (op_class_tbl->channels[chan_idx]) {
op_cls_chan = op_class_tbl->channels[chan_idx];
search_freq = op_class_tbl->start_freq +
(FREQ_TO_CHAN_SCALE * op_cls_chan);
is_freq_present =
reg_is_freq_present_in_cur_chan_list(pdev, search_freq);
if (!is_freq_present) {
reg_ap_cap[index].
non_sup_chan_list[n_unsup_chans++] =
op_class_tbl->channels[chan_idx];
reg_ap_cap[index].num_non_supported_chan++;
} else {
reg_ap_cap[index].sup_chan_list[n_sup_chans++] =
op_class_tbl->channels[chan_idx];
reg_ap_cap[index].num_supported_chan++;
}
chan_idx++;
}
if (reg_ap_cap[index].num_supported_chan >= 1)
*is_opclass_operable = true;
}
QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
struct regdmn_ap_cap_opclass_t *reg_ap_cap,
uint8_t *n_opclasses,
uint8_t max_supp_op_class,
bool global_tbl_lookup)
{
uint8_t max_reg_power = 0;
const struct reg_dmn_op_class_map_t *op_class_tbl;
uint8_t index = 0;
if (global_tbl_lookup)
op_class_tbl = global_op_class;
else
reg_get_op_class_tbl_by_chan_map(&op_class_tbl);
max_reg_power = reg_get_max_tx_power(pdev);
while (op_class_tbl->op_class && (index < max_supp_op_class)) {
bool is_opclass_operable = false;
qdf_mem_zero(reg_ap_cap[index].sup_chan_list,
REG_MAX_CHANNELS_PER_OPERATING_CLASS);
reg_ap_cap[index].num_supported_chan = 0;
qdf_mem_zero(reg_ap_cap[index].non_sup_chan_list,
REG_MAX_CHANNELS_PER_OPERATING_CLASS);
reg_ap_cap[index].num_non_supported_chan = 0;
reg_get_channels_from_opclassmap(pdev,
reg_ap_cap,
index,
op_class_tbl,
&is_opclass_operable);
if (is_opclass_operable) {
reg_ap_cap[index].op_class = op_class_tbl->op_class;
reg_ap_cap[index].ch_width =
op_class_tbl->chan_spacing;
reg_ap_cap[index].start_freq =
op_class_tbl->start_freq;
reg_ap_cap[index].max_tx_pwr_dbm = max_reg_power;
reg_ap_cap[index].behav_limit =
op_class_tbl->behav_limit;
index++;
}
op_class_tbl++;
}
*n_opclasses = index;
return QDF_STATUS_SUCCESS;
}
#endif

View file

@ -89,6 +89,21 @@ uint16_t reg_dmn_set_curr_opclasses(uint8_t num_classes, uint8_t *class);
*/
uint16_t reg_dmn_get_curr_opclasses(uint8_t *num_classes, uint8_t *class);
/**
* reg_get_opclass_details() - Get details about the current opclass table.
* @pdev: Pointer to pdev.
* @reg_ap_cap: Pointer to reg_ap_cap.
* @n_opclasses: Pointer to number of opclasses.
* @max_supp_op_class: Maximum number of operating classes supported.
* @global_tbl_lookup: Whether to lookup global op class table.
*
* Return: QDF_STATUS_SUCCESS if success, else return QDF_STATUS_FAILURE.
*/
QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
struct regdmn_ap_cap_opclass_t *reg_ap_cap,
uint8_t *n_opclasses,
uint8_t max_supp_op_class,
bool global_tbl_lookup);
#ifdef CONFIG_CHAN_FREQ_API
/**
@ -195,6 +210,16 @@ static inline void reg_dmn_print_channels_in_opclass(uint8_t *country,
{
}
static inline
QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
struct regdmn_ap_cap_opclass_t *reg_ap_cap,
uint8_t *n_opclasses,
uint8_t max_supp_op_class,
bool global_tbl_lookup)
{
return QDF_STATUS_E_FAILURE;
}
#ifdef CONFIG_CHAN_FREQ_API
static inline void

View file

@ -2853,6 +2853,36 @@ enum channel_enum reg_get_chan_enum_for_freq(qdf_freq_t freq)
return INVALID_CHANNEL;
}
bool
reg_is_freq_present_in_cur_chan_list(struct wlan_objmgr_pdev *pdev,
qdf_freq_t freq)
{
enum channel_enum chan_enum;
struct regulatory_channel *cur_chan_list;
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_rl("pdev reg obj is NULL");
return false;
}
cur_chan_list = pdev_priv_obj->cur_chan_list;
for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++)
if (cur_chan_list[chan_enum].center_freq == freq)
if ((cur_chan_list[chan_enum].state !=
CHANNEL_STATE_DISABLE) &&
!(cur_chan_list[chan_enum].chan_flags &
REGULATORY_CHAN_DISABLED))
return true;
reg_debug_rl("Channel center frequency %d not found", freq);
return false;
}
enum channel_state reg_get_channel_state_for_freq(struct wlan_objmgr_pdev *pdev,
qdf_freq_t freq)
{
@ -3474,8 +3504,38 @@ enum reg_wifi_band reg_freq_to_band(qdf_freq_t freq)
return REG_BAND_6G;
return REG_BAND_UNKNOWN;
}
#endif /* CONFIG_CHAN_FREQ_API */
uint8_t reg_get_max_tx_power(struct wlan_objmgr_pdev *pdev)
{
struct regulatory_channel *cur_chan_list;
struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
uint8_t i, max_tx_power = 0;
pdev_priv_obj = reg_get_pdev_obj(pdev);
if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
reg_err("reg pdev private obj is NULL");
return QDF_STATUS_E_FAILURE;
}
cur_chan_list = pdev_priv_obj->cur_chan_list;
for (i = 0; i < NUM_CHANNELS; i++) {
if (cur_chan_list[i].state != CHANNEL_STATE_DISABLE &&
cur_chan_list[i].chan_flags != REGULATORY_CHAN_DISABLED) {
if (cur_chan_list[i].tx_power > max_tx_power)
max_tx_power = cur_chan_list[i].tx_power;
}
}
if (!max_tx_power)
reg_err_rl("max_tx_power is zero");
return max_tx_power;
}
QDF_STATUS reg_set_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc)
{
struct wlan_regulatory_psoc_priv_obj *psoc_reg;

View file

@ -741,6 +741,21 @@ QDF_STATUS reg_disable_chan_coex(struct wlan_objmgr_pdev *pdev,
#endif
#ifdef CONFIG_CHAN_FREQ_API
/**
* reg_is_freq_present_in_cur_chan_list() - Check the input frequency
* @pdev: Pointer to pdev
* @freq: Channel center frequency in MHz
*
* Check if the input channel center frequency is present in the current
* channel list
*
* Return: Return true if channel center frequency is present in the current
* channel list, else return false.
*/
bool
reg_is_freq_present_in_cur_chan_list(struct wlan_objmgr_pdev *pdev,
qdf_freq_t freq);
/**
* reg_get_chan_enum_for_freq() - Get channel enum for given channel frequency
* @freq: Channel Frequency
@ -935,6 +950,15 @@ reg_get_5g_bonded_channel_for_freq(struct wlan_objmgr_pdev *pdev,
**bonded_chan_ptr_ptr);
#endif /* CONFIG_CHAN_FREQ_API */
/**
* reg_get_max_tx_power() - Get maximum tx power from the current channel list
* @pdev: Pointer to pdev
*
* Return: return the value of the maximum tx power in the current channel list
*
*/
uint8_t reg_get_max_tx_power(struct wlan_objmgr_pdev *pdev);
/**
* reg_set_ignore_fw_reg_offload_ind() - Set if regdb offload indication
* needs to be ignored

View file

@ -597,6 +597,30 @@ struct reg_dmn_op_class_map_t {
uint8_t channels[REG_MAX_CHANNELS_PER_OPERATING_CLASS];
};
/**
* struct regdmn_ap_cap_opclass_t: AP Cap operation class table
* @op_class: operating class number
* @ch_width: channel width in MHz
* @start_freq: Starting Frequency in MHz
* @behav_limit: OR of bitmaps of enum behav_limit
* @max_tx_pwr_dbm: Maximum tx power in dbm
* @num_supported_chan: Number of supported channels
* @num_non_supported_chan: Number of non-supported channels
* @sup_chan_list: Array of supported channel numbers
* @non_sup_chan_list: Array of non supported channel numbers
*/
struct regdmn_ap_cap_opclass_t {
uint8_t op_class;
uint8_t ch_width;
qdf_freq_t start_freq;
uint16_t behav_limit;
uint8_t max_tx_pwr_dbm;
uint8_t num_supported_chan;
uint8_t num_non_supported_chan;
uint8_t sup_chan_list[REG_MAX_CHANNELS_PER_OPERATING_CLASS];
uint8_t non_sup_chan_list[REG_MAX_CHANNELS_PER_OPERATING_CLASS];
};
/**
* struct reg_dmn_supp_op_classes: operating classes
* @num_classes: number of classes

View file

@ -605,6 +605,23 @@ uint16_t wlan_reg_dmn_get_curr_opclasses(uint8_t *num_classes,
uint8_t *class);
/**
* wlan_reg_get_opclass_details() - Get details about the current opclass table.
* @pdev: Pointer to pdev.
* @reg_ap_cap: Pointer to reg_ap_cap.
* @n_opclasses: Pointer to number of opclasses.
* @max_supp_op_class: Maximum number of operating classes supported.
* @global_tbl_lookup: Whether to lookup global op class tbl.
*
* Return: QDF_STATUS_SUCCESS if success, else return QDF_STATUS_FAILURE.
*/
QDF_STATUS
wlan_reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
struct regdmn_ap_cap_opclass_t *reg_ap_cap,
uint8_t *n_opclasses,
uint8_t max_supp_op_class,
bool global_tbl_lookup);
/**
* wlan_regulatory_init() - init regulatory component
*

View file

@ -302,6 +302,18 @@ uint16_t wlan_reg_dmn_get_curr_opclasses(uint8_t *num_classes,
return reg_dmn_get_curr_opclasses(num_classes, class);
}
QDF_STATUS
wlan_reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
struct regdmn_ap_cap_opclass_t *reg_ap_cap,
uint8_t *n_opclasses,
uint8_t max_supp_op_class,
bool global_tbl_lookup)
{
return reg_get_opclass_details(pdev, reg_ap_cap, n_opclasses,
max_supp_op_class,
global_tbl_lookup);
}
QDF_STATUS wlan_regulatory_init(void)
{
QDF_STATUS status;