regd = rcu_dereference_rtnl(hw->wiphy->regd); /* This can happen during wiphy registration where the previous *userrequestisreceivedbeforeweupdatetheregdreceived *fromfirmware.
*/ if (!regd) returntrue;
ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Regulatory Notification received for %s\n", wiphy_name(wiphy));
if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
ath12k_dbg(ar->ab, ATH12K_DBG_REG, "driver initiated regd update\n"); if (ah->state != ATH12K_HW_STATE_ON) return;
for_each_ar(ah, ar, i) {
ret = ath12k_reg_update_chan_list(ar, true); if (ret && ret != -EINVAL) {
ath12k_warn(ar->ab, "failed to update chan list for pdev %u, ret %d\n",
i, ret); break;
}
} return;
}
/* Currently supporting only General User Hints. Cell base user *hintstobehandledlater. *HintsfromothersourceslikeCore,Beaconsarenotexpectedfor *selfmanagedwiphy's
*/ if (!(request->initiator == NL80211_REGDOM_SET_BY_USER &&
request->user_reg_hint_type == NL80211_USER_REG_HINT_USER)) {
ath12k_warn(ar->ab, "Unexpected Regulatory event for this wiphy\n"); return;
}
if (!IS_ENABLED(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) {
ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Country Setting is not allowed\n"); return;
}
if (!ath12k_regdom_changes(hw, request->alpha2)) {
ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Country is already set\n"); return;
}
int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
{ struct ieee80211_supported_band **bands; struct ath12k_wmi_scan_chan_list_arg *arg; struct ieee80211_channel *channel; struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); struct ath12k_wmi_channel_arg *ch; enum nl80211_band band; int num_channels = 0; int i, ret = 0;
if (ar->ah->state == ATH12K_HW_STATE_RESTARTING) return0;
bands = hw->wiphy->bands; for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!(ar->mac.sbands[band].channels && bands[band])) continue;
for (i = 0; i < bands[band]->n_channels; i++) { if (bands[band]->channels[i].flags &
IEEE80211_CHAN_DISABLED) continue; /* Skip Channels that are not in current radio's range */ if (bands[band]->channels[i].center_freq <
KHZ_TO_MHZ(ar->freq_range.start_freq) ||
bands[band]->channels[i].center_freq >
KHZ_TO_MHZ(ar->freq_range.end_freq)) continue;
num_channels++;
}
}
if (!num_channels) {
ath12k_dbg(ar->ab, ATH12K_DBG_REG, "pdev is not supported for this country\n"); return -EINVAL;
}
for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!(ar->mac.sbands[band].channels && bands[band])) continue;
for (i = 0; i < bands[band]->n_channels; i++) {
channel = &bands[band]->channels[i];
if (channel->flags & IEEE80211_CHAN_DISABLED) continue;
/* Skip Channels that are not in current radio's range */ if (bands[band]->channels[i].center_freq <
KHZ_TO_MHZ(ar->freq_range.start_freq) ||
bands[band]->channels[i].center_freq >
KHZ_TO_MHZ(ar->freq_range.end_freq)) continue;
/* TODO: Set to true/false based on some condition? */
ch->allow_ht = true;
ch->allow_vht = true;
ch->allow_he = true;
time_left = wait_for_completion_timeout(&ar->regd_update_completed,
ATH12K_REG_UPDATE_TIMEOUT_HZ); if (time_left == 0) {
ath12k_warn(ab, "Timeout while waiting for regulatory update"); /* Even though timeout has occurred, still continue since at least boot *timedatawouldbetheretoprocess
*/
}
/* Possible that due to reg change, current limits for supported *frequencychanged.Updateit.Asafirststep,resetthe *previousvaluesandthencomputeandsetthenewvalues.
*/
ar->freq_range.start_freq = 0;
ar->freq_range.end_freq = 0;
if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) { if (ab->hw_params->single_pdev_only) {
phy_id = ar->pdev->cap.band[WMI_HOST_WLAN_2GHZ_CAP].phy_id;
reg_cap = &ab->hal_reg_cap[phy_id];
}
/* If one of the radios within ah has already updated the regd for *thewiphy,thenavoidsettingregdagain
*/ if (ah->regd_updated) return0;
/* firmware provides reg rules which are similar for 2 GHz and 5 GHz *pdevbut6GHzpdevhassupersetofallrulesincludingrulesfor *allbands,weprefer6GHzpdev'srulestobeusedforsetupof *thewiphyregd. *If6GHzpdevwaspartoftheath12k_hw,waitforthe6GHzpdev, *elsepickthefirstpdevwhichcallsthisfunctionanduseits *regdtoupdateglobalhwregd. *Theregd_updatedflagsetattheendwillnotallowanyfurther *updates.
*/ if (ah->use_6ghz_regd && !ar->supports_6ghz) return0;
pdev_id = ar->pdev_idx;
spin_lock_bh(&ab->base_lock);
if (init) { /* Apply the regd received during init through *WMI_REG_CHAN_LIST_CCevent.Incaseoffailureto *receivetheregd,initializewithadefaultworld *regulatory.
*/ if (ab->default_regd[pdev_id]) {
regd = ab->default_regd[pdev_id];
} else {
ath12k_warn(ab, "failed to receive default regd during init\n");
regd = (struct ieee80211_regdomain *)&ath12k_world_regd;
}
} else {
regd = ab->new_regd[pdev_id];
}
if (!regd) {
ret = -EINVAL;
spin_unlock_bh(&ab->base_lock); goto err;
}
/* Reset start and end frequency for each band
*/
ab->reg_freq_5ghz.start_freq = INT_MAX;
ab->reg_freq_5ghz.end_freq = 0;
ab->reg_freq_2ghz.start_freq = INT_MAX;
ab->reg_freq_2ghz.end_freq = 0;
ab->reg_freq_6ghz.start_freq = INT_MAX;
ab->reg_freq_6ghz.end_freq = 0;
/* Update reg_rules[] below. Firmware is expected to *sendtheserulesinorder(2Grulesfirstandthen5G)
*/ for (; i < num_rules; i++) { if (reg_info->num_2g_reg_rules &&
(i < reg_info->num_2g_reg_rules)) {
reg_rule = reg_info->reg_rules_2g_ptr + i;
max_bw = min_t(u16, reg_rule->max_bw,
reg_info->max_bw_2g);
flags = ath12k_get_bw_reg_flags(reg_info->max_bw_2g);
ath12k_reg_update_freq_range(&ab->reg_freq_2ghz, reg_rule);
} elseif (reg_info->num_5g_reg_rules &&
(j < reg_info->num_5g_reg_rules)) {
reg_rule = reg_info->reg_rules_5g_ptr + j++;
max_bw = min_t(u16, reg_rule->max_bw,
reg_info->max_bw_5g);
ret = ath12k_regd_update(ar, false); if (ret) { /* Firmware has already moved to the new regd. We need *tomaintainchannelconsistencyacrossFW,Hostdriver *anduserspace.Henceasafallbackmechanismwecanset *theprevordefaultcountrycodetothefirmware.
*/ /* TODO: Implement Fallback Mechanism */
}
}
void ath12k_reg_reset_reg_info(struct ath12k_reg_info *reg_info)
{
u8 i, j;
if (reg_info->status_code != REG_SET_CC_STATUS_PASS) { /* In case of failure to set the requested country, *firmwareretainsthecurrentregd.Weprintafailureinfo *andreturnfromhere.
*/
ath12k_warn(ab, "Failed to set the requested Country regulatory setting\n"); return ATH12K_REG_STATUS_DROP;
}
if (pdev_idx >= ab->num_radios) { /* Process the event for phy0 only if single_pdev_only *istrue.Ifpdev_idxisvalidbutnot0,discardthe *event.Otherwise,itgoestofallback.
*/ if (ab->hw_params->single_pdev_only &&
pdev_idx < ab->hw_params->num_rxdma_per_pdev) return ATH12K_REG_STATUS_DROP; else return ATH12K_REG_STATUS_FALLBACK;
}
/* Avoid multiple overwrites to default regd, during core *stop-startaftermacregistration.
*/ if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
!memcmp(ab->default_regd[pdev_idx]->alpha2,
reg_info->alpha2, 2)) return ATH12K_REG_STATUS_DROP;
regd = ath12k_reg_build_regd(ab, reg_info, vdev_type, power_type); if (!regd) return -EINVAL;
spin_lock_bh(&ab->base_lock); if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) { /* Once mac is registered, ar is valid and all CC events from *firmwareisconsideredtobereceivedduetouserrequests *currently. *Freepreviouslybuiltregdbeforeassigningthenewly *generatedregdtoar.NULLpointerhandlingwillbe *takencarebykfreeitself.
*/
ar = ab->pdevs[pdev_idx].ar;
kfree(ab->new_regd[pdev_idx]);
ab->new_regd[pdev_idx] = regd;
queue_work(ab->workqueue, &ar->regd_update_work);
} else { /* Multiple events for the same *ar is not expected. But we *canstillclearanypreviouslystoreddefault_regdifwe *arereceivingthiseventforthesameradiobymistake. *NULLpointerhandlingwillbetakencarebykfreeitself.
*/
kfree(ab->default_regd[pdev_idx]); /* This regd would be applied during mac registration */
ab->default_regd[pdev_idx] = regd;
}
ab->dfs_region = reg_info->dfs_region;
spin_unlock_bh(&ab->base_lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.