Commit d3c84636 authored by Zong-Zhe Yang's avatar Zong-Zhe Yang Committed by Ping-Ke Shih

wifi: rtw89: regd: extend policy of UNII-4 for IC regulatory

Originally, we have an ACPI function to determine whether to enable UNII-4.
Since IC (Industry Canada) has allowed UNII-4, the ACPI result is extended
to be two bits as below.
  * BIT(0): determine if rtw89_regd::FCC enable UNII-4
  * BIT(1): determine if rtw89_regd::IC enable UNII-4

Besides, to take old platforms into account, we enable UNII-4 on IC if and
only if BIOS configuration enable it.
Signed-off-by: default avatarZong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Link: https://msgid.link/20240412115729.8316-7-pkshih@realtek.com
parent 01e67a62
......@@ -12,7 +12,12 @@ enum rtw89_acpi_dsm_func {
RTW89_ACPI_DSM_FUNC_6G_DIS = 3,
RTW89_ACPI_DSM_FUNC_6G_BP = 4,
RTW89_ACPI_DSM_FUNC_TAS_EN = 5,
RTW89_ACPI_DSM_FUNC_59G_EN = 6,
RTW89_ACPI_DSM_FUNC_UNII4_SUP = 6,
};
enum rtw89_acpi_conf_unii4 {
RTW89_ACPI_CONF_UNII4_FCC = BIT(0),
RTW89_ACPI_CONF_UNII4_IC = BIT(1),
};
enum rtw89_acpi_policy_mode {
......
......@@ -82,6 +82,9 @@ static struct ieee80211_channel rtw89_channels_5ghz[] = {
RTW89_DEF_CHAN_5G(5885, 177),
};
static_assert(RTW89_5GHZ_UNII4_START_INDEX + RTW89_5GHZ_UNII4_CHANNEL_NUM ==
ARRAY_SIZE(rtw89_channels_5ghz));
static struct ieee80211_channel rtw89_channels_6ghz[] = {
RTW89_DEF_CHAN_6G(5955, 1),
RTW89_DEF_CHAN_6G(5975, 5),
......
......@@ -4752,10 +4752,13 @@ struct rtw89_regd {
};
#define RTW89_REGD_MAX_COUNTRY_NUM U8_MAX
#define RTW89_5GHZ_UNII4_CHANNEL_NUM 3
#define RTW89_5GHZ_UNII4_START_INDEX 25
struct rtw89_regulatory_info {
const struct rtw89_regd *regd;
enum rtw89_reg_6ghz_power reg_6ghz_power;
DECLARE_BITMAP(block_unii4, RTW89_REGD_MAX_COUNTRY_NUM);
DECLARE_BITMAP(block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM);
};
......
......@@ -341,51 +341,60 @@ do { \
static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev,
struct wiphy *wiphy)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_chip_info *chip = rtwdev->chip;
bool regd_allow_unii_4 = chip->support_unii4;
struct ieee80211_supported_band *sband;
struct rtw89_acpi_dsm_result res = {};
bool enable_by_fcc;
bool enable_by_ic;
int ret;
u8 val;
int i;
if (!chip->support_unii4)
goto bottom;
sband = wiphy->bands[NL80211_BAND_5GHZ];
if (!sband)
return;
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_59G_EN, &res);
if (!chip->support_unii4) {
sband->n_channels -= RTW89_5GHZ_UNII4_CHANNEL_NUM;
return;
}
bitmap_fill(regulatory->block_unii4, RTW89_REGD_MAX_COUNTRY_NUM);
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_UNII4_SUP, &res);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: cannot eval unii 4: %d\n", ret);
enable_by_fcc = true;
enable_by_ic = false;
goto bottom;
}
val = res.u.value;
enable_by_fcc = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_FCC);
enable_by_ic = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_IC);
rtw89_debug(rtwdev, RTW89_DBG_REGD,
"acpi: eval if allow unii 4: %d\n", val);
switch (val) {
case 0:
regd_allow_unii_4 = false;
break;
case 1:
regd_allow_unii_4 = true;
break;
default:
break;
}
"acpi: eval if allow unii-4: 0x%x\n", val);
bottom:
rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow unii 4: %d\n",
regd_allow_unii_4);
if (regd_allow_unii_4)
return;
sband = wiphy->bands[NL80211_BAND_5GHZ];
if (!sband)
return;
for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) {
const struct rtw89_regd *regd = &rtw89_regd_map[i];
sband->n_channels -= 3;
switch (regd->txpwr_regd[RTW89_BAND_5G]) {
case RTW89_FCC:
if (enable_by_fcc)
clear_bit(i, regulatory->block_unii4);
break;
case RTW89_IC:
if (enable_by_ic)
clear_bit(i, regulatory->block_unii4);
break;
default:
break;
}
}
}
static void __rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev, bool block,
......@@ -562,6 +571,35 @@ int rtw89_regd_init(struct rtw89_dev *rtwdev,
return 0;
}
static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev,
struct wiphy *wiphy)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_regd *regd = regulatory->regd;
struct ieee80211_supported_band *sband;
u8 index;
int i;
sband = wiphy->bands[NL80211_BAND_5GHZ];
if (!sband)
return;
if (!chip->support_unii4)
return;
index = rtw89_regd_get_index(regd);
if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
!test_bit(index, regulatory->block_unii4))
return;
rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c unii-4 is blocked by policy\n",
regd->alpha2[0], regd->alpha2[1]);
for (i = RTW89_5GHZ_UNII4_START_INDEX; i < sband->n_channels; i++)
sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
}
static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
struct wiphy *wiphy)
{
......@@ -602,6 +640,7 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
else
wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
rtw89_regd_apply_policy_unii4(rtwdev, wiphy);
rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment