qcacmn: Add regulatory API for phymode change

Add new enum in regulatory to hold all current phymodes.
Add a new API to get max allowed phymode which is not more than the
user provided phymode.

This change simplifies the phymode selection process when starting
or updating the parameters of a vdev.

Change-Id: I12c15e357b80faf2f5272800e55179f02755a263
CRs-fixed: 2658290
This commit is contained in:
Lincoln Tran 2020-03-18 15:13:39 -07:00 • committed by nshrivas
commit 0779b77211
5 changed files with 149 additions and 0 deletions

View file

@ -3795,3 +3795,74 @@ reg_get_unii_5g_bitmap(struct wlan_objmgr_pdev *pdev, uint8_t *bitmap)
return QDF_STATUS_SUCCESS;
}
#endif
#ifdef CHECK_REG_PHYMODE
/**
* reg_is_phymode_allowed() - Check if requested phymode is unallowed
* @phy_in: phymode that the user requested
* @phymode_bitmap: bitmap of unallowed phymodes for specific country
*
* Return: true if phymode is not allowed, else false
*/
static bool reg_is_phymode_unallowed(enum reg_phymode phy_in,
uint32_t phymode_bitmap)
{
if (!phymode_bitmap)
return false;
if (phy_in == REG_PHYMODE_11AX)
return phymode_bitmap & REGULATORY_PHYMODE_NO11AX;
else if (phy_in == REG_PHYMODE_11AC)
return phymode_bitmap & REGULATORY_PHYMODE_NO11AC;
else if (phy_in == REG_PHYMODE_11N)
return phymode_bitmap & REGULATORY_CHAN_NO11N;
else if (phy_in == REG_PHYMODE_11G)
return phymode_bitmap & REGULATORY_PHYMODE_NO11G;
else if (phy_in == REG_PHYMODE_11A)
return phymode_bitmap & REGULATORY_PHYMODE_NO11A;
else if (phy_in == REG_PHYMODE_11B)
return phymode_bitmap & REGULATORY_PHYMODE_NO11B;
else
return true;
}
enum reg_phymode reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
enum reg_phymode phy_in,
qdf_freq_t freq)
{
struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
uint32_t phymode_bitmap;
enum reg_phymode current_phymode = phy_in;
pdev_priv_obj = reg_get_pdev_obj(pdev);
if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
reg_err("pdev reg component is NULL");
return REG_PHYMODE_INVALID;
}
phymode_bitmap = pdev_priv_obj->phybitmap;
while (1) {
if (reg_is_phymode_unallowed(current_phymode, phymode_bitmap)) {
if (current_phymode == REG_PHYMODE_11N) {
if (REG_IS_24GHZ_CH_FREQ(freq))
current_phymode = REG_PHYMODE_11G;
else
current_phymode = REG_PHYMODE_11A;
} else if (current_phymode == REG_PHYMODE_11A ||
current_phymode == REG_PHYMODE_11B) {
reg_err("Couldn't find a suitable phymode");
return REG_PHYMODE_INVALID;
} else if (current_phymode > REG_PHYMODE_MAX) {
reg_err("Unknown phymode");
return REG_PHYMODE_INVALID;
} else {
current_phymode--;
}
} else {
return current_phymode;
}
}
}
#endif /* CHECK_REG_PHYMODE */

View file

@ -1098,4 +1098,27 @@ QDF_STATUS
reg_get_unii_5g_bitmap(struct wlan_objmgr_pdev *pdev, uint8_t *bitmap);
#endif
#ifdef CHECK_REG_PHYMODE
/**
* reg_get_max_phymode() - Recursively find the best possible phymode given a
* phymode, a frequency, and per-country regulations
* @pdev: pdev pointer
* @phy_in: phymode that the user requested
* @freq: current operating center frequency
*
* Return: maximum phymode allowed in current country that is <= phy_in
*/
enum reg_phymode reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
enum reg_phymode phy_in,
qdf_freq_t freq);
#else
static inline enum reg_phymode
reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
enum reg_phymode phy_in,
qdf_freq_t freq)
{
return REG_PHYMODE_INVALID;
}
#endif /* CHECK_REG_PHYMODE */
#endif

View file

@ -1137,4 +1137,26 @@ struct reg_ctl_params {
uint8_t ctl_5g;
};
/**
* enum reg_phymode - Regulatory phymode
* @REG_PHYMODE_INVALID: Invalid phymode
* @REG_PHYMODE_11B: 802.11b phymode
* @REG_PHYMODE_11G: 802.11g phymode
* @REG_PHYMODE_11A: 802.11a phymode
* @REG_PHYMODE_11N: 802.11n phymode
* @REG_PHYMODE_11AC: 802.11ac phymode
* @REG_PHYMODE_11AX: 802.11ax phymode
* @REG_PHYMODE_MAX: placeholder for future phymodes
*/
enum reg_phymode {
REG_PHYMODE_INVALID,
REG_PHYMODE_11B,
REG_PHYMODE_11G,
REG_PHYMODE_11A,
REG_PHYMODE_11N,
REG_PHYMODE_11AC,
REG_PHYMODE_11AX,
REG_PHYMODE_MAX,
};
#endif

View file

@ -1402,4 +1402,28 @@ uint16_t wlan_reg_chan_opclass_to_freq(uint8_t chan,
qdf_freq_t wlan_reg_chan_opclass_to_freq_auto(uint8_t chan, uint8_t op_class,
bool global_tbl_lookup);
#ifdef CHECK_REG_PHYMODE
/**
* wlan_reg_get_max_phymode() - Find the best possible phymode given a
* phymode, a frequency, and per-country regulations
* @pdev: pdev pointer
* @phy_in: phymode that the user requested
* @freq: current operating center frequency
*
* Return: maximum phymode allowed in current country that is <= phy_in
*/
enum reg_phymode wlan_reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
enum reg_phymode phy_in,
qdf_freq_t freq);
#else
static inline enum reg_phymode
wlan_reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
enum reg_phymode phy_in,
qdf_freq_t freq)
{
return REG_PHYMODE_INVALID;
}
#endif /* CHECK_REG_PHYMODE */
#endif

View file

@ -1155,3 +1155,12 @@ qdf_freq_t wlan_reg_chan_opclass_to_freq_auto(uint8_t chan, uint8_t op_class,
return reg_chan_opclass_to_freq_auto(chan, op_class, global_tbl_lookup);
}
#ifdef CHECK_REG_PHYMODE
enum reg_phymode wlan_reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
enum reg_phymode phy_in,
qdf_freq_t freq)
{
return reg_get_max_phymode(pdev, phy_in, freq);
}
#endif /* CHECK_REG_PHYMODE */