From 0779b77211d119eede30b1e295aa31d56b6c110d Mon Sep 17 00:00:00 2001 From: Lincoln Tran Date: Wed, 18 Mar 2020 15:13:39 -0700 Subject: [PATCH] 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 --- .../regulatory/core/src/reg_services_common.c | 71 +++++++++++++++++++ .../regulatory/core/src/reg_services_common.h | 23 ++++++ .../inc/reg_services_public_struct.h | 22 ++++++ .../dispatcher/inc/wlan_reg_services_api.h | 24 +++++++ .../dispatcher/src/wlan_reg_services_api.c | 9 +++ 5 files changed, 149 insertions(+) diff --git a/umac/regulatory/core/src/reg_services_common.c b/umac/regulatory/core/src/reg_services_common.c index 159f9e6f4e69..3080989df77f 100644 --- a/umac/regulatory/core/src/reg_services_common.c +++ b/umac/regulatory/core/src/reg_services_common.c @@ -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 */ diff --git a/umac/regulatory/core/src/reg_services_common.h b/umac/regulatory/core/src/reg_services_common.h index 7741c3050c78..5e8f8473211e 100644 --- a/umac/regulatory/core/src/reg_services_common.h +++ b/umac/regulatory/core/src/reg_services_common.h @@ -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 diff --git a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h index c90692e9ea29..c698e7926c47 100644 --- a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h +++ b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h @@ -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 diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index f6e7824ba65a..1d81e43b4075 100644 --- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -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 diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index f12d52ef01d5..e37a13291212 100644 --- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -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 */