mirror of
https://github.com/openwrt/openwrt.git
synced 2025-04-07 11:27:09 +00:00
mac80211: update to linux 6.1-rc8
This should help stay in sync with upstream development Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
b1b29ba987
commit
8d90b9fef1
618
package/kernel/ath10k-ct/patches/100-api_update.patch
Normal file
618
package/kernel/ath10k-ct/patches/100-api_update.patch
Normal file
@ -0,0 +1,618 @@
|
||||
--- a/ath10k-5.15/mac.c
|
||||
+++ b/ath10k-5.15/mac.c
|
||||
@@ -788,7 +788,7 @@ int ath10k_mac_vif_chan(struct ieee80211
|
||||
struct ieee80211_chanctx_conf *conf;
|
||||
|
||||
rcu_read_lock();
|
||||
- conf = rcu_dereference(vif->chanctx_conf);
|
||||
+ conf = rcu_dereference(vif->bss_conf.chanctx_conf);
|
||||
if (!conf) {
|
||||
rcu_read_unlock();
|
||||
return -ENOENT;
|
||||
@@ -1764,8 +1764,8 @@ static int ath10k_vdev_start_restart(str
|
||||
arg.channel.chan_radar =
|
||||
!!(chandef->chan->flags & IEEE80211_CHAN_RADAR);
|
||||
} else if (arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
|
||||
- arg.ssid = arvif->vif->bss_conf.ssid;
|
||||
- arg.ssid_len = arvif->vif->bss_conf.ssid_len;
|
||||
+ arg.ssid = arvif->vif->cfg.ssid;
|
||||
+ arg.ssid_len = arvif->vif->cfg.ssid_len;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
@@ -1890,7 +1890,7 @@ static int ath10k_mac_setup_bcn_tmpl(str
|
||||
arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
|
||||
return 0;
|
||||
|
||||
- bcn = ieee80211_beacon_get_template(hw, vif, &offs);
|
||||
+ bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
|
||||
if (!bcn) {
|
||||
ath10k_warn(ar, "failed to get beacon template from mac80211\n");
|
||||
return -EPERM;
|
||||
@@ -2083,8 +2083,7 @@ static void ath10k_control_beaconing(str
|
||||
}
|
||||
|
||||
static void ath10k_control_ibss(struct ath10k_vif *arvif,
|
||||
- struct ieee80211_bss_conf *info,
|
||||
- const u8 self_peer[ETH_ALEN])
|
||||
+ struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath10k *ar = arvif->ar;
|
||||
u32 vdev_param;
|
||||
@@ -2092,7 +2091,7 @@ static void ath10k_control_ibss(struct a
|
||||
|
||||
lockdep_assert_held(&arvif->ar->conf_mutex);
|
||||
|
||||
- if (!info->ibss_joined) {
|
||||
+ if (!vif->cfg.ibss_joined) {
|
||||
if (is_zero_ether_addr(arvif->bssid))
|
||||
return;
|
||||
|
||||
@@ -2298,7 +2297,7 @@ static void ath10k_mac_vif_ap_csa_count_
|
||||
if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
|
||||
return;
|
||||
|
||||
- if (!vif->csa_active)
|
||||
+ if (!vif->bss_conf.csa_active)
|
||||
return;
|
||||
|
||||
if (!arvif->is_up)
|
||||
@@ -2433,7 +2432,7 @@ static void ath10k_peer_assoc_h_basic(st
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
- aid = vif->bss_conf.aid;
|
||||
+ aid = vif->cfg.aid;
|
||||
else
|
||||
aid = sta->aid;
|
||||
|
||||
@@ -2463,7 +2462,8 @@ static void ath10k_peer_assoc_h_crypto(s
|
||||
return;
|
||||
|
||||
bss = cfg80211_get_bss(ar->hw->wiphy, def.chan, info->bssid,
|
||||
- info->ssid_len ? info->ssid : NULL, info->ssid_len,
|
||||
+ vif->cfg.ssid_len ? vif->cfg.ssid : NULL,
|
||||
+ vif->cfg.ssid_len,
|
||||
IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
|
||||
if (bss) {
|
||||
const struct cfg80211_bss_ies *ies;
|
||||
@@ -2521,7 +2521,7 @@ static void ath10k_peer_assoc_h_rates(st
|
||||
|
||||
band = def.chan->band;
|
||||
sband = ar->hw->wiphy->bands[band];
|
||||
- ratemask = sta->supp_rates[band];
|
||||
+ ratemask = sta->deflink.supp_rates[band];
|
||||
ratemask &= arvif->bitrate_mask.control[band].legacy;
|
||||
rates = sband->bitrates;
|
||||
|
||||
@@ -2770,7 +2770,7 @@ static void ath10k_peer_assoc_h_ht(struc
|
||||
struct ieee80211_sta *sta,
|
||||
struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
- const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
+ const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct cfg80211_chan_def def;
|
||||
enum nl80211_band band;
|
||||
@@ -2814,7 +2814,7 @@ static void ath10k_peer_assoc_h_ht(struc
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
|
||||
arg->peer_flags |= ar->wmi.peer_flags->ldbc;
|
||||
|
||||
- if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
|
||||
+ if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) {
|
||||
arg->peer_flags |= ar->wmi.peer_flags->bw40;
|
||||
arg->peer_rate_caps |= WMI_RC_CW40_FLAG;
|
||||
}
|
||||
@@ -2883,7 +2883,7 @@ static void ath10k_peer_assoc_h_ht(struc
|
||||
arg->peer_ht_rates.rates[i] = i;
|
||||
} else {
|
||||
arg->peer_ht_rates.num_rates = n;
|
||||
- arg->peer_num_spatial_streams = min(sta->rx_nss, max_nss);
|
||||
+ arg->peer_num_spatial_streams = min(sta->deflink.rx_nss, max_nss);
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
|
||||
@@ -3045,7 +3045,7 @@ static void ath10k_peer_assoc_h_vht(stru
|
||||
struct ieee80211_sta *sta,
|
||||
struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
- const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
|
||||
+ const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct cfg80211_chan_def def;
|
||||
@@ -3087,10 +3087,10 @@ static void ath10k_peer_assoc_h_vht(stru
|
||||
(1U << (IEEE80211_HT_MAX_AMPDU_FACTOR +
|
||||
ampdu_factor)) - 1);
|
||||
|
||||
- if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
|
||||
+ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
|
||||
arg->peer_flags |= ar->wmi.peer_flags->bw80;
|
||||
|
||||
- if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
|
||||
+ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
|
||||
arg->peer_flags |= ar->wmi.peer_flags->bw160;
|
||||
|
||||
/* Calculate peer NSS capability from VHT capabilities if STA
|
||||
@@ -3104,7 +3104,7 @@ static void ath10k_peer_assoc_h_vht(stru
|
||||
vht_mcs_mask[i])
|
||||
max_nss = i + 1;
|
||||
}
|
||||
- arg->peer_num_spatial_streams = min(sta->rx_nss, max_nss);
|
||||
+ arg->peer_num_spatial_streams = min(sta->deflink.rx_nss, max_nss);
|
||||
arg->peer_vht_rates.rx_max_rate =
|
||||
__le16_to_cpu(vht_cap->vht_mcs.rx_highest);
|
||||
arg->peer_vht_rates.rx_mcs_set =
|
||||
@@ -3266,7 +3266,7 @@ static bool ath10k_mac_sta_has_ofdm_only
|
||||
{
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
u32 msk = arvif->bitrate_mask.control[NL80211_BAND_2GHZ].legacy &
|
||||
- sta->supp_rates[NL80211_BAND_2GHZ];
|
||||
+ sta->deflink.supp_rates[NL80211_BAND_2GHZ];
|
||||
/* We have 12 bits of legacy rates, first 4 are /b (CCK) rates. */
|
||||
return (msk & 0xff0) && !(msk & 0xf);
|
||||
}
|
||||
@@ -3276,7 +3276,7 @@ static bool ath10k_mac_sta_has_ofdm_and_
|
||||
{
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
u32 msk = arvif->bitrate_mask.control[NL80211_BAND_2GHZ].legacy &
|
||||
- sta->supp_rates[NL80211_BAND_2GHZ];
|
||||
+ sta->deflink.supp_rates[NL80211_BAND_2GHZ];
|
||||
/* We have 12 bits of legacy rates, first 4 are /b (CCK) rates. */
|
||||
return ((msk & 0xf) && (msk & 0xff0));
|
||||
}
|
||||
@@ -3284,8 +3284,10 @@ static bool ath10k_mac_sta_has_ofdm_and_
|
||||
static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
- if (sta->bandwidth == IEEE80211_STA_RX_BW_160) {
|
||||
- switch (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
|
||||
+ struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
+
|
||||
+ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
|
||||
+ switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
|
||||
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
|
||||
return MODE_11AC_VHT160;
|
||||
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
|
||||
@@ -3296,13 +3298,13 @@ static enum wmi_phy_mode ath10k_mac_get_
|
||||
}
|
||||
}
|
||||
|
||||
- if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
|
||||
+ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
|
||||
return MODE_11AC_VHT80;
|
||||
|
||||
- if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
|
||||
+ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
|
||||
return MODE_11AC_VHT40;
|
||||
|
||||
- if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
|
||||
+ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
|
||||
return MODE_11AC_VHT20;
|
||||
|
||||
return MODE_UNKNOWN;
|
||||
@@ -3329,15 +3331,15 @@ static void ath10k_peer_assoc_h_phymode(
|
||||
|
||||
switch (band) {
|
||||
case NL80211_BAND_2GHZ:
|
||||
- if (sta->vht_cap.vht_supported &&
|
||||
+ if (sta->deflink.vht_cap.vht_supported &&
|
||||
!ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
|
||||
- if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
|
||||
+ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
|
||||
phymode = MODE_11AC_VHT40;
|
||||
else
|
||||
phymode = MODE_11AC_VHT20;
|
||||
- } else if (sta->ht_cap.ht_supported &&
|
||||
+ } else if (sta->deflink.ht_cap.ht_supported &&
|
||||
!ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
|
||||
- if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
|
||||
+ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
|
||||
phymode = MODE_11NG_HT40;
|
||||
else
|
||||
phymode = MODE_11NG_HT20;
|
||||
@@ -3354,12 +3356,12 @@ static void ath10k_peer_assoc_h_phymode(
|
||||
/*
|
||||
* Check VHT first.
|
||||
*/
|
||||
- if (sta->vht_cap.vht_supported &&
|
||||
+ if (sta->deflink.vht_cap.vht_supported &&
|
||||
!ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
|
||||
phymode = ath10k_mac_get_phymode_vht(ar, sta);
|
||||
- } else if (sta->ht_cap.ht_supported &&
|
||||
+ } else if (sta->deflink.ht_cap.ht_supported &&
|
||||
!ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
|
||||
- if (sta->bandwidth >= IEEE80211_STA_RX_BW_40)
|
||||
+ if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40)
|
||||
phymode = MODE_11NA_HT40;
|
||||
else
|
||||
phymode = MODE_11NA_HT20;
|
||||
@@ -3373,8 +3375,8 @@ static void ath10k_peer_assoc_h_phymode(
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM phymode %s legacy-supp-rates: 0x%x arvif-legacy-rates: 0x%x vht-supp: %d\n",
|
||||
- sta->addr, ath10k_wmi_phymode_str(phymode), sta->supp_rates[band],
|
||||
- arvif->bitrate_mask.control[band].legacy, sta->vht_cap.vht_supported);
|
||||
+ sta->addr, ath10k_wmi_phymode_str(phymode), sta->deflink.supp_rates[band],
|
||||
+ arvif->bitrate_mask.control[band].legacy, sta->deflink.vht_cap.vht_supported);
|
||||
|
||||
arg->peer_phymode = phymode;
|
||||
WARN_ON(phymode == MODE_UNKNOWN);
|
||||
@@ -3677,8 +3679,8 @@ static void ath10k_bss_assoc(struct ieee
|
||||
/* ap_sta must be accessed only within rcu section which must be left
|
||||
* before calling ath10k_setup_peer_smps() which might sleep.
|
||||
*/
|
||||
- ht_cap = ap_sta->ht_cap;
|
||||
- vht_cap = ap_sta->vht_cap;
|
||||
+ ht_cap = ap_sta->deflink.ht_cap;
|
||||
+ vht_cap = ap_sta->deflink.vht_cap;
|
||||
|
||||
ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg);
|
||||
if (ret) {
|
||||
@@ -3713,11 +3715,11 @@ static void ath10k_bss_assoc(struct ieee
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac vdev %d up (associated) bssid %pM aid %d bandwidth %d\n",
|
||||
- arvif->vdev_id, bss_conf->bssid, bss_conf->aid, ap_sta->bandwidth);
|
||||
+ arvif->vdev_id, bss_conf->bssid, vif->cfg.aid, ap_sta->deflink.bandwidth);
|
||||
|
||||
WARN_ON(arvif->is_up);
|
||||
|
||||
- arvif->aid = bss_conf->aid;
|
||||
+ arvif->aid = vif->cfg.aid;
|
||||
ether_addr_copy(arvif->bssid, bss_conf->bssid);
|
||||
|
||||
ret = ath10k_wmi_pdev_set_param(ar,
|
||||
@@ -4022,7 +4024,7 @@ static int ath10k_station_assoc(struct a
|
||||
*/
|
||||
if (!reassoc) {
|
||||
ret = ath10k_setup_peer_smps(ar, arvif, sta->addr,
|
||||
- &sta->ht_cap);
|
||||
+ &sta->deflink.ht_cap);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
@@ -6916,7 +6918,7 @@ static void ath10k_recalculate_mgmt_rate
|
||||
static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info,
|
||||
- u32 changed)
|
||||
+ u64 changed)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
@@ -6930,7 +6932,7 @@ static void ath10k_bss_info_changed(stru
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (changed & BSS_CHANGED_IBSS)
|
||||
- ath10k_control_ibss(arvif, info, vif->addr);
|
||||
+ ath10k_control_ibss(arvif, vif);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_INT) {
|
||||
arvif->beacon_interval = info->beacon_int;
|
||||
@@ -6995,9 +6997,9 @@ static void ath10k_bss_info_changed(stru
|
||||
|
||||
if (changed & BSS_CHANGED_SSID &&
|
||||
vif->type == NL80211_IFTYPE_AP) {
|
||||
- arvif->u.ap.ssid_len = info->ssid_len;
|
||||
- if (info->ssid_len)
|
||||
- memcpy(arvif->u.ap.ssid, info->ssid, info->ssid_len);
|
||||
+ arvif->u.ap.ssid_len = vif->cfg.ssid_len;
|
||||
+ if (vif->cfg.ssid_len)
|
||||
+ memcpy(arvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);
|
||||
arvif->u.ap.hidden_ssid = info->hidden_ssid;
|
||||
}
|
||||
|
||||
@@ -7074,7 +7076,7 @@ static void ath10k_bss_info_changed(stru
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
- if (info->assoc) {
|
||||
+ if (vif->cfg.assoc) {
|
||||
/* Workaround: Make sure monitor vdev is not running
|
||||
* when associating to prevent some firmware revisions
|
||||
* (e.g. 10.1 and 10.2) from crashing.
|
||||
@@ -7099,7 +7101,7 @@ static void ath10k_bss_info_changed(stru
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_PS) {
|
||||
- arvif->ps = vif->bss_conf.ps;
|
||||
+ arvif->ps = vif->cfg.ps;
|
||||
|
||||
ret = ath10k_config_ps(ar);
|
||||
if (ret)
|
||||
@@ -7699,7 +7701,7 @@ static void ath10k_sta_rc_update_wk(stru
|
||||
|
||||
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_STA, "mac update sta %pM supp rates, bandwidth: %d\n",
|
||||
- sta->addr, sta->bandwidth);
|
||||
+ sta->addr, sta->deflink.bandwidth);
|
||||
|
||||
err = ath10k_station_assoc(ar, arvif->vif, sta, true);
|
||||
if (err)
|
||||
@@ -7751,10 +7753,10 @@ static int ath10k_sta_set_txpwr(struct i
|
||||
int ret = 0;
|
||||
s16 txpwr;
|
||||
|
||||
- if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
|
||||
+ if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
|
||||
txpwr = 0;
|
||||
} else {
|
||||
- txpwr = sta->txpwr.power;
|
||||
+ txpwr = sta->deflink.txpwr.power;
|
||||
if (!txpwr)
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -7874,26 +7876,29 @@ static int ath10k_mac_validate_rate_mask
|
||||
struct ieee80211_sta *sta,
|
||||
u32 rate_ctrl_flag, u8 nss)
|
||||
{
|
||||
- if (nss > sta->rx_nss) {
|
||||
+ struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
+ struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
+
|
||||
+ if (nss > sta->deflink.rx_nss) {
|
||||
ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n",
|
||||
- nss, sta->rx_nss);
|
||||
+ nss, sta->deflink.rx_nss);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) {
|
||||
- if (!sta->vht_cap.vht_supported) {
|
||||
+ if (!vht_cap->vht_supported) {
|
||||
ath10k_warn(ar, "Invalid VHT rate for sta %pM\n",
|
||||
sta->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) {
|
||||
- if (!sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) {
|
||||
+ if (!ht_cap->ht_supported || vht_cap->vht_supported) {
|
||||
ath10k_warn(ar, "Invalid HT rate for sta %pM\n",
|
||||
sta->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
- if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported)
|
||||
+ if (ht_cap->ht_supported || vht_cap->vht_supported)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -8567,7 +8572,7 @@ static int ath10k_sta_state(struct ieee8
|
||||
* New association.
|
||||
*/
|
||||
ath10k_dbg(ar, ATH10K_DBG_STA, "mac sta %pM associated, bandwidth: %d\n",
|
||||
- sta->addr, sta->bandwidth);
|
||||
+ sta->addr, sta->deflink.bandwidth);
|
||||
|
||||
ret = ath10k_station_assoc(ar, vif, sta, false);
|
||||
if (ret)
|
||||
@@ -8580,7 +8585,7 @@ static int ath10k_sta_state(struct ieee8
|
||||
* Tdls station authorized.
|
||||
*/
|
||||
ath10k_dbg(ar, ATH10K_DBG_STA, "mac tdls sta %pM authorized, bandwidth: %d\n",
|
||||
- sta->addr, sta->bandwidth);
|
||||
+ sta->addr, sta->deflink.bandwidth);
|
||||
|
||||
ret = ath10k_station_assoc(ar, vif, sta, false);
|
||||
if (ret) {
|
||||
@@ -8721,8 +8726,8 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int ath10k_conf_tx(struct ieee80211_hw *hw,
|
||||
- struct ieee80211_vif *vif, u16 ac,
|
||||
+static int ath10k_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
+ unsigned int link_id, u16 ac,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
@@ -9308,7 +9313,7 @@ static bool ath10k_mac_set_vht_bitrate_m
|
||||
u8 rate = arvif->vht_pfr;
|
||||
|
||||
/* skip non vht and multiple rate peers */
|
||||
- if (!sta->vht_cap.vht_supported || arvif->vht_num_rates != 1)
|
||||
+ if (!sta->deflink.vht_cap.vht_supported || arvif->vht_num_rates != 1)
|
||||
return false;
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
@@ -9349,7 +9354,7 @@ static void ath10k_mac_clr_bitrate_mask_
|
||||
int err;
|
||||
|
||||
/* clear vht peers only */
|
||||
- if (arsta->arvif != arvif || !sta->vht_cap.vht_supported)
|
||||
+ if (arsta->arvif != arvif || !sta->deflink.vht_cap.vht_supported)
|
||||
return;
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
@@ -9534,13 +9539,13 @@ static void ath10k_sta_rc_update(struct
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_STA,
|
||||
"mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
|
||||
- sta->addr, changed, sta->bandwidth, sta->rx_nss,
|
||||
- sta->smps_mode);
|
||||
+ sta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss,
|
||||
+ sta->deflink.smps_mode);
|
||||
|
||||
if (changed & IEEE80211_RC_BW_CHANGED) {
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
|
||||
- switch (sta->bandwidth) {
|
||||
+ switch (sta->deflink.bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
@@ -9555,7 +9560,7 @@ static void ath10k_sta_rc_update(struct
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n",
|
||||
- sta->bandwidth, sta->addr);
|
||||
+ sta->deflink.bandwidth, sta->addr);
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
}
|
||||
@@ -9564,12 +9569,12 @@ static void ath10k_sta_rc_update(struct
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_RC_NSS_CHANGED)
|
||||
- arsta->nss = sta->rx_nss;
|
||||
+ arsta->nss = sta->deflink.rx_nss;
|
||||
|
||||
if (changed & IEEE80211_RC_SMPS_CHANGED) {
|
||||
smps = WMI_PEER_SMPS_PS_NONE;
|
||||
|
||||
- switch (sta->smps_mode) {
|
||||
+ switch (sta->deflink.smps_mode) {
|
||||
case IEEE80211_SMPS_AUTOMATIC:
|
||||
case IEEE80211_SMPS_OFF:
|
||||
smps = WMI_PEER_SMPS_PS_NONE;
|
||||
@@ -9582,7 +9587,7 @@ static void ath10k_sta_rc_update(struct
|
||||
break;
|
||||
case IEEE80211_SMPS_NUM_MODES:
|
||||
ath10k_warn(ar, "Invalid smps %d in sta rc update for %pM\n",
|
||||
- sta->smps_mode, sta->addr);
|
||||
+ sta->deflink.smps_mode, sta->addr);
|
||||
smps = WMI_PEER_SMPS_PS_NONE;
|
||||
break;
|
||||
}
|
||||
@@ -9896,7 +9901,7 @@ ath10k_mac_change_chanctx_cnt_iter(void
|
||||
{
|
||||
struct ath10k_mac_change_chanctx_arg *arg = data;
|
||||
|
||||
- if (rcu_access_pointer(vif->chanctx_conf) != arg->ctx)
|
||||
+ if (rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx)
|
||||
return;
|
||||
|
||||
arg->n_vifs++;
|
||||
@@ -9909,7 +9914,7 @@ ath10k_mac_change_chanctx_fill_iter(void
|
||||
struct ath10k_mac_change_chanctx_arg *arg = data;
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
|
||||
- ctx = rcu_access_pointer(vif->chanctx_conf);
|
||||
+ ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf);
|
||||
if (ctx != arg->ctx)
|
||||
return;
|
||||
|
||||
@@ -9982,6 +9987,7 @@ unlock:
|
||||
static int
|
||||
ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
+ struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
@@ -10061,6 +10067,7 @@ err:
|
||||
static void
|
||||
ath10k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
+ struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
--- a/ath10k-5.15/txrx.c
|
||||
+++ b/ath10k-5.15/txrx.c
|
||||
@@ -260,7 +260,7 @@ int ath10k_txrx_tx_unref(struct ath10k_h
|
||||
nf = ar->debug.nf_sum[0];
|
||||
#endif
|
||||
info->status.ack_signal = nf + tx_done->ack_rssi;
|
||||
- info->status.is_valid_ack_signal = true;
|
||||
+ info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
|
||||
}
|
||||
|
||||
if (tx_done->tx_rate_code || tx_done->tx_rate_flags || ar->ok_tx_rate_status) {
|
||||
--- a/ath10k-5.15/wmi.c
|
||||
+++ b/ath10k-5.15/wmi.c
|
||||
@@ -2587,7 +2587,7 @@ wmi_process_mgmt_tx_comp(struct ath10k *
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->status.ack_signal = ath10k_get_noisefloor(0, ar) +
|
||||
param->ack_rssi;
|
||||
- info->status.is_valid_ack_signal = true;
|
||||
+ info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
|
||||
}
|
||||
|
||||
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
||||
@@ -4258,13 +4258,13 @@ void ath10k_wmi_event_host_swba(struct a
|
||||
* Once CSA counter is completed stop sending beacons until
|
||||
* actual channel switch is done
|
||||
*/
|
||||
- if (arvif->vif->csa_active &&
|
||||
+ if (arvif->vif->bss_conf.csa_active &&
|
||||
ieee80211_beacon_cntdwn_is_complete(arvif->vif)) {
|
||||
ieee80211_csa_finish(arvif->vif);
|
||||
continue;
|
||||
}
|
||||
|
||||
- bcn = ieee80211_beacon_get(ar->hw, arvif->vif);
|
||||
+ bcn = ieee80211_beacon_get(ar->hw, arvif->vif, 0);
|
||||
if (!bcn) {
|
||||
ath10k_warn(ar, "could not get mac80211 beacon, vdev_id: %i addr: %pM\n",
|
||||
arvif->vdev_id, arvif->vif->addr);
|
||||
--- a/ath10k-5.15/htt_rx.c
|
||||
+++ b/ath10k-5.15/htt_rx.c
|
||||
@@ -4017,7 +4017,7 @@ ath10k_update_per_peer_tx_stats(struct a
|
||||
switch (txrate.flags) {
|
||||
case WMI_RATE_PREAMBLE_OFDM:
|
||||
if (arsta->arvif && arsta->arvif->vif)
|
||||
- conf = rcu_dereference(arsta->arvif->vif->chanctx_conf);
|
||||
+ conf = rcu_dereference(arsta->arvif->vif->bss_conf.chanctx_conf);
|
||||
if (conf && conf->def.chan->band == NL80211_BAND_5GHZ)
|
||||
arsta->tx_info.status.rates[0].idx = rate_idx - 4;
|
||||
break;
|
||||
--- a/ath10k-5.15/wmi-tlv.c
|
||||
+++ b/ath10k-5.15/wmi-tlv.c
|
||||
@@ -205,7 +205,7 @@ static int ath10k_wmi_tlv_event_bcn_tx_s
|
||||
}
|
||||
|
||||
arvif = ath10k_get_arvif(ar, vdev_id);
|
||||
- if (arvif && arvif->is_up && arvif->vif->csa_active)
|
||||
+ if (arvif && arvif->is_up && arvif->vif->bss_conf.csa_active)
|
||||
ieee80211_queue_work(ar->hw, &arvif->ap_csa_work);
|
||||
|
||||
kfree(tb);
|
||||
--- a/ath10k-5.15/core.c
|
||||
+++ b/ath10k-5.15/core.c
|
||||
@@ -4081,7 +4081,7 @@ static int ath10k_core_probe_fw(struct a
|
||||
ath10k_debug_print_board_info(ar);
|
||||
}
|
||||
|
||||
- device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr));
|
||||
+ device_get_mac_address(ar->dev, ar->mac_addr);
|
||||
|
||||
/* Try to get mac address from device node (from nvmem cell) */
|
||||
of_get_mac_address(ar->dev->of_node, ar->mac_addr);
|
||||
--- a/ath10k-5.15/pci.c
|
||||
+++ b/ath10k-5.15/pci.c
|
||||
@@ -3547,8 +3547,7 @@ static void ath10k_pci_free_irq(struct a
|
||||
|
||||
void ath10k_pci_init_napi(struct ath10k *ar)
|
||||
{
|
||||
- netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_pci_napi_poll,
|
||||
- ATH10K_NAPI_BUDGET);
|
||||
+ netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_pci_napi_poll);
|
||||
}
|
||||
|
||||
static int ath10k_pci_init_irq(struct ath10k *ar)
|
||||
--- a/ath10k-5.15/sdio.c
|
||||
+++ b/ath10k-5.15/sdio.c
|
||||
@@ -2531,8 +2531,7 @@ static int ath10k_sdio_probe(struct sdio
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
- netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_sdio_napi_poll,
|
||||
- ATH10K_NAPI_BUDGET);
|
||||
+ netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_sdio_napi_poll);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"sdio new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
|
||||
--- a/ath10k-5.15/snoc.c
|
||||
+++ b/ath10k-5.15/snoc.c
|
||||
@@ -1242,8 +1242,7 @@ static int ath10k_snoc_napi_poll(struct
|
||||
|
||||
static void ath10k_snoc_init_napi(struct ath10k *ar)
|
||||
{
|
||||
- netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_snoc_napi_poll,
|
||||
- ATH10K_NAPI_BUDGET);
|
||||
+ netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_snoc_napi_poll);
|
||||
}
|
||||
|
||||
static int ath10k_snoc_request_irq(struct ath10k *ar)
|
@ -42,7 +42,7 @@ Signed-off-by: Mathias Kresin <dev@kresin.me>
|
||||
if (ret)
|
||||
--- a/ath10k-5.15/mac.c
|
||||
+++ b/ath10k-5.15/mac.c
|
||||
@@ -11544,7 +11544,7 @@ int ath10k_mac_register(struct ath10k *a
|
||||
@@ -11551,7 +11551,7 @@ int ath10k_mac_register(struct ath10k *a
|
||||
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
|
||||
|
||||
#ifdef CPTCFG_MAC80211_LEDS
|
||||
|
@ -10,10 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=mac80211
|
||||
|
||||
PKG_VERSION:=5.15.81-1
|
||||
PKG_VERSION:=6.1-rc8
|
||||
PKG_RELEASE:=1
|
||||
PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.15.81/
|
||||
PKG_HASH:=5227d3c35ccebacfaee6b8180b3a87b9910f3c94ee768ebc5c0fef3c86b6146d
|
||||
# PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.15.58/
|
||||
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
|
||||
PKG_HASH:=7f3d96c2573183cd79d6a3ebe5e1b7b73c19d1326d443c85b69c4181f14e6e2b
|
||||
|
||||
PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz
|
||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION)
|
||||
|
@ -82,7 +82,7 @@
|
||||
help
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -106,6 +106,7 @@ ADM8211=
|
||||
@@ -110,6 +110,7 @@ ADM8211=
|
||||
ATH_COMMON=
|
||||
WLAN_VENDOR_ATH=
|
||||
ATH_DEBUG=
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/net/wireless/reg.c
|
||||
+++ b/net/wireless/reg.c
|
||||
@@ -3315,6 +3315,8 @@ void regulatory_hint_country_ie(struct w
|
||||
@@ -3370,6 +3370,8 @@ void regulatory_hint_country_ie(struct w
|
||||
enum environment_cap env = ENVIRON_ANY;
|
||||
struct regulatory_request *request = NULL, *lr;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
/* IE len must be evenly divisible by 2 */
|
||||
if (country_ie_len & 0x01)
|
||||
return;
|
||||
@@ -3566,6 +3568,7 @@ static bool is_wiphy_all_set_reg_flag(en
|
||||
@@ -3621,6 +3623,7 @@ static bool is_wiphy_all_set_reg_flag(en
|
||||
|
||||
void regulatory_hint_disconnect(void)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
FRANCE_RES = 0x31,
|
||||
FCC3_FCCA = 0x3A,
|
||||
FCC3_WORLD = 0x3B,
|
||||
@@ -172,6 +173,7 @@ static struct reg_dmn_pair_mapping regDo
|
||||
@@ -173,6 +174,7 @@ static struct reg_dmn_pair_mapping regDo
|
||||
{FCC2_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{FCC2_ETSIC, CTL_FCC, CTL_ETSI},
|
||||
{FCC3_FCCA, CTL_FCC, CTL_FCC},
|
||||
@ -16,7 +16,7 @@
|
||||
{FCC3_WORLD, CTL_FCC, CTL_ETSI},
|
||||
{FCC3_ETSIC, CTL_FCC, CTL_ETSI},
|
||||
{FCC4_FCCA, CTL_FCC, CTL_FCC},
|
||||
@@ -483,6 +485,7 @@ static struct country_code_to_enum_rd al
|
||||
@@ -486,6 +488,7 @@ static struct country_code_to_enum_rd al
|
||||
{CTRY_UAE, NULL1_WORLD, "AE"},
|
||||
{CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
|
||||
{CTRY_UNITED_STATES, FCC3_FCCA, "US"},
|
||||
|
@ -37,7 +37,7 @@
|
||||
void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -165,6 +165,7 @@ ATH10K_SNOC=
|
||||
@@ -169,6 +169,7 @@ ATH10K_SNOC=
|
||||
ATH10K_DEBUG=
|
||||
ATH10K_DEBUGFS=
|
||||
ATH10K_SPECTRAL=
|
||||
|
@ -1,69 +0,0 @@
|
||||
From 2587d5198aa5adcbd8896aae4a2404dc13d48637 Mon Sep 17 00:00:00 2001
|
||||
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
Date: Wed, 18 May 2022 10:27:26 +0300
|
||||
Subject: ath10k: improve tx status reporting
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We use ieee80211_tx_status() to report each completed tx frame.
|
||||
Internally, this function calls sta_info_get_by_addrs(), what has a
|
||||
couple of drawbacks:
|
||||
1. additional station lookup causes a performance degradation;
|
||||
2. mac80211 can not properly account Ethernet encapsulated frames due
|
||||
to the inability to properly determine the destination (station) MAC
|
||||
address since ieee80211_tx_status() assumes the frame has a 802.11
|
||||
header.
|
||||
|
||||
The latter is especially destructive if we want to use hardware frames
|
||||
encapsulation.
|
||||
|
||||
To fix both of these issues, replace ieee80211_tx_status() with
|
||||
ieee80211_tx_status_ext() call and feed it station pointer from the tx
|
||||
queue associated with the transmitted frame.
|
||||
|
||||
Tested-on: QCA9888 hw2.0 PCI 10.4-3.9.0.2-00131
|
||||
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00157-QCARMSWPZ-1
|
||||
|
||||
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
Tested-by: Oldřich Jedlička <oldium.pro@gmail.com> # TP-Link Archer C7 v4 & v5 (QCA9563 + QCA9880)
|
||||
Tested-by: Edward Matijevic <motolav@gmail.com> # TP-Link Archer C2600 (IPQ8064 + QCA9980 10.4.1.00030-1)
|
||||
Tested-by: Edward Matijevic <motolav@gmail.com> # QCA9377 PCI in Sta mode
|
||||
Tested-by: Zhijun You <hujy652@gmail.com> # NETGEAR R7800 (QCA9984 10.4-3.9.0.2-00159)
|
||||
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20220516032519.29831-2-ryazanov.s.a@gmail.com
|
||||
---
|
||||
drivers/net/wireless/ath/ath10k/txrx.c | 15 ++++++++++++++-
|
||||
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/txrx.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
|
||||
@@ -43,6 +43,7 @@ out:
|
||||
int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
const struct htt_tx_done *tx_done)
|
||||
{
|
||||
+ struct ieee80211_tx_status status;
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct device *dev = ar->dev;
|
||||
struct ieee80211_tx_info *info;
|
||||
@@ -128,7 +129,19 @@ int ath10k_txrx_tx_unref(struct ath10k_h
|
||||
info->status.is_valid_ack_signal = true;
|
||||
}
|
||||
|
||||
- ieee80211_tx_status(htt->ar->hw, msdu);
|
||||
+ memset(&status, 0, sizeof(status));
|
||||
+ status.skb = msdu;
|
||||
+ status.info = info;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+
|
||||
+ if (txq)
|
||||
+ status.sta = txq->sta;
|
||||
+
|
||||
+ ieee80211_tx_status_ext(htt->ar->hw, &status);
|
||||
+
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
/* we do not own the msdu anymore */
|
||||
|
||||
return 0;
|
@ -1,74 +0,0 @@
|
||||
From a09740548275a74b897654b3aca5af589289b57a Mon Sep 17 00:00:00 2001
|
||||
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
Date: Mon, 16 May 2022 13:26:00 +0300
|
||||
Subject: ath10k: turn rawmode into frame_mode
|
||||
|
||||
Turn boolean rawmode module param into integer frame_mode param that
|
||||
contains value from ath10k_hw_txrx_mode enum. As earlier the default
|
||||
param value is non-RAW (native Wi-Fi) encapsulation. The param name
|
||||
is selected to be consistent with the similar ath11k param.
|
||||
|
||||
This is a preparation step for upcoming encapsulation offloading
|
||||
support.
|
||||
|
||||
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20220516032519.29831-4-ryazanov.s.a@gmail.com
|
||||
---
|
||||
drivers/net/wireless/ath/ath10k/core.c | 11 +++++++----
|
||||
drivers/net/wireless/ath/ath10k/core.h | 1 +
|
||||
2 files changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
||||
@@ -32,9 +32,11 @@ EXPORT_SYMBOL(ath10k_debug_mask);
|
||||
static unsigned int ath10k_cryptmode_param;
|
||||
static bool uart_print;
|
||||
static bool skip_otp;
|
||||
-static bool rawmode;
|
||||
static bool fw_diag_log;
|
||||
|
||||
+/* frame mode values are mapped as per enum ath10k_hw_txrx_mode */
|
||||
+unsigned int ath10k_frame_mode = ATH10K_HW_TXRX_NATIVE_WIFI;
|
||||
+
|
||||
unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) |
|
||||
BIT(ATH10K_FW_CRASH_DUMP_CE_DATA);
|
||||
|
||||
@@ -43,15 +45,16 @@ module_param_named(debug_mask, ath10k_de
|
||||
module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
|
||||
module_param(uart_print, bool, 0644);
|
||||
module_param(skip_otp, bool, 0644);
|
||||
-module_param(rawmode, bool, 0644);
|
||||
module_param(fw_diag_log, bool, 0644);
|
||||
+module_param_named(frame_mode, ath10k_frame_mode, uint, 0644);
|
||||
module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444);
|
||||
|
||||
MODULE_PARM_DESC(debug_mask, "Debugging mask");
|
||||
MODULE_PARM_DESC(uart_print, "Uart target debugging");
|
||||
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
|
||||
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
|
||||
-MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
|
||||
+MODULE_PARM_DESC(frame_mode,
|
||||
+ "Datapath frame mode (0: raw, 1: native wifi (default))");
|
||||
MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
|
||||
MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging");
|
||||
|
||||
@@ -2487,7 +2490,7 @@ static int ath10k_core_init_firmware_fea
|
||||
ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
|
||||
ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;
|
||||
|
||||
- if (rawmode) {
|
||||
+ if (ath10k_frame_mode == ATH10K_HW_TXRX_RAW) {
|
||||
if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
|
||||
fw_file->fw_features)) {
|
||||
ath10k_err(ar, "rawmode = 1 requires support from firmware");
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.h
|
||||
@@ -1311,6 +1311,7 @@ static inline bool ath10k_peer_stats_ena
|
||||
return false;
|
||||
}
|
||||
|
||||
+extern unsigned int ath10k_frame_mode;
|
||||
extern unsigned long ath10k_coredump_mask;
|
||||
|
||||
void ath10k_core_napi_sync_disable(struct ath10k *ar);
|
@ -1,163 +0,0 @@
|
||||
From 70f119fb82af7f7417dc659faf02c91e1f853739 Mon Sep 17 00:00:00 2001
|
||||
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
Date: Mon, 16 May 2022 13:26:00 +0300
|
||||
Subject: ath10k: htt_tx: do not interpret Eth frames as WiFi
|
||||
|
||||
The xmit path for the Ethernet encapsulated frames become more or less
|
||||
usable since d740d8fd2439 ("ath10k: unify tx mode and dispatch"). This
|
||||
change reorganize the xmit path in a manageable way to properly support
|
||||
various tx modes, but misses that the Ethernet encapsulated frame is a
|
||||
special case. We do not have an IEEE 802.11 header at the begining of
|
||||
them. But the HTT Tx handler still interprets first bytes of each frame
|
||||
as an IEEE 802.11 Frame Control field.
|
||||
|
||||
Than this code was copied by e62ee5c381c5 ("ath10k: Add support for
|
||||
htt_data_tx_desc_64 descriptor") and a2097d6444c3 ("ath10k: htt: High
|
||||
latency TX support") to another handlers. In fact the issue in the high
|
||||
latency (HL) handler was introduced by 83ac260151e7 ("ath10k: add mic
|
||||
bytes for pmf management packet").
|
||||
|
||||
Ethernet encapsulated frame tx mode stay unused until 75d85fd9993c
|
||||
("ath10k: introduce basic tdls functionality") started using it for TDLS
|
||||
frames to avoid key selection issue in some firmwares.
|
||||
|
||||
Trying to interpret the begining of an Ethernet encapsulated frame as an
|
||||
IEEE 802.11 header was not hurt us noticeably since we need to meet two
|
||||
conditions: (1) xmit should be performed towards a TDLS peer, and (2)
|
||||
the TDLS peer should have a specific OUI part of its MAC address. Looks
|
||||
like that the rareness in TDLS communications of OUIs that can be
|
||||
interpreted as an 802.11 management frame saves users from facing this
|
||||
issue earlier.
|
||||
|
||||
Improve Ethernet tx mode support in the HTT Tx handler by avoiding
|
||||
interpreting its first bytes as an IEEE 802.11 header. While at it, make
|
||||
the ieee80211_hdr variable local to the code block that is guarded by
|
||||
!is_eth check. In this way, we clarify in which cases a frame can be
|
||||
interpreted as IEEE 802.11, and saves us from similar issues in the
|
||||
future.
|
||||
|
||||
Credits: this change as part of xmit encapsulation offloading support
|
||||
was originally made by QCA and then submitted for inclusion by John
|
||||
Crispin [1]. But the whole work was not accepted due to the lack of a
|
||||
part for 64-bits descriptors [2]. Zhijun You then pointed this out to me
|
||||
in a reply to my initial RFC patch series. And I made this slightly
|
||||
reworked version that covered all the HTT Tx handler variants.
|
||||
|
||||
1. https://lore.kernel.org/all/20191216092207.31032-1-john@phrozen.org/
|
||||
2. https://patchwork.kernel.org/project/linux-wireless/patch/20191216092207.31032-1-john@phrozen.org/
|
||||
|
||||
Reported-by: Zhijun You <hujy652@gmail.com>
|
||||
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
|
||||
Signed-off-by: John Crispin <john@phrozen.org>
|
||||
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20220516032519.29831-3-ryazanov.s.a@gmail.com
|
||||
---
|
||||
drivers/net/wireless/ath/ath10k/htt_tx.c | 61 ++++++++++++++++++--------------
|
||||
1 file changed, 35 insertions(+), 26 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
|
||||
@@ -1295,7 +1295,6 @@ static int ath10k_htt_tx_hl(struct ath10
|
||||
struct ath10k *ar = htt->ar;
|
||||
int res, data_len;
|
||||
struct htt_cmd_hdr *cmd_hdr;
|
||||
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
struct htt_data_tx_desc *tx_desc;
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
|
||||
struct sk_buff *tmp_skb;
|
||||
@@ -1306,11 +1305,15 @@ static int ath10k_htt_tx_hl(struct ath10
|
||||
u16 flags1 = 0;
|
||||
u16 msdu_id = 0;
|
||||
|
||||
- if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
- ieee80211_is_deauth(hdr->frame_control) ||
|
||||
- ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
- ieee80211_has_protected(hdr->frame_control)) {
|
||||
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
+ if (!is_eth) {
|
||||
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
+
|
||||
+ if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
+ ieee80211_is_deauth(hdr->frame_control) ||
|
||||
+ ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
+ ieee80211_has_protected(hdr->frame_control)) {
|
||||
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
+ }
|
||||
}
|
||||
|
||||
data_len = msdu->len;
|
||||
@@ -1407,7 +1410,6 @@ static int ath10k_htt_tx_32(struct ath10
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct device *dev = ar->dev;
|
||||
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
|
||||
struct ath10k_hif_sg_item sg_items[2];
|
||||
@@ -1439,15 +1441,19 @@ static int ath10k_htt_tx_32(struct ath10
|
||||
txbuf_paddr = htt->txbuf.paddr +
|
||||
(sizeof(struct ath10k_htt_txbuf_32) * msdu_id);
|
||||
|
||||
- if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
- ieee80211_is_deauth(hdr->frame_control) ||
|
||||
- ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
- ieee80211_has_protected(hdr->frame_control)) {
|
||||
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
- } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
|
||||
- txmode == ATH10K_HW_TXRX_RAW &&
|
||||
- ieee80211_has_protected(hdr->frame_control)) {
|
||||
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
+ if (!is_eth) {
|
||||
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
+
|
||||
+ if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
+ ieee80211_is_deauth(hdr->frame_control) ||
|
||||
+ ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
+ ieee80211_has_protected(hdr->frame_control)) {
|
||||
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
+ } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
|
||||
+ txmode == ATH10K_HW_TXRX_RAW &&
|
||||
+ ieee80211_has_protected(hdr->frame_control)) {
|
||||
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
+ }
|
||||
}
|
||||
|
||||
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
|
||||
@@ -1609,7 +1615,6 @@ static int ath10k_htt_tx_64(struct ath10
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct device *dev = ar->dev;
|
||||
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
|
||||
struct ath10k_hif_sg_item sg_items[2];
|
||||
@@ -1641,15 +1646,19 @@ static int ath10k_htt_tx_64(struct ath10
|
||||
txbuf_paddr = htt->txbuf.paddr +
|
||||
(sizeof(struct ath10k_htt_txbuf_64) * msdu_id);
|
||||
|
||||
- if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
- ieee80211_is_deauth(hdr->frame_control) ||
|
||||
- ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
- ieee80211_has_protected(hdr->frame_control)) {
|
||||
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
- } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
|
||||
- txmode == ATH10K_HW_TXRX_RAW &&
|
||||
- ieee80211_has_protected(hdr->frame_control)) {
|
||||
- skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
+ if (!is_eth) {
|
||||
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
+
|
||||
+ if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
+ ieee80211_is_deauth(hdr->frame_control) ||
|
||||
+ ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
+ ieee80211_has_protected(hdr->frame_control)) {
|
||||
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
+ } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
|
||||
+ txmode == ATH10K_HW_TXRX_RAW &&
|
||||
+ ieee80211_has_protected(hdr->frame_control)) {
|
||||
+ skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
+ }
|
||||
}
|
||||
|
||||
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
|
@ -1,194 +0,0 @@
|
||||
From af6d8265c47e46881b80c6b073f53c8c4af52d28 Mon Sep 17 00:00:00 2001
|
||||
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
Date: Mon, 16 May 2022 13:26:00 +0300
|
||||
Subject: ath10k: add encapsulation offloading support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Frame encapsulation from Ethernet into the IEEE 802.11 frame format
|
||||
takes a considerable host CPU time on the xmit path. The firmware is
|
||||
able to do this operation for us, so enable encapsulation offloading for
|
||||
AP and Sta interface types to improve overall system performance.
|
||||
|
||||
The driver is almost ready for encapsulation offloading support. There
|
||||
are only a few places where the driver assumes the frame format is IEEE
|
||||
802.11 that need to be fixed.
|
||||
|
||||
Encapsulation offloading is currently disabled by default and the driver
|
||||
utilizes mac80211 encapsulation support. To activate offloading, the
|
||||
frame_mode=2 parameter should be passed during module loading.
|
||||
|
||||
On a QCA9563+QCA9888-based access point in bridged mode, encapsulation
|
||||
offloading increases TCP 16-streams DL throughput from 365 to 396 mbps
|
||||
(+8%) and UDP DL throughput from 436 to 483 mbps (+11%).
|
||||
|
||||
Tested-on: QCA9888 hw2.0 PCI 10.4-3.9.0.2-00131
|
||||
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00157-QCARMSWPZ-1
|
||||
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
Tested-by: Oldřich Jedlička <oldium.pro@gmail.com> # TP-Link Archer C7 v4 & v5 (QCA9563 + QCA9880)
|
||||
Tested-by: Edward Matijevic <motolav@gmail.com> # TP-Link Archer C2600 (IPQ8064 + QCA9980 10.4.1.00030-1)
|
||||
Tested-by: Edward Matijevic <motolav@gmail.com> # QCA9377 PCI in Sta mode
|
||||
Tested-by: Zhijun You <hujy652@gmail.com> # NETGEAR R7800 (QCA9984 10.4-3.9.0.2-00159)
|
||||
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20220516032519.29831-5-ryazanov.s.a@gmail.com
|
||||
---
|
||||
drivers/net/wireless/ath/ath10k/core.c | 2 +-
|
||||
drivers/net/wireless/ath/ath10k/mac.c | 67 +++++++++++++++++++++++++++-------
|
||||
2 files changed, 55 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
||||
@@ -54,7 +54,7 @@ MODULE_PARM_DESC(uart_print, "Uart targe
|
||||
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
|
||||
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
|
||||
MODULE_PARM_DESC(frame_mode,
|
||||
- "Datapath frame mode (0: raw, 1: native wifi (default))");
|
||||
+ "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
|
||||
MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
|
||||
MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging");
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||
@@ -3717,6 +3717,9 @@ ath10k_mac_tx_h_get_txmode(struct ath10k
|
||||
const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
|
||||
__le16 fc = hdr->frame_control;
|
||||
|
||||
+ if (IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
|
||||
+ return ATH10K_HW_TXRX_ETHERNET;
|
||||
+
|
||||
if (!vif || vif->type == NL80211_IFTYPE_MONITOR)
|
||||
return ATH10K_HW_TXRX_RAW;
|
||||
|
||||
@@ -3877,6 +3880,12 @@ static void ath10k_mac_tx_h_fill_cb(stru
|
||||
bool noack = false;
|
||||
|
||||
cb->flags = 0;
|
||||
+
|
||||
+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
|
||||
+ cb->flags |= ATH10K_SKB_F_QOS; /* Assume data frames are QoS */
|
||||
+ goto finish_cb_fill;
|
||||
+ }
|
||||
+
|
||||
if (!ath10k_tx_h_use_hwcrypto(vif, skb))
|
||||
cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
|
||||
|
||||
@@ -3915,6 +3924,7 @@ static void ath10k_mac_tx_h_fill_cb(stru
|
||||
cb->flags |= ATH10K_SKB_F_RAW_TX;
|
||||
}
|
||||
|
||||
+finish_cb_fill:
|
||||
cb->vif = vif;
|
||||
cb->txq = txq;
|
||||
cb->airtime_est = airtime;
|
||||
@@ -4038,7 +4048,11 @@ static int ath10k_mac_tx(struct ath10k *
|
||||
ath10k_tx_h_seq_no(vif, skb);
|
||||
break;
|
||||
case ATH10K_HW_TXRX_ETHERNET:
|
||||
- ath10k_tx_h_8023(skb);
|
||||
+ /* Convert 802.11->802.3 header only if the frame was erlier
|
||||
+ * encapsulated to 802.11 by mac80211. Otherwise pass it as is.
|
||||
+ */
|
||||
+ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
|
||||
+ ath10k_tx_h_8023(skb);
|
||||
break;
|
||||
case ATH10K_HW_TXRX_RAW:
|
||||
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) &&
|
||||
@@ -4650,12 +4664,10 @@ static void ath10k_mac_op_tx(struct ieee
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct ieee80211_sta *sta = control->sta;
|
||||
struct ieee80211_txq *txq = NULL;
|
||||
- struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
enum ath10k_hw_txrx_mode txmode;
|
||||
enum ath10k_mac_tx_path txpath;
|
||||
bool is_htt;
|
||||
bool is_mgmt;
|
||||
- bool is_presp;
|
||||
int ret;
|
||||
u16 airtime;
|
||||
|
||||
@@ -4669,8 +4681,14 @@ static void ath10k_mac_op_tx(struct ieee
|
||||
is_mgmt = (txpath == ATH10K_MAC_TX_HTT_MGMT);
|
||||
|
||||
if (is_htt) {
|
||||
+ bool is_presp = false;
|
||||
+
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
- is_presp = ieee80211_is_probe_resp(hdr->frame_control);
|
||||
+ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) {
|
||||
+ struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
+
|
||||
+ is_presp = ieee80211_is_probe_resp(hdr->frame_control);
|
||||
+ }
|
||||
|
||||
ret = ath10k_htt_tx_inc_pending(htt);
|
||||
if (ret) {
|
||||
@@ -5470,6 +5488,30 @@ static int ath10k_mac_set_txbf_conf(stru
|
||||
ar->wmi.vdev_param->txbf, value);
|
||||
}
|
||||
|
||||
+static void ath10k_update_vif_offload(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_vif *vif)
|
||||
+{
|
||||
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
+ struct ath10k *ar = hw->priv;
|
||||
+ u32 vdev_param;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (ath10k_frame_mode != ATH10K_HW_TXRX_ETHERNET ||
|
||||
+ ar->wmi.vdev_param->tx_encap_type == WMI_VDEV_PARAM_UNSUPPORTED ||
|
||||
+ (vif->type != NL80211_IFTYPE_STATION &&
|
||||
+ vif->type != NL80211_IFTYPE_AP))
|
||||
+ vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
|
||||
+
|
||||
+ vdev_param = ar->wmi.vdev_param->tx_encap_type;
|
||||
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
|
||||
+ ATH10K_HW_TXRX_NATIVE_WIFI);
|
||||
+ /* 10.X firmware does not support this VDEV parameter. Do not warn */
|
||||
+ if (ret && ret != -EOPNOTSUPP) {
|
||||
+ ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n",
|
||||
+ arvif->vdev_id, ret);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* TODO:
|
||||
* Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
|
||||
@@ -5679,15 +5721,7 @@ static int ath10k_add_interface(struct i
|
||||
|
||||
arvif->def_wep_key_idx = -1;
|
||||
|
||||
- vdev_param = ar->wmi.vdev_param->tx_encap_type;
|
||||
- ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
|
||||
- ATH10K_HW_TXRX_NATIVE_WIFI);
|
||||
- /* 10.X firmware does not support this VDEV parameter. Do not warn */
|
||||
- if (ret && ret != -EOPNOTSUPP) {
|
||||
- ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n",
|
||||
- arvif->vdev_id, ret);
|
||||
- goto err_vdev_delete;
|
||||
- }
|
||||
+ ath10k_update_vif_offload(hw, vif);
|
||||
|
||||
/* Configuring number of spatial stream for monitor interface is causing
|
||||
* target assert in qca9888 and qca6174.
|
||||
@@ -9372,6 +9406,7 @@ static const struct ieee80211_ops ath10k
|
||||
.stop = ath10k_stop,
|
||||
.config = ath10k_config,
|
||||
.add_interface = ath10k_add_interface,
|
||||
+ .update_vif_offload = ath10k_update_vif_offload,
|
||||
.remove_interface = ath10k_remove_interface,
|
||||
.configure_filter = ath10k_configure_filter,
|
||||
.bss_info_changed = ath10k_bss_info_changed,
|
||||
@@ -10041,6 +10076,12 @@ int ath10k_mac_register(struct ath10k *a
|
||||
if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_TDLS_BUFFER_STA);
|
||||
|
||||
+ if (ath10k_frame_mode == ATH10K_HW_TXRX_ETHERNET) {
|
||||
+ if (ar->wmi.vdev_param->tx_encap_type !=
|
||||
+ WMI_VDEV_PARAM_UNSUPPORTED)
|
||||
+ ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
|
||||
+ }
|
||||
+
|
||||
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||
ar->hw->wiphy->max_remain_on_channel_duration = 5000;
|
@ -1,65 +0,0 @@
|
||||
From f2a7064a78b22f2b68b9fcbc8a6f4c5e61c5ba64 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robimarko@gmail.com>
|
||||
Date: Sun, 10 Oct 2021 00:17:11 +0200
|
||||
Subject: [PATCH] ath10k: support bus and device specific API 1 BDF selection
|
||||
|
||||
Some ath10k IPQ40xx devices like the MikroTik hAP ac2 and ac3 require the
|
||||
BDF-s to be extracted from the device storage instead of shipping packaged
|
||||
API 2 BDF-s.
|
||||
|
||||
This is required as MikroTik has started shipping boards that require BDF-s
|
||||
to be updated, as otherwise their WLAN performance really suffers.
|
||||
This is however impossible as the devices that require this are release
|
||||
under the same revision and its not possible to differentiate them from
|
||||
devices using the older BDF-s.
|
||||
|
||||
In OpenWrt we are extracting the calibration data during runtime and we are
|
||||
able to extract the BDF-s in the same manner, however we cannot package the
|
||||
BDF-s to API 2 format on the fly and can only use API 1 to provide BDF-s on
|
||||
the fly.
|
||||
This is an issue as the ath10k driver explicitly looks only for the
|
||||
board.bin file and not for something like board-bus-device.bin like it does
|
||||
for pre-cal data.
|
||||
Due to this we have no way of providing correct BDF-s on the fly, so lets
|
||||
extend the ath10k driver to first look for BDF-s in the
|
||||
board-bus-device.bin format, for example: board-ahb-a800000.wifi.bin
|
||||
If that fails, look for the default board file name as defined previously.
|
||||
|
||||
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20211009221711.2315352-1-robimarko@gmail.com
|
||||
---
|
||||
drivers/net/wireless/ath/ath10k/core.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
||||
@@ -1202,6 +1202,7 @@ success:
|
||||
static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
+ char boardname[100];
|
||||
|
||||
if (bd_ie_type == ATH10K_BD_IE_BOARD) {
|
||||
if (!ar->hw_params.fw.board) {
|
||||
@@ -1209,9 +1210,19 @@ static int ath10k_core_fetch_board_data_
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ scnprintf(boardname, sizeof(boardname), "board-%s-%s.bin",
|
||||
+ ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
|
||||
+
|
||||
ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
- ar->hw_params.fw.board);
|
||||
+ boardname);
|
||||
+ if (IS_ERR(ar->normal_mode_fw.board)) {
|
||||
+ fw = ath10k_fetch_fw_file(ar,
|
||||
+ ar->hw_params.fw.dir,
|
||||
+ ar->hw_params.fw.board);
|
||||
+ ar->normal_mode_fw.board = fw;
|
||||
+ }
|
||||
+
|
||||
if (IS_ERR(ar->normal_mode_fw.board))
|
||||
return PTR_ERR(ar->normal_mode_fw.board);
|
||||
|
@ -1,162 +0,0 @@
|
||||
From e2333703373e8b81294da5d1c73c30154f75b082 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Lamparter <chunkeey@gmail.com>
|
||||
Date: Fri, 15 Oct 2021 18:56:33 +0200
|
||||
Subject: [PATCH] ath10k: fetch (pre-)calibration data via nvmem subsystem
|
||||
|
||||
On most embedded ath10k devices (like range extenders,
|
||||
routers, accesspoints, ...) the calibration data is
|
||||
stored in a easily accessible MTD partitions named
|
||||
"ART", "caldata", "calibration", etc...
|
||||
|
||||
Since commit 4b361cfa8624 ("mtd: core: add OTP nvmem provider support"):
|
||||
MTD partitions and portions of them can be specified
|
||||
as potential nvmem-cells which are accessible through
|
||||
the nvmem subsystem.
|
||||
|
||||
This feature - together with an nvmem cell definition either
|
||||
in the platform data or via device-tree allows drivers to get
|
||||
the (pre-)calibration data which is required for initializing
|
||||
the WIFI.
|
||||
|
||||
Tested with Netgear EX6150v2 (IPQ4018)
|
||||
|
||||
Cc: Robert Marko <robimarko@gmail.com>
|
||||
Cc: Thibaut Varene <hacks@slashdirt.org>
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
---
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/pm_qos.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "core.h"
|
||||
@@ -955,7 +956,8 @@ static int ath10k_core_get_board_id_from
|
||||
}
|
||||
|
||||
if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
|
||||
- ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
|
||||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
|
||||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
|
||||
bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID;
|
||||
else
|
||||
bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID;
|
||||
@@ -1757,7 +1759,8 @@ static int ath10k_download_and_run_otp(s
|
||||
|
||||
/* As of now pre-cal is valid for 10_4 variants */
|
||||
if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
|
||||
- ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
|
||||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
|
||||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
|
||||
bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
|
||||
|
||||
ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
|
||||
@@ -1884,6 +1887,39 @@ out_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int ath10k_download_cal_nvmem(struct ath10k *ar, const char *cell_name)
|
||||
+{
|
||||
+ struct nvmem_cell *cell;
|
||||
+ void *buf;
|
||||
+ size_t len;
|
||||
+ int ret;
|
||||
+
|
||||
+ cell = devm_nvmem_cell_get(ar->dev, cell_name);
|
||||
+ if (IS_ERR(cell)) {
|
||||
+ ret = PTR_ERR(cell);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ buf = nvmem_cell_read(cell, &len);
|
||||
+ if (IS_ERR(buf))
|
||||
+ return PTR_ERR(buf);
|
||||
+
|
||||
+ if (ar->hw_params.cal_data_len != len) {
|
||||
+ kfree(buf);
|
||||
+ ath10k_warn(ar, "invalid calibration data length in nvmem-cell '%s': %zu != %u\n",
|
||||
+ cell_name, len, ar->hw_params.cal_data_len);
|
||||
+ return -EMSGSIZE;
|
||||
+ }
|
||||
+
|
||||
+ ret = ath10k_download_board_data(ar, buf, len);
|
||||
+ kfree(buf);
|
||||
+ if (ret)
|
||||
+ ath10k_warn(ar, "failed to download calibration data from nvmem-cell '%s': %d\n",
|
||||
+ cell_name, ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
|
||||
struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
@@ -2118,6 +2154,18 @@ static int ath10k_core_pre_cal_download(
|
||||
{
|
||||
int ret;
|
||||
|
||||
+ ret = ath10k_download_cal_nvmem(ar, "pre-calibration");
|
||||
+ if (ret == 0) {
|
||||
+ ar->cal_mode = ATH10K_PRE_CAL_MODE_NVMEM;
|
||||
+ goto success;
|
||||
+ } else if (ret == -EPROBE_DEFER) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
+ "boot did not find a pre-calibration nvmem-cell, try file next: %d\n",
|
||||
+ ret);
|
||||
+
|
||||
ret = ath10k_download_cal_file(ar, ar->pre_cal_file);
|
||||
if (ret == 0) {
|
||||
ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;
|
||||
@@ -2184,6 +2232,18 @@ static int ath10k_download_cal_data(stru
|
||||
"pre cal download procedure failed, try cal file: %d\n",
|
||||
ret);
|
||||
|
||||
+ ret = ath10k_download_cal_nvmem(ar, "calibration");
|
||||
+ if (ret == 0) {
|
||||
+ ar->cal_mode = ATH10K_CAL_MODE_NVMEM;
|
||||
+ goto done;
|
||||
+ } else if (ret == -EPROBE_DEFER) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
+ "boot did not find a calibration nvmem-cell, try file next: %d\n",
|
||||
+ ret);
|
||||
+
|
||||
ret = ath10k_download_cal_file(ar, ar->cal_file);
|
||||
if (ret == 0) {
|
||||
ar->cal_mode = ATH10K_CAL_MODE_FILE;
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.h
|
||||
@@ -877,8 +877,10 @@ enum ath10k_cal_mode {
|
||||
ATH10K_CAL_MODE_FILE,
|
||||
ATH10K_CAL_MODE_OTP,
|
||||
ATH10K_CAL_MODE_DT,
|
||||
+ ATH10K_CAL_MODE_NVMEM,
|
||||
ATH10K_PRE_CAL_MODE_FILE,
|
||||
ATH10K_PRE_CAL_MODE_DT,
|
||||
+ ATH10K_PRE_CAL_MODE_NVMEM,
|
||||
ATH10K_CAL_MODE_EEPROM,
|
||||
};
|
||||
|
||||
@@ -898,10 +900,14 @@ static inline const char *ath10k_cal_mod
|
||||
return "otp";
|
||||
case ATH10K_CAL_MODE_DT:
|
||||
return "dt";
|
||||
+ case ATH10K_CAL_MODE_NVMEM:
|
||||
+ return "nvmem";
|
||||
case ATH10K_PRE_CAL_MODE_FILE:
|
||||
return "pre-cal-file";
|
||||
case ATH10K_PRE_CAL_MODE_DT:
|
||||
return "pre-cal-dt";
|
||||
+ case ATH10K_PRE_CAL_MODE_NVMEM:
|
||||
+ return "pre-cal-nvmem";
|
||||
case ATH10K_CAL_MODE_EEPROM:
|
||||
return "eeprom";
|
||||
}
|
@ -14,7 +14,7 @@ Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
||||
@@ -3443,6 +3443,16 @@ int ath10k_core_register(struct ath10k *
|
||||
@@ -3500,6 +3500,16 @@ int ath10k_core_register(struct ath10k *
|
||||
|
||||
queue_work(ar->workqueue, &ar->register_work);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||
@@ -9898,6 +9898,21 @@ static int ath10k_mac_init_rd(struct ath
|
||||
@@ -9909,6 +9909,21 @@ static int ath10k_mac_init_rd(struct ath
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
int ath10k_mac_register(struct ath10k *ar)
|
||||
{
|
||||
static const u32 cipher_suites[] = {
|
||||
@@ -10256,6 +10271,12 @@ int ath10k_mac_register(struct ath10k *a
|
||||
@@ -10267,6 +10282,12 @@ int ath10k_mac_register(struct ath10k *a
|
||||
|
||||
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
|
||||
|
||||
|
@ -114,7 +114,7 @@ v13:
|
||||
ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -166,6 +166,7 @@ ATH10K_DEBUG=
|
||||
@@ -170,6 +170,7 @@ ATH10K_DEBUG=
|
||||
ATH10K_DEBUGFS=
|
||||
ATH10K_SPECTRAL=
|
||||
ATH10K_THERMAL=
|
||||
@ -140,7 +140,7 @@ v13:
|
||||
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
|
||||
@@ -138,6 +140,7 @@ static const struct ath10k_hw_params ath
|
||||
@@ -144,6 +146,7 @@ static const struct ath10k_hw_params ath
|
||||
.dev_id = QCA9887_1_0_DEVICE_ID,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.name = "qca9887 hw1.0",
|
||||
@ -148,7 +148,7 @@ v13:
|
||||
.patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
|
||||
@@ -355,6 +358,7 @@ static const struct ath10k_hw_params ath
|
||||
@@ -379,6 +382,7 @@ static const struct ath10k_hw_params ath
|
||||
.dev_id = QCA99X0_2_0_DEVICE_ID,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.name = "qca99x0 hw2.0",
|
||||
@ -156,7 +156,7 @@ v13:
|
||||
.patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.otp_exe_param = 0x00000700,
|
||||
@@ -397,6 +401,7 @@ static const struct ath10k_hw_params ath
|
||||
@@ -424,6 +428,7 @@ static const struct ath10k_hw_params ath
|
||||
.dev_id = QCA9984_1_0_DEVICE_ID,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.name = "qca9984/qca9994 hw1.0",
|
||||
@ -164,7 +164,7 @@ v13:
|
||||
.patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
|
||||
@@ -446,6 +451,7 @@ static const struct ath10k_hw_params ath
|
||||
@@ -476,6 +481,7 @@ static const struct ath10k_hw_params ath
|
||||
.dev_id = QCA9888_2_0_DEVICE_ID,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.name = "qca9888 hw2.0",
|
||||
@ -172,7 +172,7 @@ v13:
|
||||
.patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
|
||||
@@ -3158,6 +3164,10 @@ int ath10k_core_start(struct ath10k *ar,
|
||||
@@ -3215,6 +3221,10 @@ int ath10k_core_start(struct ath10k *ar,
|
||||
goto err_hif_stop;
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ v13:
|
||||
return 0;
|
||||
|
||||
err_hif_stop:
|
||||
@@ -3416,9 +3426,18 @@ static void ath10k_core_register_work(st
|
||||
@@ -3473,9 +3483,18 @@ static void ath10k_core_register_work(st
|
||||
goto err_spectral_destroy;
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ v13:
|
||||
err_spectral_destroy:
|
||||
ath10k_spectral_destroy(ar);
|
||||
err_debug_destroy:
|
||||
@@ -3464,6 +3483,8 @@ void ath10k_core_unregister(struct ath10
|
||||
@@ -3521,6 +3540,8 @@ void ath10k_core_unregister(struct ath10
|
||||
if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
|
||||
return;
|
||||
|
||||
@ -221,7 +221,7 @@ v13:
|
||||
|
||||
#include "htt.h"
|
||||
#include "htc.h"
|
||||
@@ -1256,6 +1257,13 @@ struct ath10k {
|
||||
@@ -1253,6 +1254,13 @@ struct ath10k {
|
||||
} testmode;
|
||||
|
||||
struct {
|
||||
@ -237,7 +237,7 @@ v13:
|
||||
u32 fw_crash_counter;
|
||||
--- a/drivers/net/wireless/ath/ath10k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath10k/hw.h
|
||||
@@ -517,6 +517,7 @@ struct ath10k_hw_params {
|
||||
@@ -519,6 +519,7 @@ struct ath10k_hw_params {
|
||||
const char *name;
|
||||
u32 patch_load_addr;
|
||||
int uart_pin;
|
||||
|
@ -16,7 +16,7 @@ Signed-off-by: Mathias Kresin <dev@kresin.me>
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.h
|
||||
@@ -1312,6 +1312,10 @@ struct ath10k {
|
||||
@@ -1309,6 +1309,10 @@ struct ath10k {
|
||||
s32 tx_power_2g_limit;
|
||||
s32 tx_power_5g_limit;
|
||||
|
||||
@ -42,7 +42,7 @@ Signed-off-by: Mathias Kresin <dev@kresin.me>
|
||||
if (ret)
|
||||
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||
@@ -10273,7 +10273,7 @@ int ath10k_mac_register(struct ath10k *a
|
||||
@@ -10284,7 +10284,7 @@ int ath10k_mac_register(struct ath10k *a
|
||||
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
|
||||
|
||||
#ifdef CPTCFG_MAC80211_LEDS
|
||||
|
@ -89,7 +89,7 @@ Forwarded: no
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
||||
arg.ssid = arvif->u.ap.ssid;
|
||||
@@ -3434,7 +3470,8 @@ static int ath10k_update_channel_list(st
|
||||
@@ -3437,7 +3473,8 @@ static int ath10k_update_channel_list(st
|
||||
ch->min_power = 0;
|
||||
ch->max_power = channel->max_power * 2;
|
||||
ch->max_reg_power = channel->max_reg_power * 2;
|
||||
|
@ -26,9 +26,9 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
#include <linux/property.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/ctype.h>
|
||||
@@ -3334,6 +3335,8 @@ static int ath10k_core_probe_fw(struct a
|
||||
@@ -3391,6 +3392,8 @@ static int ath10k_core_probe_fw(struct a
|
||||
|
||||
device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr));
|
||||
device_get_mac_address(ar->dev, ar->mac_addr);
|
||||
|
||||
+ of_get_mac_address(ar->dev->of_node, ar->mac_addr);
|
||||
+
|
||||
|
@ -17,7 +17,7 @@
|
||||
{ AR5K_RXNOFRM, 8 },
|
||||
--- a/drivers/net/wireless/ath/ath5k/dma.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/dma.c
|
||||
@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
|
||||
@@ -854,10 +854,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
|
||||
* guess we can tweak it and see how it goes ;-)
|
||||
*/
|
||||
if (ah->ah_version != AR5K_AR5210) {
|
||||
|
@ -18,7 +18,7 @@
|
||||
goto end;
|
||||
--- a/drivers/net/wireless/ath/ath5k/base.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/base.c
|
||||
@@ -1963,7 +1963,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
|
||||
@@ -2009,7 +2009,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
|
||||
}
|
||||
|
||||
if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
|
||||
@ -27,7 +27,7 @@
|
||||
ah->opmode == NL80211_IFTYPE_MESH_POINT) {
|
||||
u64 tsf = ath5k_hw_get_tsf64(ah);
|
||||
u32 tsftu = TSF_TO_TU(tsf);
|
||||
@@ -2049,7 +2049,7 @@ ath5k_beacon_update_timers(struct ath5k_
|
||||
@@ -2095,7 +2095,7 @@ ath5k_beacon_update_timers(struct ath5k_
|
||||
|
||||
intval = ah->bintval & AR5K_BEACON_PERIOD;
|
||||
if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
|
||||
@ -36,7 +36,7 @@
|
||||
intval /= ATH_BCBUF; /* staggered multi-bss beacons */
|
||||
if (intval < 15)
|
||||
ATH5K_WARN(ah, "intval %u is too low, min 15\n",
|
||||
@@ -2515,6 +2515,7 @@ static const struct ieee80211_iface_limi
|
||||
@@ -2561,6 +2561,7 @@ static const struct ieee80211_iface_limi
|
||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
#endif
|
||||
BIT(NL80211_IFTYPE_AP) },
|
||||
|
@ -1,28 +0,0 @@
|
||||
From 03469e79fee9e8e908dae3bd1a80bcd9a66f2a88 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Lamparter <chunkeey@gmail.com>
|
||||
Date: Mon, 11 Oct 2021 18:18:00 +0300
|
||||
Subject: ath9k: support DT ieee80211-freq-limit property to limit channels
|
||||
|
||||
The common DT property can be used to limit the available channels
|
||||
but ath9k has to manually call wiphy_read_of_freq_limits().
|
||||
|
||||
I would have put this into ath9k_of_init(). But it didn't work there.
|
||||
The reason is that in ath9k_of_init() the channels and bands are not yet
|
||||
registered in the wiphy struct. So there isn't any channel to flag as
|
||||
disabled.
|
||||
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
Link: https://lore.kernel.org/r/20211009212847.1781986-1-chunkeey@gmail.com
|
||||
---
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -1038,6 +1038,8 @@ int ath9k_init_device(u16 devid, struct
|
||||
ARRAY_SIZE(ath9k_tpt_blink));
|
||||
#endif
|
||||
|
||||
+ wiphy_read_of_freq_limits(hw->wiphy);
|
||||
+
|
||||
/* Register with mac80211 */
|
||||
error = ieee80211_register_hw(hw);
|
||||
if (error)
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -47,7 +47,7 @@ int ath9k_modparam_nohwcrypt;
|
||||
@@ -48,7 +48,7 @@ int ath9k_modparam_nohwcrypt;
|
||||
module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
|
||||
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -826,6 +826,7 @@ static const struct ieee80211_iface_limi
|
||||
@@ -882,6 +882,7 @@ static const struct ieee80211_iface_limi
|
||||
BIT(NL80211_IFTYPE_AP) },
|
||||
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) },
|
||||
|
@ -14,7 +14,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -907,6 +907,7 @@ static void ath9k_set_hw_capab(struct at
|
||||
@@ -963,6 +963,7 @@ static void ath9k_set_hw_capab(struct at
|
||||
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
|
||||
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
|
||||
ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
|
||||
@ -22,7 +22,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
|
||||
if (ath9k_ps_enable)
|
||||
ieee80211_hw_set(hw, SUPPORTS_PS);
|
||||
@@ -919,9 +920,6 @@ static void ath9k_set_hw_capab(struct at
|
||||
@@ -975,9 +976,6 @@ static void ath9k_set_hw_capab(struct at
|
||||
IEEE80211_RADIOTAP_MCS_HAVE_STBC;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1364,6 +1364,53 @@ void ath9k_deinit_debug(struct ath_softc
|
||||
@@ -1413,6 +1413,53 @@ void ath9k_deinit_debug(struct ath_softc
|
||||
ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -1383,6 +1430,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1432,6 +1479,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
ath9k_tx99_init_debug(sc);
|
||||
ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -1122,25 +1122,25 @@ static int __init ath9k_init(void)
|
||||
@@ -1178,25 +1178,25 @@ static int __init ath9k_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1411,6 +1411,52 @@ static const struct file_operations fops
|
||||
@@ -1460,6 +1460,52 @@ static const struct file_operations fops
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -1432,6 +1478,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1481,6 +1527,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
|
||||
debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_eeprom);
|
||||
|
@ -181,7 +181,7 @@
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -1032,7 +1032,7 @@ int ath9k_init_device(u16 devid, struct
|
||||
@@ -1088,7 +1088,7 @@ int ath9k_init_device(u16 devid, struct
|
||||
|
||||
#ifdef CPTCFG_MAC80211_LEDS
|
||||
/* must be initialized before ieee80211_register_hw */
|
||||
@ -192,7 +192,7 @@
|
||||
#endif
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1456,6 +1456,61 @@ static const struct file_operations fops
|
||||
@@ -1505,6 +1505,61 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
@ -254,7 +254,7 @@
|
||||
|
||||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
@@ -1480,6 +1535,10 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1529,6 +1584,10 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
&fops_eeprom);
|
||||
debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
||||
sc, &fops_chanbw);
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1512,6 +1512,50 @@ static const struct file_operations fops
|
||||
@@ -1561,6 +1561,50 @@ static const struct file_operations fops
|
||||
#endif
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -1539,6 +1583,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1588,6 +1632,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
debugfs_create_file("gpio_led", S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_gpio_led);
|
||||
#endif
|
||||
@ -84,7 +84,7 @@
|
||||
bool reset_power_on;
|
||||
bool htc_reset_init;
|
||||
|
||||
@@ -1077,6 +1085,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
|
||||
@@ -1079,6 +1087,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
|
||||
bool ath9k_hw_check_alive(struct ath_hw *ah);
|
||||
|
||||
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
|
||||
|
@ -18,7 +18,7 @@
|
||||
void (*spectral_scan_trigger)(struct ath_hw *ah);
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
|
||||
@@ -1927,6 +1927,26 @@ void ar9003_hw_init_rate_txpower(struct
|
||||
@@ -1918,6 +1918,26 @@ void ar9003_hw_init_rate_txpower(struct
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
@@ -1963,6 +1983,7 @@ void ar9003_hw_attach_phy_ops(struct ath
|
||||
@@ -1954,6 +1974,7 @@ void ar9003_hw_attach_phy_ops(struct ath
|
||||
priv_ops->set_radar_params = ar9003_hw_set_radar_params;
|
||||
priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -814,7 +814,8 @@ static void ath9k_init_txpower_limits(st
|
||||
@@ -870,7 +870,8 @@ static void ath9k_init_txpower_limits(st
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
|
||||
ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ);
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
}
|
||||
|
||||
static const struct ieee80211_iface_limit if_limits[] = {
|
||||
@@ -992,6 +993,18 @@ static void ath9k_set_hw_capab(struct at
|
||||
@@ -1048,6 +1049,18 @@ static void ath9k_set_hw_capab(struct at
|
||||
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@
|
||||
int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
@@ -1039,6 +1052,8 @@ int ath9k_init_device(u16 devid, struct
|
||||
@@ -1095,6 +1108,8 @@ int ath9k_init_device(u16 devid, struct
|
||||
|
||||
wiphy_read_of_freq_limits(hw->wiphy);
|
||||
|
||||
|
@ -79,7 +79,7 @@
|
||||
static const u8 ofdm2pwr[] = {
|
||||
ALL_TARGET_LEGACY_6_24,
|
||||
ALL_TARGET_LEGACY_6_24,
|
||||
@@ -1077,11 +1063,6 @@ static bool ar9003_hw_ani_control(struct
|
||||
@@ -1068,11 +1054,6 @@ static bool ar9003_hw_ani_control(struct
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
struct ar5416AniState *aniState = &ah->ani;
|
||||
@ -91,7 +91,7 @@
|
||||
s32 value, value2;
|
||||
|
||||
switch (cmd & ah->ani_function) {
|
||||
@@ -1095,61 +1076,6 @@ static bool ar9003_hw_ani_control(struct
|
||||
@@ -1086,61 +1067,6 @@ static bool ar9003_hw_ani_control(struct
|
||||
*/
|
||||
u32 on = param ? 1 : 0;
|
||||
|
||||
|
@ -371,7 +371,7 @@
|
||||
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -133,6 +133,7 @@ ATH9K_WOW=
|
||||
@@ -137,6 +137,7 @@ ATH9K_WOW=
|
||||
ATH9K_RFKILL=
|
||||
ATH9K_CHANNEL_CONTEXT=
|
||||
ATH9K_PCOEM=
|
||||
|
@ -271,7 +271,7 @@
|
||||
|
||||
if (!dev_get_platdata(&pdev->dev)) {
|
||||
dev_err(&pdev->dev, "no platform data specified\n");
|
||||
@@ -122,13 +371,16 @@ static int ath_ahb_probe(struct platform
|
||||
@@ -118,13 +367,16 @@ static int ath_ahb_probe(struct platform
|
||||
sc->mem = mem;
|
||||
sc->irq = irq;
|
||||
|
||||
@ -289,7 +289,7 @@
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize device\n");
|
||||
goto err_irq;
|
||||
@@ -159,6 +411,9 @@ static int ath_ahb_remove(struct platfor
|
||||
@@ -155,6 +407,9 @@ static int ath_ahb_remove(struct platfor
|
||||
free_irq(sc->irq, sc);
|
||||
ieee80211_free_hw(sc->hw);
|
||||
}
|
||||
@ -299,7 +299,7 @@
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -168,6 +423,9 @@ static struct platform_driver ath_ahb_dr
|
||||
@@ -164,6 +419,9 @@ static struct platform_driver ath_ahb_dr
|
||||
.remove = ath_ahb_remove,
|
||||
.driver = {
|
||||
.name = "ath9k",
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -644,6 +644,12 @@ static int ath9k_of_init(struct ath_soft
|
||||
@@ -696,6 +696,12 @@ static int ath9k_of_init(struct ath_soft
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
@@ -747,6 +753,9 @@ static int ath9k_init_softc(u16 devid, s
|
||||
@@ -803,6 +809,9 @@ static int ath9k_init_softc(u16 devid, s
|
||||
if (ret)
|
||||
goto err_hw;
|
||||
|
||||
|
@ -1,154 +0,0 @@
|
||||
From dab16ef495dbb3cabb355b6c80f0771a4a25e35d Mon Sep 17 00:00:00 2001
|
||||
From: Christian Lamparter <chunkeey@gmail.com>
|
||||
Date: Fri, 20 Aug 2021 22:44:52 +0200
|
||||
Subject: [PATCH] ath9k: fetch calibration data via nvmem subsystem
|
||||
|
||||
On most embedded ath9k devices (like range extenders,
|
||||
routers, accesspoints, ...) the calibration data is
|
||||
stored in a MTD partitions named "ART", or "caldata"/
|
||||
"calibration".
|
||||
|
||||
Ever since commit
|
||||
4b361cfa8624 ("mtd: core: add OTP nvmem provider support")
|
||||
all MTD partitions are all automatically available through
|
||||
the nvmem subsystem. This allows drivers like ath9k to read
|
||||
the necessary data without needing any userspace helpers
|
||||
that would do this extraction.
|
||||
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
---
|
||||
|
||||
includes:
|
||||
|
||||
From 57671351379b2051cfb07fc14e0bead9916a0880 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Date: Mon, 11 Oct 2021 18:18:01 +0300
|
||||
Subject: ath9k: fix an IS_ERR() vs NULL check
|
||||
|
||||
The devm_kmemdup() function doesn't return error pointers, it returns
|
||||
NULL on error.
|
||||
|
||||
Fixes: eb3a97a69be8 ("ath9k: fetch calibration data via nvmem subsystem")
|
||||
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
Link: https://lore.kernel.org/r/20211011123533.GA15188@kili
|
||||
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
|
||||
@@ -135,13 +135,23 @@ static bool ath9k_hw_nvram_read_firmware
|
||||
offset, data);
|
||||
}
|
||||
|
||||
+static bool ath9k_hw_nvram_read_nvmem(struct ath_hw *ah, off_t offset,
|
||||
+ u16 *data)
|
||||
+{
|
||||
+ return ath9k_hw_nvram_read_array(ah->nvmem_blob,
|
||||
+ ah->nvmem_blob_len / sizeof(u16),
|
||||
+ offset, data);
|
||||
+}
|
||||
+
|
||||
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_platform_data *pdata = ah->dev->platform_data;
|
||||
bool ret;
|
||||
|
||||
- if (ah->eeprom_blob)
|
||||
+ if (ah->nvmem_blob)
|
||||
+ ret = ath9k_hw_nvram_read_nvmem(ah, off, data);
|
||||
+ else if (ah->eeprom_blob)
|
||||
ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
|
||||
else if (pdata && !pdata->use_eeprom)
|
||||
ret = ath9k_hw_nvram_read_pdata(pdata, off, data);
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -988,6 +988,8 @@ struct ath_hw {
|
||||
bool disable_5ghz;
|
||||
|
||||
const struct firmware *eeprom_blob;
|
||||
+ u16 *nvmem_blob; /* devres managed */
|
||||
+ size_t nvmem_blob_len;
|
||||
|
||||
struct ath_dynack dynack;
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
#include <linux/relay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
@@ -568,6 +569,57 @@ static void ath9k_eeprom_release(struct
|
||||
release_firmware(sc->sc_ah->eeprom_blob);
|
||||
}
|
||||
|
||||
+static int ath9k_nvmem_request_eeprom(struct ath_softc *sc)
|
||||
+{
|
||||
+ struct ath_hw *ah = sc->sc_ah;
|
||||
+ struct nvmem_cell *cell;
|
||||
+ void *buf;
|
||||
+ size_t len;
|
||||
+ int err;
|
||||
+
|
||||
+ cell = devm_nvmem_cell_get(sc->dev, "calibration");
|
||||
+ if (IS_ERR(cell)) {
|
||||
+ err = PTR_ERR(cell);
|
||||
+
|
||||
+ /* nvmem cell might not be defined, or the nvmem
|
||||
+ * subsystem isn't included. In this case, follow
|
||||
+ * the established "just return 0;" convention of
|
||||
+ * ath9k_init_platform to say:
|
||||
+ * "All good. Nothing to see here. Please go on."
|
||||
+ */
|
||||
+ if (err == -ENOENT || err == -EOPNOTSUPP)
|
||||
+ return 0;
|
||||
+
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ buf = nvmem_cell_read(cell, &len);
|
||||
+ if (IS_ERR(buf))
|
||||
+ return PTR_ERR(buf);
|
||||
+
|
||||
+ /* run basic sanity checks on the returned nvram cell length.
|
||||
+ * That length has to be a multiple of a "u16" (i.e.: & 1).
|
||||
+ * Furthermore, it has to be more than "let's say" 512 bytes
|
||||
+ * but less than the maximum of AR9300_EEPROM_SIZE (16kb).
|
||||
+ */
|
||||
+ if (((len & 1) == 1) || (len < 512) || (len >= AR9300_EEPROM_SIZE)) {
|
||||
+ kfree(buf);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* devres manages the calibration values release on shutdown */
|
||||
+ ah->nvmem_blob = (u16 *)devm_kmemdup(sc->dev, buf, len, GFP_KERNEL);
|
||||
+ kfree(buf);
|
||||
+ if (!ah->nvmem_blob)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ah->nvmem_blob_len = len;
|
||||
+ ah->ah_flags &= ~AH_USE_EEPROM;
|
||||
+ ah->ah_flags |= AH_NO_EEP_SWAP;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ath9k_init_platform(struct ath_softc *sc)
|
||||
{
|
||||
struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||
@@ -710,6 +762,10 @@ static int ath9k_init_softc(u16 devid, s
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ ret = ath9k_nvmem_request_eeprom(sc);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
if (ath9k_led_active_high != -1)
|
||||
ah->config.led_active_high = ath9k_led_active_high == 1;
|
||||
|
@ -1,181 +0,0 @@
|
||||
From 9bf31835f11aa3c4fe5a9c1f7462c199c5d8e7ca Mon Sep 17 00:00:00 2001
|
||||
From: Christian Lamparter <chunkeey@gmail.com>
|
||||
Date: Sat, 21 Aug 2021 00:22:39 +0200
|
||||
Subject: [PATCH] ath9k: owl-loader: fetch pci init values through nvmem
|
||||
|
||||
extends the owl loader to fetch important pci initialization
|
||||
values - which are stored together with the calibration data -
|
||||
through the nvmem subsystem.
|
||||
|
||||
This allows for much faster WIFI/ath9k initializations on devices
|
||||
that do not require to perform any post-processing (like XOR'ing/
|
||||
reversal or unpacking) since no userspace helper is required.
|
||||
|
||||
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||
---
|
||||
.../wireless/ath/ath9k/ath9k_pci_owl_loader.c | 105 +++++++++++++-----
|
||||
1 file changed, 76 insertions(+), 29 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
|
||||
@@ -19,9 +19,14 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/ath9k_platform.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/workqueue.h>
|
||||
|
||||
struct owl_ctx {
|
||||
+ struct pci_dev *pdev;
|
||||
struct completion eeprom_load;
|
||||
+ struct work_struct work;
|
||||
+ struct nvmem_cell *cell;
|
||||
};
|
||||
|
||||
#define EEPROM_FILENAME_LEN 100
|
||||
@@ -42,6 +47,12 @@ static int ath9k_pci_fixup(struct pci_de
|
||||
u32 bar0;
|
||||
bool swap_needed = false;
|
||||
|
||||
+ /* also note that we are doing *u16 operations on the file */
|
||||
+ if (cal_len > 4096 || cal_len < 0x200 || (cal_len & 1) == 1) {
|
||||
+ dev_err(&pdev->dev, "eeprom has an invalid size.\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
if (*cal_data != AR5416_EEPROM_MAGIC) {
|
||||
if (*cal_data != swab16(AR5416_EEPROM_MAGIC)) {
|
||||
dev_err(&pdev->dev, "invalid calibration data\n");
|
||||
@@ -99,38 +110,31 @@ static int ath9k_pci_fixup(struct pci_de
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void owl_fw_cb(const struct firmware *fw, void *context)
|
||||
+static void owl_rescan(struct pci_dev *pdev)
|
||||
{
|
||||
- struct pci_dev *pdev = (struct pci_dev *)context;
|
||||
- struct owl_ctx *ctx = (struct owl_ctx *)pci_get_drvdata(pdev);
|
||||
- struct pci_bus *bus;
|
||||
-
|
||||
- complete(&ctx->eeprom_load);
|
||||
-
|
||||
- if (!fw) {
|
||||
- dev_err(&pdev->dev, "no eeprom data received.\n");
|
||||
- goto release;
|
||||
- }
|
||||
-
|
||||
- /* also note that we are doing *u16 operations on the file */
|
||||
- if (fw->size > 4096 || fw->size < 0x200 || (fw->size & 1) == 1) {
|
||||
- dev_err(&pdev->dev, "eeprom file has an invalid size.\n");
|
||||
- goto release;
|
||||
- }
|
||||
-
|
||||
- if (ath9k_pci_fixup(pdev, (const u16 *)fw->data, fw->size))
|
||||
- goto release;
|
||||
+ struct pci_bus *bus = pdev->bus;
|
||||
|
||||
pci_lock_rescan_remove();
|
||||
- bus = pdev->bus;
|
||||
pci_stop_and_remove_bus_device(pdev);
|
||||
/* the device should come back with the proper
|
||||
* ProductId. But we have to initiate a rescan.
|
||||
*/
|
||||
pci_rescan_bus(bus);
|
||||
pci_unlock_rescan_remove();
|
||||
+}
|
||||
+
|
||||
+static void owl_fw_cb(const struct firmware *fw, void *context)
|
||||
+{
|
||||
+ struct owl_ctx *ctx = (struct owl_ctx *)context;
|
||||
+
|
||||
+ complete(&ctx->eeprom_load);
|
||||
|
||||
-release:
|
||||
+ if (fw) {
|
||||
+ ath9k_pci_fixup(ctx->pdev, (const u16 *)fw->data, fw->size);
|
||||
+ owl_rescan(ctx->pdev);
|
||||
+ } else {
|
||||
+ dev_err(&ctx->pdev->dev, "no eeprom data received.\n");
|
||||
+ }
|
||||
release_firmware(fw);
|
||||
}
|
||||
|
||||
@@ -152,6 +156,43 @@ static const char *owl_get_eeprom_name(s
|
||||
return eeprom_name;
|
||||
}
|
||||
|
||||
+static void owl_nvmem_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct owl_ctx *ctx = container_of(work, struct owl_ctx, work);
|
||||
+ void *buf;
|
||||
+ size_t len;
|
||||
+
|
||||
+ complete(&ctx->eeprom_load);
|
||||
+
|
||||
+ buf = nvmem_cell_read(ctx->cell, &len);
|
||||
+ if (!IS_ERR(buf)) {
|
||||
+ ath9k_pci_fixup(ctx->pdev, buf, len);
|
||||
+ kfree(buf);
|
||||
+ owl_rescan(ctx->pdev);
|
||||
+ } else {
|
||||
+ dev_err(&ctx->pdev->dev, "no nvmem data received.\n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int owl_nvmem_probe(struct owl_ctx *ctx)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ ctx->cell = devm_nvmem_cell_get(&ctx->pdev->dev, "calibration");
|
||||
+ if (IS_ERR(ctx->cell)) {
|
||||
+ err = PTR_ERR(ctx->cell);
|
||||
+ if (err == -ENOENT || err == -EOPNOTSUPP)
|
||||
+ return 1; /* not present, try firmware_request */
|
||||
+
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ INIT_WORK(&ctx->work, owl_nvmem_work);
|
||||
+ schedule_work(&ctx->work);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int owl_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
@@ -164,21 +205,27 @@ static int owl_probe(struct pci_dev *pde
|
||||
|
||||
pcim_pin_device(pdev);
|
||||
|
||||
- eeprom_name = owl_get_eeprom_name(pdev);
|
||||
- if (!eeprom_name) {
|
||||
- dev_err(&pdev->dev, "no eeprom filename found.\n");
|
||||
- return -ENODEV;
|
||||
- }
|
||||
-
|
||||
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
init_completion(&ctx->eeprom_load);
|
||||
+ ctx->pdev = pdev;
|
||||
|
||||
pci_set_drvdata(pdev, ctx);
|
||||
+
|
||||
+ err = owl_nvmem_probe(ctx);
|
||||
+ if (err <= 0)
|
||||
+ return err;
|
||||
+
|
||||
+ eeprom_name = owl_get_eeprom_name(pdev);
|
||||
+ if (!eeprom_name) {
|
||||
+ dev_err(&pdev->dev, "no eeprom filename found.\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
err = request_firmware_nowait(THIS_MODULE, true, eeprom_name,
|
||||
- &pdev->dev, GFP_KERNEL, pdev, owl_fw_cb);
|
||||
+ &pdev->dev, GFP_KERNEL, ctx, owl_fw_cb);
|
||||
if (err)
|
||||
dev_err(&pdev->dev, "failed to request caldata (%d).\n", err);
|
||||
|
@ -1,103 +0,0 @@
|
||||
From 716c220b4d990a4fe7800d0685ca69dee99e4e8f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pavel=20L=C3=B6bl?= <pavel@loebl.cz>
|
||||
Date: Fri, 6 May 2022 06:42:46 +0200
|
||||
Subject: [PATCH] brcmfmac: allow setting wlan MAC address using device tree
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This allows firmware to provide MAC address using device tree. Like in
|
||||
case there is no MAC burned in wlan NVRAM.
|
||||
|
||||
Signed-off-by: Pavel Löbl <pavel@loebl.cz>
|
||||
Signed-off-by: Kalle Valo <kvalo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20220506044246.67146-1-pavel@loebl.cz
|
||||
---
|
||||
.../broadcom/brcm80211/brcmfmac/common.c | 23 ++++++++++++++-----
|
||||
.../broadcom/brcm80211/brcmfmac/common.h | 1 +
|
||||
.../broadcom/brcm80211/brcmfmac/core.c | 4 +++-
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/of.c | 3 +++
|
||||
4 files changed, 24 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
||||
@@ -202,13 +202,24 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
|
||||
char *ptr;
|
||||
s32 err;
|
||||
|
||||
- /* retreive mac address */
|
||||
- err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
- sizeof(ifp->mac_addr));
|
||||
- if (err < 0) {
|
||||
- bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err);
|
||||
- goto done;
|
||||
+ if (is_valid_ether_addr(ifp->mac_addr)) {
|
||||
+ /* set mac address */
|
||||
+ err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
+ ETH_ALEN);
|
||||
+ if (err < 0) {
|
||||
+ bphy_err(ifp->drvr, "Setting cur_etheraddr failed, %d\n", err);
|
||||
+ goto done;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* retrieve mac address */
|
||||
+ err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
+ sizeof(ifp->mac_addr));
|
||||
+ if (err < 0) {
|
||||
+ bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err);
|
||||
+ goto done;
|
||||
+ }
|
||||
}
|
||||
+
|
||||
memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
|
||||
memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN);
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
|
||||
@@ -50,6 +50,7 @@ struct brcmf_mp_device {
|
||||
bool ignore_probe_fail;
|
||||
struct brcmfmac_pd_cc *country_codes;
|
||||
const char *board_type;
|
||||
+ unsigned char mac[ETH_ALEN];
|
||||
union {
|
||||
struct brcmfmac_sdio_pd sdio;
|
||||
} bus;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/inetdevice.h>
|
||||
+#include <linux/property.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include <net/addrconf.h>
|
||||
@@ -1227,7 +1228,8 @@ static int brcmf_bus_started(struct brcm
|
||||
brcmf_dbg(TRACE, "\n");
|
||||
|
||||
/* add primary networking interface */
|
||||
- ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL);
|
||||
+ ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d",
|
||||
+ is_valid_ether_addr(drvr->settings->mac) ? drvr->settings->mac : NULL);
|
||||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
+#include <linux/of_net.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include "debug.h"
|
||||
@@ -97,6 +98,8 @@ void brcmf_of_probe(struct device *dev,
|
||||
if (err)
|
||||
brcmf_err("failed to get OF country code map (err=%d)\n", err);
|
||||
|
||||
+ of_get_mac_address(np, settings->mac);
|
||||
+
|
||||
if (bus_type != BRCMF_BUSTYPE_SDIO)
|
||||
return;
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
if (phy->type == B43_PHYTYPE_B) {
|
||||
value16 = b43_read16(dev, 0x005E);
|
||||
@@ -3985,7 +3985,6 @@ static int b43_op_config(struct ieee8021
|
||||
@@ -3986,7 +3986,6 @@ static int b43_op_config(struct ieee8021
|
||||
struct b43_wldev *dev = wl->current_dev;
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
@ -28,7 +28,7 @@
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
@@ -4028,11 +4027,9 @@ static int b43_op_config(struct ieee8021
|
||||
@@ -4029,11 +4028,9 @@ static int b43_op_config(struct ieee8021
|
||||
}
|
||||
|
||||
/* Antennas for RX and management frame TX. */
|
||||
@ -42,7 +42,7 @@
|
||||
|
||||
if (wl->radio_enabled != phy->radio_on) {
|
||||
if (wl->radio_enabled) {
|
||||
@@ -5175,6 +5172,47 @@ static int b43_op_get_survey(struct ieee
|
||||
@@ -5176,6 +5173,47 @@ static int b43_op_get_survey(struct ieee
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -89,8 +89,8 @@
|
||||
+
|
||||
static const struct ieee80211_ops b43_hw_ops = {
|
||||
.tx = b43_op_tx,
|
||||
.conf_tx = b43_op_conf_tx,
|
||||
@@ -5196,6 +5234,8 @@ static const struct ieee80211_ops b43_hw
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
@@ -5198,6 +5236,8 @@ static const struct ieee80211_ops b43_hw
|
||||
.sw_scan_complete = b43_op_sw_scan_complete_notifier,
|
||||
.get_survey = b43_op_get_survey,
|
||||
.rfkill_poll = b43_rfkill_poll,
|
||||
@ -99,7 +99,7 @@
|
||||
};
|
||||
|
||||
/* Hard-reset the chip. Do not call this directly.
|
||||
@@ -5497,6 +5537,8 @@ static int b43_one_core_attach(struct b4
|
||||
@@ -5499,6 +5539,8 @@ static int b43_one_core_attach(struct b4
|
||||
if (!wldev)
|
||||
goto out;
|
||||
|
||||
@ -108,7 +108,7 @@
|
||||
wldev->use_pio = b43_modparam_pio;
|
||||
wldev->dev = dev;
|
||||
wldev->wl = wl;
|
||||
@@ -5588,6 +5630,9 @@ static struct b43_wl *b43_wireless_init(
|
||||
@@ -5590,6 +5632,9 @@ static struct b43_wl *b43_wireless_init(
|
||||
|
||||
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/broadcom/b43/main.c
|
||||
+++ b/drivers/net/wireless/broadcom/b43/main.c
|
||||
@@ -114,7 +114,7 @@ static int b43_modparam_pio = 0;
|
||||
@@ -114,7 +114,7 @@ static int b43_modparam_pio;
|
||||
module_param_named(pio, b43_modparam_pio, int, 0644);
|
||||
MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
|
||||
|
||||
|
@ -13,15 +13,15 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||||
@@ -431,6 +431,7 @@ struct brcmf_fw {
|
||||
struct brcmf_fw_request *req;
|
||||
@@ -459,6 +459,7 @@ struct brcmf_fw {
|
||||
u32 curpos;
|
||||
unsigned int board_index;
|
||||
void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
|
||||
+ struct completion *completion;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
@@ -655,6 +656,8 @@ static void brcmf_fw_request_done(const
|
||||
@@ -686,6 +687,8 @@ static void brcmf_fw_request_done(const
|
||||
fwctx->req = NULL;
|
||||
}
|
||||
fwctx->done(fwctx->dev, ret, fwctx->req);
|
||||
@ -30,7 +30,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
kfree(fwctx);
|
||||
}
|
||||
|
||||
@@ -695,6 +698,8 @@ int brcmf_fw_get_firmwares(struct device
|
||||
@@ -751,6 +754,8 @@ int brcmf_fw_get_firmwares(struct device
|
||||
{
|
||||
struct brcmf_fw_item *first = &req->items[0];
|
||||
struct brcmf_fw *fwctx;
|
||||
@ -39,7 +39,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
char *alt_path = NULL;
|
||||
int ret;
|
||||
|
||||
@@ -712,6 +717,9 @@ int brcmf_fw_get_firmwares(struct device
|
||||
@@ -768,6 +773,9 @@ int brcmf_fw_get_firmwares(struct device
|
||||
fwctx->dev = dev;
|
||||
fwctx->req = req;
|
||||
fwctx->done = fw_cb;
|
||||
@ -48,8 +48,8 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
+ fwctx->completion = &completion;
|
||||
|
||||
/* First try alternative board-specific path if any */
|
||||
if (fwctx->req->board_type)
|
||||
@@ -730,6 +738,12 @@ int brcmf_fw_get_firmwares(struct device
|
||||
if (fwctx->req->board_types[0])
|
||||
@@ -787,6 +795,12 @@ int brcmf_fw_get_firmwares(struct device
|
||||
if (ret < 0)
|
||||
brcmf_fw_request_done(NULL, fwctx);
|
||||
|
||||
|
@ -10,7 +10,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -715,8 +715,36 @@ static struct wireless_dev *brcmf_cfg802
|
||||
@@ -710,8 +710,36 @@ static struct wireless_dev *brcmf_cfg802
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
struct wireless_dev *wdev;
|
||||
|
@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -2974,6 +2974,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
|
||||
@@ -2973,6 +2973,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
|
||||
* preference in cfg struct to apply this to
|
||||
* FW later while initializing the dongle
|
||||
*/
|
||||
|
@ -12,7 +12,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
||||
@@ -59,6 +59,36 @@ static int brcmf_of_get_country_codes(st
|
||||
@@ -65,6 +65,36 @@ static int brcmf_of_get_country_codes(st
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
||||
struct brcmf_mp_device *settings)
|
||||
{
|
||||
@@ -91,6 +121,8 @@ void brcmf_of_probe(struct device *dev,
|
||||
@@ -105,6 +135,8 @@ void brcmf_of_probe(struct device *dev,
|
||||
of_node_put(root);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
#include "of.h"
|
||||
|
||||
static int brcmf_of_get_country_codes(struct device *dev,
|
||||
@@ -153,3 +154,38 @@ void brcmf_of_probe(struct device *dev,
|
||||
@@ -167,3 +168,38 @@ void brcmf_of_probe(struct device *dev,
|
||||
sdio->oob_irq_nr = irq;
|
||||
sdio->oob_irq_flags = irqf;
|
||||
}
|
||||
@ -92,7 +92,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
|
||||
#define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500)
|
||||
#define CTL_DONE_TIMEOUT msecs_to_jiffies(2500)
|
||||
@@ -633,7 +634,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "b
|
||||
@@ -634,7 +635,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "b
|
||||
/* per-board firmware binaries */
|
||||
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin");
|
||||
|
||||
@ -101,7 +101,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
|
||||
@@ -659,6 +660,9 @@ static const struct brcmf_firmware_mappi
|
||||
@@ -662,6 +663,9 @@ static const struct brcmf_firmware_mappi
|
||||
BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752)
|
||||
};
|
||||
|
||||
@ -111,18 +111,9 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
#define TXCTL_CREDITS 2
|
||||
|
||||
static void pkt_align(struct sk_buff *p, int len, int align)
|
||||
@@ -4140,7 +4144,7 @@ int brcmf_sdio_get_fwname(struct device
|
||||
|
||||
fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
|
||||
brcmf_sdio_fwnames,
|
||||
- ARRAY_SIZE(brcmf_sdio_fwnames),
|
||||
+ brcmf_sdio_fwnames_count,
|
||||
fwnames, ARRAY_SIZE(fwnames));
|
||||
if (!fwreq)
|
||||
return -ENOMEM;
|
||||
@@ -4196,6 +4200,9 @@ static const struct brcmf_bus_ops brcmf_
|
||||
#define BRCMF_SDIO_FW_CODE 0
|
||||
@@ -4192,6 +4196,9 @@ static const struct brcmf_bus_ops brcmf_
|
||||
#define BRCMF_SDIO_FW_NVRAM 1
|
||||
#define BRCMF_SDIO_FW_CLM 2
|
||||
|
||||
+static struct brcmf_fw_request *
|
||||
+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus);
|
||||
@ -130,7 +121,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
static void brcmf_sdio_firmware_callback(struct device *dev, int err,
|
||||
struct brcmf_fw_request *fwreq)
|
||||
{
|
||||
@@ -4211,6 +4218,22 @@ static void brcmf_sdio_firmware_callback
|
||||
@@ -4207,6 +4214,22 @@ static void brcmf_sdio_firmware_callback
|
||||
|
||||
brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
|
||||
|
||||
@ -153,7 +144,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
@@ -4419,7 +4442,7 @@ brcmf_sdio_prepare_fw_request(struct brc
|
||||
@@ -4417,7 +4440,7 @@ brcmf_sdio_prepare_fw_request(struct brc
|
||||
|
||||
fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
|
||||
brcmf_sdio_fwnames,
|
||||
|
@ -1,148 +0,0 @@
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -2921,6 +2921,63 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
+brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
|
||||
+ int idx, struct survey_info *survey)
|
||||
+{
|
||||
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
+ struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
+ struct brcmu_chan ch;
|
||||
+ enum nl80211_band band = 0;
|
||||
+ s32 err = 0;
|
||||
+ int noise;
|
||||
+ u32 freq;
|
||||
+ u32 chanspec;
|
||||
+
|
||||
+ memset(survey, 0, sizeof(struct survey_info));
|
||||
+ if (idx != 0) {
|
||||
+ if (idx >= cfg->pub->num_chan_stats || cfg->pub->chan_stats == NULL)
|
||||
+ return -ENOENT;
|
||||
+ if (cfg->pub->chan_stats[idx].freq == 0)
|
||||
+ return -ENOENT;
|
||||
+ survey->filled = SURVEY_INFO_NOISE_DBM;
|
||||
+ survey->channel = ieee80211_get_channel(wiphy, cfg->pub->chan_stats[idx].freq);
|
||||
+ survey->noise = cfg->pub->chan_stats[idx].noise;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ err = brcmf_fil_iovar_int_get(ifp, "chanspec", &chanspec);
|
||||
+ if (err) {
|
||||
+ brcmf_err("chanspec failed (%d)\n", err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ ch.chspec = chanspec;
|
||||
+ cfg->d11inf.decchspec(&ch);
|
||||
+
|
||||
+ switch (ch.band) {
|
||||
+ case BRCMU_CHAN_BAND_2G:
|
||||
+ band = NL80211_BAND_2GHZ;
|
||||
+ break;
|
||||
+ case BRCMU_CHAN_BAND_5G:
|
||||
+ band = NL80211_BAND_5GHZ;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ freq = ieee80211_channel_to_frequency(ch.control_ch_num, band);
|
||||
+ survey->channel = ieee80211_get_channel(wiphy, freq);
|
||||
+
|
||||
+ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PHY_NOISE, &noise);
|
||||
+ if (err) {
|
||||
+ brcmf_err("Could not get noise (%d)\n", err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ survey->filled = SURVEY_INFO_NOISE_DBM | SURVEY_INFO_IN_USE;
|
||||
+ survey->noise = le32_to_cpu(noise);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
int idx, u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
@@ -3021,6 +3078,7 @@ static s32 brcmf_inform_single_bss(struc
|
||||
struct brcmu_chan ch;
|
||||
u16 channel;
|
||||
u32 freq;
|
||||
+ int i;
|
||||
u16 notify_capability;
|
||||
u16 notify_interval;
|
||||
u8 *notify_ie;
|
||||
@@ -3045,6 +3103,17 @@ static s32 brcmf_inform_single_bss(struc
|
||||
band = NL80211_BAND_5GHZ;
|
||||
|
||||
freq = ieee80211_channel_to_frequency(channel, band);
|
||||
+ for (i = 0;i < cfg->pub->num_chan_stats;i++) {
|
||||
+ if (freq == cfg->pub->chan_stats[i].freq)
|
||||
+ break;
|
||||
+ if (cfg->pub->chan_stats[i].freq == 0)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (i < cfg->pub->num_chan_stats) {
|
||||
+ cfg->pub->chan_stats[i].freq = freq;
|
||||
+ cfg->pub->chan_stats[i].noise = bi->phy_noise;
|
||||
+ }
|
||||
+
|
||||
bss_data.chan = ieee80211_get_channel(wiphy, freq);
|
||||
bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20;
|
||||
bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime());
|
||||
@@ -5573,6 +5642,7 @@ static struct cfg80211_ops brcmf_cfg8021
|
||||
.leave_ibss = brcmf_cfg80211_leave_ibss,
|
||||
.get_station = brcmf_cfg80211_get_station,
|
||||
.dump_station = brcmf_cfg80211_dump_station,
|
||||
+ .dump_survey = brcmf_cfg80211_dump_survey,
|
||||
.set_tx_power = brcmf_cfg80211_set_tx_power,
|
||||
.get_tx_power = brcmf_cfg80211_get_tx_power,
|
||||
.add_key = brcmf_cfg80211_add_key,
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -1364,6 +1364,8 @@ int brcmf_attach(struct device *dev)
|
||||
|
||||
/* Link to bus module */
|
||||
drvr->hdrlen = 0;
|
||||
+ drvr->chan_stats = vzalloc(256 * sizeof(struct brcmf_chan_stats));
|
||||
+ drvr->num_chan_stats = 256;
|
||||
|
||||
/* Attach and link in the protocol */
|
||||
ret = brcmf_proto_attach(drvr);
|
||||
@@ -1446,6 +1448,12 @@ void brcmf_detach(struct device *dev)
|
||||
if (drvr == NULL)
|
||||
return;
|
||||
|
||||
+ drvr->num_chan_stats = 0;
|
||||
+ if (drvr->chan_stats) {
|
||||
+ vfree(drvr->chan_stats);
|
||||
+ drvr->chan_stats = NULL;
|
||||
+ }
|
||||
+
|
||||
#ifdef CONFIG_INET
|
||||
unregister_inetaddr_notifier(&drvr->inetaddr_notifier);
|
||||
#endif
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
||||
@@ -91,6 +91,11 @@ struct brcmf_rev_info {
|
||||
u32 nvramrev;
|
||||
};
|
||||
|
||||
+struct brcmf_chan_stats {
|
||||
+ u32 freq;
|
||||
+ int noise;
|
||||
+};
|
||||
+
|
||||
/* Common structure for module and instance linkage */
|
||||
struct brcmf_pub {
|
||||
/* Linkage ponters */
|
||||
@@ -100,6 +105,9 @@ struct brcmf_pub {
|
||||
struct cfg80211_ops *ops;
|
||||
struct brcmf_cfg80211_info *config;
|
||||
|
||||
+ int num_chan_stats;
|
||||
+ struct brcmf_chan_stats *chan_stats;
|
||||
+
|
||||
/* Internal brcmf items */
|
||||
uint hdrlen; /* Total BRCMF header length (proto + bus) */
|
||||
|
@ -1,34 +0,0 @@
|
||||
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
|
||||
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
|
||||
@@ -11470,6 +11470,15 @@ static const struct attribute_group ipw_
|
||||
.attrs = ipw_sysfs_entries,
|
||||
};
|
||||
|
||||
+#if LINUX_VERSION_IS_LESS(4,10,0)
|
||||
+static int __change_mtu(struct net_device *ndev, int new_mtu){
|
||||
+ if (new_mtu < 68 || new_mtu > LIBIPW_DATA_LEN)
|
||||
+ return -EINVAL;
|
||||
+ ndev->mtu = new_mtu;
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
#ifdef CPTCFG_IPW2200_PROMISCUOUS
|
||||
static int ipw_prom_open(struct net_device *dev)
|
||||
{
|
||||
@@ -11518,15 +11527,6 @@ static netdev_tx_t ipw_prom_hard_start_x
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
-#if LINUX_VERSION_IS_LESS(4,10,0)
|
||||
-static int __change_mtu(struct net_device *ndev, int new_mtu){
|
||||
- if (new_mtu < 68 || new_mtu > LIBIPW_DATA_LEN)
|
||||
- return -EINVAL;
|
||||
- ndev->mtu = new_mtu;
|
||||
- return 0;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
static const struct net_device_ops ipw_prom_netdev_ops = {
|
||||
#if LINUX_VERSION_IS_LESS(4,10,0)
|
||||
.ndo_change_mtu = __change_mtu,
|
@ -1,6 +1,6 @@
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -451,43 +451,6 @@ USB_VL600=
|
||||
@@ -470,43 +470,6 @@ USB_VL600=
|
||||
USB_NET_CH9200=
|
||||
USB_NET_AQC111=
|
||||
USB_RTL8153_ECM=
|
||||
@ -99,7 +99,7 @@
|
||||
return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
|
||||
#else
|
||||
return bus->chipco.dev;
|
||||
@@ -4870,7 +4870,7 @@ static int b43_wireless_core_init(struct
|
||||
@@ -4871,7 +4871,7 @@ static int b43_wireless_core_init(struct
|
||||
}
|
||||
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
|
||||
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
|
||||
@ -158,27 +158,6 @@
|
||||
pcidev = bus->pcicore.dev;
|
||||
#endif
|
||||
gpiodev = bus->chipco.dev ? : pcidev;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
|
||||
@@ -24,7 +24,7 @@ struct brcms_led {
|
||||
struct gpio_desc *gpiod;
|
||||
};
|
||||
|
||||
-#ifdef CPTCFG_BCMA_DRIVER_GPIO
|
||||
+#ifdef CONFIG_BCMA_DRIVER_GPIO
|
||||
void brcms_led_unregister(struct brcms_info *wl);
|
||||
int brcms_led_register(struct brcms_info *wl);
|
||||
#else
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
|
||||
@@ -42,6 +42,6 @@ brcmsmac-y := \
|
||||
brcms_trace_events.o \
|
||||
debug.o
|
||||
|
||||
-brcmsmac-$(CPTCFG_BCMA_DRIVER_GPIO) += led.o
|
||||
+brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
|
||||
|
||||
obj-$(CPTCFG_BRCMSMAC) += brcmsmac.o
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
|
||||
@@ -8,7 +8,7 @@ config BRCMSMAC
|
||||
@ -187,12 +166,12 @@
|
||||
depends on BCMA_POSSIBLE
|
||||
- select BCMA
|
||||
+ depends on BCMA
|
||||
select NEW_LEDS if BCMA_DRIVER_GPIO
|
||||
select LEDS_CLASS if BCMA_DRIVER_GPIO
|
||||
select BRCMUTIL
|
||||
depends on FW_LOADER
|
||||
depends on CORDIC
|
||||
--- a/Kconfig.local
|
||||
+++ b/Kconfig.local
|
||||
@@ -1357,117 +1357,6 @@ config BACKPORTED_USB_NET_AQC111
|
||||
@@ -1414,117 +1414,6 @@ config BACKPORTED_USB_NET_AQC111
|
||||
config BACKPORTED_USB_RTL8153_ECM
|
||||
tristate
|
||||
default USB_RTL8153_ECM
|
||||
|
@ -5,6 +5,6 @@
|
||||
depends on WLAN && MMC && CFG80211
|
||||
depends on m
|
||||
- select CFG80211_WEXT
|
||||
depends on CRYPTO
|
||||
select BPAUTO_CRYPTO_LIB_ARC4
|
||||
help
|
||||
This option enables support for RTL8723BS SDIO drivers, such as
|
||||
|
@ -0,0 +1,24 @@
|
||||
--- a/drivers/net/wireless/mac80211_hwsim.c
|
||||
+++ b/drivers/net/wireless/mac80211_hwsim.c
|
||||
@@ -5363,7 +5363,9 @@ static struct genl_family hwsim_genl_fam
|
||||
.module = THIS_MODULE,
|
||||
.small_ops = hwsim_ops,
|
||||
.n_small_ops = ARRAY_SIZE(hwsim_ops),
|
||||
+#if LINUX_VERSION_IS_GEQ(6,1,0)
|
||||
.resv_start_op = HWSIM_CMD_DEL_MAC_ADDR + 1,
|
||||
+#endif
|
||||
.mcgrps = hwsim_mcgrps,
|
||||
.n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
|
||||
};
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -17232,7 +17232,9 @@ static struct genl_family nl80211_fam __
|
||||
.n_ops = ARRAY_SIZE(nl80211_ops),
|
||||
.small_ops = nl80211_small_ops,
|
||||
.n_small_ops = ARRAY_SIZE(nl80211_small_ops),
|
||||
+#if LINUX_VERSION_IS_GEQ(6,1,0)
|
||||
.resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1,
|
||||
+#endif
|
||||
.mcgrps = nl80211_mcgrps,
|
||||
.n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
|
||||
.parallel_ops = true,
|
13
package/kernel/mac80211/patches/build/090-bcma-otp.patch
Normal file
13
package/kernel/mac80211/patches/build/090-bcma-otp.patch
Normal file
@ -0,0 +1,13 @@
|
||||
--- /dev/null
|
||||
+++ b/backport-include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -0,0 +1,10 @@
|
||||
+#ifndef __BACKPORT_BCMA_DRIVER_CHIPCOMMON_H
|
||||
+#define __BACKPORT_BCMA_DRIVER_CHIPCOMMON_H
|
||||
+
|
||||
+#include_next <linux/bcma/bcma_driver_chipcommon.h>
|
||||
+
|
||||
+#ifndef BCMA_CC_SROM_CONTROL_OTP_PRESENT
|
||||
+#define BCMA_CC_SROM_CONTROL_OTP_PRESENT 0x00000020
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/marvell/mwl8k.c
|
||||
+++ b/drivers/net/wireless/marvell/mwl8k.c
|
||||
@@ -5699,6 +5699,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
|
||||
@@ -5703,6 +5703,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
|
||||
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
|
||||
|
||||
static const struct pci_device_id mwl8k_pci_id_table[] = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/marvell/libertas/cfg.c
|
||||
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
|
||||
@@ -2053,6 +2053,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
|
||||
@@ -2052,6 +2052,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
|
||||
goto err_wiphy_new;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
err_wiphy_new:
|
||||
--- a/drivers/net/wireless/marvell/libertas/main.c
|
||||
+++ b/drivers/net/wireless/marvell/libertas/main.c
|
||||
@@ -935,6 +935,7 @@ struct lbs_private *lbs_add_card(void *c
|
||||
@@ -934,6 +934,7 @@ struct lbs_private *lbs_add_card(void *c
|
||||
goto err_adapter;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/marvell/libertas/cfg.c
|
||||
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
|
||||
@@ -2129,6 +2129,8 @@ int lbs_cfg_register(struct lbs_private
|
||||
@@ -2128,6 +2128,8 @@ int lbs_cfg_register(struct lbs_private
|
||||
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
|
||||
wdev->wiphy->reg_notifier = lbs_reg_notifier;
|
||||
|
||||
|
@ -21,7 +21,7 @@ the card-specific structure.
|
||||
|
||||
--- a/drivers/net/wireless/marvell/mwifiex/decl.h
|
||||
+++ b/drivers/net/wireless/marvell/mwifiex/decl.h
|
||||
@@ -30,7 +30,7 @@
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#define MWIFIEX_BSS_COEX_COUNT 2
|
||||
@ -30,7 +30,7 @@ the card-specific structure.
|
||||
|
||||
#define MWIFIEX_DMA_ALIGN_SZ 64
|
||||
#define MWIFIEX_RX_HEADROOM 64
|
||||
@@ -112,7 +112,7 @@
|
||||
@@ -100,7 +100,7 @@
|
||||
#define MWIFIEX_RATE_INDEX_OFDM0 4
|
||||
|
||||
#define MWIFIEX_MAX_STA_NUM 3
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/net/wireless/marvell/mwl8k.c
|
||||
+++ b/drivers/net/wireless/marvell/mwl8k.c
|
||||
@@ -6285,6 +6285,8 @@ static int mwl8k_probe(struct pci_dev *p
|
||||
@@ -6289,6 +6289,8 @@ static int mwl8k_probe(struct pci_dev *p
|
||||
|
||||
priv->running_bsses = 0;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
return rc;
|
||||
|
||||
err_stop_firmware:
|
||||
@@ -6318,8 +6320,6 @@ static void mwl8k_remove(struct pci_dev
|
||||
@@ -6322,8 +6324,6 @@ static void mwl8k_remove(struct pci_dev
|
||||
return;
|
||||
priv = hw->priv;
|
||||
|
||||
|
@ -19,7 +19,7 @@ Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
|
||||
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
|
||||
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
|
||||
@@ -28,6 +28,85 @@
|
||||
@@ -16,6 +16,85 @@
|
||||
|
||||
static void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);
|
||||
|
||||
@ -105,7 +105,7 @@ Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
/*
|
||||
* This function initializes a command node.
|
||||
*
|
||||
@@ -205,8 +284,8 @@ static int mwifiex_dnld_cmd_to_fw(struct
|
||||
@@ -193,8 +272,8 @@ static int mwifiex_dnld_cmd_to_fw(struct
|
||||
cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
|
||||
cmd_code != HostCmd_CMD_FUNC_INIT) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
@ -116,7 +116,7 @@ Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
mwifiex_recycle_cmd_node(adapter, cmd_node);
|
||||
queue_work(adapter->workqueue, &adapter->main_work);
|
||||
return -1;
|
||||
@@ -660,8 +739,8 @@ int mwifiex_send_cmd(struct mwifiex_priv
|
||||
@@ -653,8 +732,8 @@ int mwifiex_send_cmd(struct mwifiex_priv
|
||||
/* Return error, since the command preparation failed */
|
||||
if (ret) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
@ -127,7 +127,7 @@ Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
return -1;
|
||||
}
|
||||
@@ -900,8 +979,9 @@ int mwifiex_process_cmdresp(struct mwifi
|
||||
@@ -902,8 +981,9 @@ int mwifiex_process_cmdresp(struct mwifi
|
||||
if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
|
||||
if (ret) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
@ -139,7 +139,7 @@ Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
mwifiex_init_fw_complete(adapter);
|
||||
return -1;
|
||||
} else if (adapter->last_init_cmd == cmdresp_no)
|
||||
@@ -1264,8 +1344,8 @@ mwifiex_process_sleep_confirm_resp(struc
|
||||
@@ -1273,8 +1353,8 @@ mwifiex_process_sleep_confirm_resp(struc
|
||||
|
||||
if (command != HostCmd_CMD_802_11_PS_MODE_ENH) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
@ -152,7 +152,7 @@ Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
|
||||
--- a/drivers/net/wireless/marvell/mwifiex/main.h
|
||||
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
|
||||
@@ -1108,6 +1108,8 @@ void mwifiex_cancel_all_pending_cmd(stru
|
||||
@@ -1099,6 +1099,8 @@ void mwifiex_cancel_all_pending_cmd(stru
|
||||
void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter);
|
||||
void mwifiex_cancel_scan(struct mwifiex_adapter *adapter);
|
||||
|
||||
@ -163,7 +163,7 @@ Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
|
||||
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
|
||||
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
|
||||
@@ -48,8 +48,9 @@ mwifiex_process_cmdresp_error(struct mwi
|
||||
@@ -36,8 +36,9 @@ mwifiex_process_cmdresp_error(struct mwi
|
||||
struct host_cmd_ds_802_11_ps_mode_enh *pm;
|
||||
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
@ -177,7 +177,7 @@ Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
adapter->cmd_wait_q.status = -1;
|
||||
--- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
|
||||
+++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
|
||||
@@ -806,7 +806,8 @@ int mwifiex_uap_prepare_cmd(struct mwifi
|
||||
@@ -794,7 +794,8 @@ int mwifiex_uap_prepare_cmd(struct mwifi
|
||||
break;
|
||||
default:
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
|
@ -1,52 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:26:27 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979242
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:26:27 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 01/16] rt2x00: define RF5592 in init_eeprom routine
|
||||
Message-ID:
|
||||
<d7eccb2c7b8ec4cd360fa2007796abffc35abb0d.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
From: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
|
||||
Fix incorrect RF value encoded in EEPROM on devices with Ralink Rt5592
|
||||
PCIe radio (a single chip 2T2R 802.11abgn solution).
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -9461,6 +9461,8 @@ static int rt2800_init_eeprom(struct rt2
|
||||
rf = RF3853;
|
||||
else if (rt2x00_rt(rt2x00dev, RT5350))
|
||||
rf = RF5350;
|
||||
+ else if (rt2x00_rt(rt2x00dev, RT5592))
|
||||
+ rf = RF5592;
|
||||
else
|
||||
rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
|
||||
|
@ -1,76 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:26:40 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979243
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:26:40 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 02/16] rt2x00: add throughput LED trigger
|
||||
Message-ID:
|
||||
<73f5ba4134e621462a26186449400cf0c1ac1730.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
|
||||
This adds a (currently missing) throughput LED trigger for the rt2x00
|
||||
driver. Previously, LED triggers had to be assigned to the netdev, which
|
||||
was limited to a single VAP.
|
||||
|
||||
Tested-by: Christoph Krapp <achterin@googlemail.com>
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1093,6 +1093,19 @@ static void rt2x00lib_remove_hw(struct r
|
||||
kfree(rt2x00dev->spec.channels_info);
|
||||
}
|
||||
|
||||
+static const struct ieee80211_tpt_blink rt2x00_tpt_blink[] = {
|
||||
+ { .throughput = 0 * 1024, .blink_time = 334 },
|
||||
+ { .throughput = 1 * 1024, .blink_time = 260 },
|
||||
+ { .throughput = 2 * 1024, .blink_time = 220 },
|
||||
+ { .throughput = 5 * 1024, .blink_time = 190 },
|
||||
+ { .throughput = 10 * 1024, .blink_time = 170 },
|
||||
+ { .throughput = 25 * 1024, .blink_time = 150 },
|
||||
+ { .throughput = 54 * 1024, .blink_time = 130 },
|
||||
+ { .throughput = 120 * 1024, .blink_time = 110 },
|
||||
+ { .throughput = 265 * 1024, .blink_time = 80 },
|
||||
+ { .throughput = 586 * 1024, .blink_time = 50 },
|
||||
+};
|
||||
+
|
||||
static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
||||
@@ -1174,6 +1187,11 @@ static int rt2x00lib_probe_hw(struct rt2
|
||||
|
||||
#undef RT2X00_TASKLET_INIT
|
||||
|
||||
+ ieee80211_create_tpt_led_trigger(rt2x00dev->hw,
|
||||
+ IEEE80211_TPT_LEDTRIG_FL_RADIO,
|
||||
+ rt2x00_tpt_blink,
|
||||
+ ARRAY_SIZE(rt2x00_tpt_blink));
|
||||
+
|
||||
/*
|
||||
* Register HW.
|
||||
*/
|
@ -1,125 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:26:55 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979244
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:26:55 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 03/16] rt2x00: add support for external PA on MT7620
|
||||
Message-ID:
|
||||
<af2c68ff831816a86fc39b0c10911c129a1f03dc.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
Implement support for external PA connected to MT7620A.
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
[pozega.tomislav@gmail.com: use chanreg and dccal helpers.]
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800.h | 1 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 52 ++++++++++++++++++-
|
||||
2 files changed, 52 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
|
||||
@@ -2739,6 +2739,7 @@ enum rt2800_eeprom_word {
|
||||
#define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f)
|
||||
#define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0)
|
||||
#define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600)
|
||||
+#define EEPROM_NIC_CONF2_EXTERNAL_PA FIELD16(0x8000)
|
||||
|
||||
/*
|
||||
* EEPROM LNA
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -4372,6 +4372,43 @@ static void rt2800_config_channel(struct
|
||||
rt2800_iq_calibrate(rt2x00dev, rf->channel);
|
||||
}
|
||||
|
||||
+ if (rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0,
|
||||
+ &rt2x00dev->cap_flags)) {
|
||||
+ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
|
||||
+ reg |= 0x00000101;
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
|
||||
+
|
||||
+ reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
|
||||
+ reg |= 0x00000101;
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
|
||||
+
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
|
||||
+ 0x36303636);
|
||||
+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN,
|
||||
+ 0x6C6C6B6C);
|
||||
+ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
|
||||
+ 0x6C6C6B6C);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
bbp = rt2800_bbp_read(rt2x00dev, 4);
|
||||
rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
|
||||
rt2800_bbp_write(rt2x00dev, 4, bbp);
|
||||
@@ -9592,7 +9629,8 @@ static int rt2800_init_eeprom(struct rt2
|
||||
*/
|
||||
eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
|
||||
|
||||
- if (rt2x00_rt(rt2x00dev, RT3352)) {
|
||||
+ if (rt2x00_rt(rt2x00dev, RT3352) ||
|
||||
+ rt2x00_rt(rt2x00dev, RT6352)) {
|
||||
if (rt2x00_get_field16(eeprom,
|
||||
EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352))
|
||||
__set_bit(CAPABILITY_EXTERNAL_PA_TX0,
|
||||
@@ -9603,6 +9641,18 @@ static int rt2800_init_eeprom(struct rt2
|
||||
&rt2x00dev->cap_flags);
|
||||
}
|
||||
|
||||
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF2);
|
||||
+
|
||||
+ if (rt2x00_rt(rt2x00dev, RT6352) && eeprom != 0 && eeprom != 0xffff) {
|
||||
+ if (!rt2x00_get_field16(eeprom,
|
||||
+ EEPROM_NIC_CONF2_EXTERNAL_PA)) {
|
||||
+ __clear_bit(CAPABILITY_EXTERNAL_PA_TX0,
|
||||
+ &rt2x00dev->cap_flags);
|
||||
+ __clear_bit(CAPABILITY_EXTERNAL_PA_TX1,
|
||||
+ &rt2x00dev->cap_flags);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,178 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:27:10 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979245
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:27:10 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 04/16] rt2x00: move up and reuse busy wait functions
|
||||
Message-ID:
|
||||
<3fdb9dc15e76a9f9c1948b4a3a1308a7a5677bb8.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
Move bbp_ready and rf_ready busy wait functions up in the code so they
|
||||
can more easily be used. Allow specifying register mask in rf_ready
|
||||
function which is useful for calibration routines which will be added
|
||||
in follow-up commits.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 99 +++++++++----------
|
||||
1 file changed, 46 insertions(+), 53 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -2143,6 +2143,48 @@ void rt2800_config_erp(struct rt2x00_dev
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_config_erp);
|
||||
|
||||
+static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev,
|
||||
+ const struct rt2x00_field32 mask)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
+ reg = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
|
||||
+ if (!rt2x00_get_field32(reg, mask))
|
||||
+ return 0;
|
||||
+
|
||||
+ udelay(REGISTER_BUSY_DELAY);
|
||||
+ }
|
||||
+
|
||||
+ rt2x00_err(rt2x00dev, "BBP/RF register access failed, aborting\n");
|
||||
+ return -EACCES;
|
||||
+}
|
||||
+
|
||||
+static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ u8 value;
|
||||
+
|
||||
+ /*
|
||||
+ * BBP was enabled after firmware was loaded,
|
||||
+ * but we need to reactivate it now.
|
||||
+ */
|
||||
+ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
|
||||
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
|
||||
+ msleep(1);
|
||||
+
|
||||
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
+ value = rt2800_bbp_read(rt2x00dev, 0);
|
||||
+ if ((value != 0xff) && (value != 0x00))
|
||||
+ return 0;
|
||||
+ udelay(REGISTER_BUSY_DELAY);
|
||||
+ }
|
||||
+
|
||||
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
|
||||
+ return -EACCES;
|
||||
+}
|
||||
+
|
||||
static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
@@ -3799,10 +3841,9 @@ static void rt2800_config_alc(struct rt2
|
||||
struct ieee80211_channel *chan,
|
||||
int power_level) {
|
||||
u16 eeprom, target_power, max_power;
|
||||
- u32 mac_sys_ctrl, mac_status;
|
||||
+ u32 mac_sys_ctrl;
|
||||
u32 reg;
|
||||
u8 bbp;
|
||||
- int i;
|
||||
|
||||
/* hardware unit is 0.5dBm, limited to 23.5dBm */
|
||||
power_level *= 2;
|
||||
@@ -3838,16 +3879,8 @@ static void rt2800_config_alc(struct rt2
|
||||
/* Disable Tx/Rx */
|
||||
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
|
||||
/* Check MAC Tx/Rx idle */
|
||||
- for (i = 0; i < 10000; i++) {
|
||||
- mac_status = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
|
||||
- if (mac_status & 0x3)
|
||||
- usleep_range(50, 200);
|
||||
- else
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (i == 10000)
|
||||
- rt2x00_warn(rt2x00dev, "Wait MAC Status to MAX !!!\n");
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY)))
|
||||
+ rt2x00_warn(rt2x00dev, "RF busy while configuring ALC\n");
|
||||
|
||||
if (chan->center_freq > 2457) {
|
||||
bbp = rt2800_bbp_read(rt2x00dev, 30);
|
||||
@@ -6275,46 +6308,6 @@ static int rt2800_init_registers(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
- unsigned int i;
|
||||
- u32 reg;
|
||||
-
|
||||
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
- reg = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
|
||||
- if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))
|
||||
- return 0;
|
||||
-
|
||||
- udelay(REGISTER_BUSY_DELAY);
|
||||
- }
|
||||
-
|
||||
- rt2x00_err(rt2x00dev, "BBP/RF register access failed, aborting\n");
|
||||
- return -EACCES;
|
||||
-}
|
||||
-
|
||||
-static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
|
||||
-{
|
||||
- unsigned int i;
|
||||
- u8 value;
|
||||
-
|
||||
- /*
|
||||
- * BBP was enabled after firmware was loaded,
|
||||
- * but we need to reactivate it now.
|
||||
- */
|
||||
- rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
|
||||
- rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
|
||||
- msleep(1);
|
||||
-
|
||||
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
- value = rt2800_bbp_read(rt2x00dev, 0);
|
||||
- if ((value != 0xff) && (value != 0x00))
|
||||
- return 0;
|
||||
- udelay(REGISTER_BUSY_DELAY);
|
||||
- }
|
||||
-
|
||||
- rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
|
||||
- return -EACCES;
|
||||
-}
|
||||
|
||||
static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
@@ -9136,7 +9129,7 @@ int rt2800_enable_radio(struct rt2x00_de
|
||||
/*
|
||||
* Wait BBP/RF to wake up.
|
||||
*/
|
||||
- if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev)))
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY)))
|
||||
return -EIO;
|
||||
|
||||
/*
|
@ -1,106 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:27:26 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979246
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:27:26 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 05/16] rt2x00: add RF self TXDC calibration for MT7620
|
||||
Message-ID:
|
||||
<dbb6e5a0c12d6101477bd09e83253091d21512c9.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
From: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
|
||||
Add TX self calibration based on mtk driver.
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
v2: use ++i instead of i = i + 1 in loops
|
||||
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 48 +++++++++++++++++++
|
||||
1 file changed, 48 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -8454,6 +8454,53 @@ static void rt2800_init_rfcsr_5592(struc
|
||||
rt2800_led_open_drain_enable(rt2x00dev);
|
||||
}
|
||||
|
||||
+static void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ u8 rfb5r1_org, rfb7r1_org, rfvalue;
|
||||
+ u32 mac0518, mac051c, mac0528, mac052c;
|
||||
+ u8 i;
|
||||
+
|
||||
+ mac0518 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
|
||||
+ mac051c = rt2800_register_read(rt2x00dev, RF_BYPASS0);
|
||||
+ mac0528 = rt2800_register_read(rt2x00dev, RF_CONTROL2);
|
||||
+ mac052c = rt2800_register_read(rt2x00dev, RF_BYPASS2);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS2, 0x0);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0xC);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x3306);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL2, 0x3330);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS2, 0xfffff);
|
||||
+ rfb5r1_org = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
|
||||
+ rfb7r1_org = rt2800_rfcsr_read_bank(rt2x00dev, 7, 1);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 1, 0x4);
|
||||
+ for (i = 0; i < 100; ++i) {
|
||||
+ usleep_range(50, 100);
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
|
||||
+ if ((rfvalue & 0x04) != 0x4)
|
||||
+ break;
|
||||
+ }
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 1, rfb5r1_org);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 1, 0x4);
|
||||
+ for (i = 0; i < 100; ++i) {
|
||||
+ usleep_range(50, 100);
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 1);
|
||||
+ if ((rfvalue & 0x04) != 0x4)
|
||||
+ break;
|
||||
+ }
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 1, rfb7r1_org);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS2, 0x0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, mac0518);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, mac051c);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL2, mac0528);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS2, mac052c);
|
||||
+}
|
||||
+
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9061,6 +9108,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
|
||||
|
||||
+ rt2800_rf_self_txdc_cal(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:27:41 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979247
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:27:41 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 06/16] rt2x00: add r calibration for MT7620
|
||||
Message-ID:
|
||||
<e0c34f233089bec4eb73826bc4f512166ee25934.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
From: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
|
||||
Add r calibration code as found in mtk driver.
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
v2: use rt2800_wait_bbp_rf_ready()
|
||||
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800.h | 2 +
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 133 ++++++++++++++++++
|
||||
2 files changed, 135 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
|
||||
@@ -1016,6 +1016,8 @@
|
||||
*/
|
||||
#define MAC_STATUS_CFG 0x1200
|
||||
#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003)
|
||||
+#define MAC_STATUS_CFG_BBP_RF_BUSY_TX FIELD32(0x00000001)
|
||||
+#define MAC_STATUS_CFG_BBP_RF_BUSY_RX FIELD32(0x00000002)
|
||||
|
||||
/*
|
||||
* PWR_PIN_CFG:
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -8501,6 +8501,138 @@ static void rt2800_rf_self_txdc_cal(stru
|
||||
rt2800_register_write(rt2x00dev, RF_BYPASS2, mac052c);
|
||||
}
|
||||
|
||||
+static int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2)
|
||||
+{
|
||||
+ int calcode = ((d2 - d1) * 1000) / 43;
|
||||
+
|
||||
+ if ((calcode % 10) >= 5)
|
||||
+ calcode += 10;
|
||||
+ calcode = (calcode / 10);
|
||||
+
|
||||
+ return calcode;
|
||||
+}
|
||||
+
|
||||
+static void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ u32 savemacsysctrl;
|
||||
+ u8 saverfb0r1, saverfb0r34, saverfb0r35;
|
||||
+ u8 saverfb5r4, saverfb5r17, saverfb5r18;
|
||||
+ u8 saverfb5r19, saverfb5r20;
|
||||
+ u8 savebbpr22, savebbpr47, savebbpr49;
|
||||
+ u8 bytevalue = 0;
|
||||
+ int rcalcode;
|
||||
+ u8 r_cal_code = 0;
|
||||
+ char d1 = 0, d2 = 0;
|
||||
+ u8 rfvalue;
|
||||
+ u32 MAC_RF_BYPASS0, MAC_RF_CONTROL0, MAC_PWR_PIN_CFG;
|
||||
+ u32 maccfg;
|
||||
+
|
||||
+ saverfb0r1 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1);
|
||||
+ saverfb0r34 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 34);
|
||||
+ saverfb0r35 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 35);
|
||||
+ saverfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
|
||||
+ saverfb5r17 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17);
|
||||
+ saverfb5r18 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18);
|
||||
+ saverfb5r19 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19);
|
||||
+ saverfb5r20 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20);
|
||||
+
|
||||
+ savebbpr22 = rt2800_bbp_read(rt2x00dev, 22);
|
||||
+ savebbpr47 = rt2800_bbp_read(rt2x00dev, 47);
|
||||
+ savebbpr49 = rt2800_bbp_read(rt2x00dev, 49);
|
||||
+
|
||||
+ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ MAC_RF_BYPASS0 = rt2800_register_read(rt2x00dev, RF_BYPASS0);
|
||||
+ MAC_RF_CONTROL0 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
|
||||
+ MAC_PWR_PIN_CFG = rt2800_register_read(rt2x00dev, PWR_PIN_CFG);
|
||||
+
|
||||
+ maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ maccfg &= (~0x04);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg);
|
||||
+
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_TX)))
|
||||
+ rt2x00_warn(rt2x00dev, "Wait MAC Tx Status to MAX !!!\n");
|
||||
+
|
||||
+ maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ maccfg &= (~0x04);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg);
|
||||
+
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_RX)))
|
||||
+ rt2x00_warn(rt2x00dev, "Wait MAC Rx Status to MAX !!!\n");
|
||||
+
|
||||
+ rfvalue = (MAC_RF_BYPASS0 | 0x3004);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, rfvalue);
|
||||
+ rfvalue = (MAC_RF_CONTROL0 | (~0x3002));
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, rfvalue);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, 0x27);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, 0x80);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, 0x83);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0x00);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x20);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, 0x00);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 34, 0x13);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x00);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x1);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 47, 0x04);
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x80);
|
||||
+ usleep_range(100, 200);
|
||||
+ bytevalue = rt2800_bbp_read(rt2x00dev, 49);
|
||||
+ if (bytevalue > 128)
|
||||
+ d1 = bytevalue - 256;
|
||||
+ else
|
||||
+ d1 = (char)bytevalue;
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x0);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x01);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x80);
|
||||
+ usleep_range(100, 200);
|
||||
+ bytevalue = rt2800_bbp_read(rt2x00dev, 49);
|
||||
+ if (bytevalue > 128)
|
||||
+ d2 = bytevalue - 256;
|
||||
+ else
|
||||
+ d2 = (char)bytevalue;
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x0);
|
||||
+
|
||||
+ rcalcode = rt2800_calcrcalibrationcode(rt2x00dev, d1, d2);
|
||||
+ if (rcalcode < 0)
|
||||
+ r_cal_code = 256 + rcalcode;
|
||||
+ else
|
||||
+ r_cal_code = (u8)rcalcode;
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 7, r_cal_code);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, 0x0);
|
||||
+
|
||||
+ bytevalue = rt2800_bbp_read(rt2x00dev, 21);
|
||||
+ bytevalue |= 0x1;
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bytevalue);
|
||||
+ bytevalue = rt2800_bbp_read(rt2x00dev, 21);
|
||||
+ bytevalue &= (~0x1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bytevalue);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, saverfb0r1);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 34, saverfb0r34);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, saverfb0r35);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, saverfb5r4);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, saverfb5r17);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, saverfb5r18);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, saverfb5r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, saverfb5r20);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 22, savebbpr22);
|
||||
+ rt2800_bbp_write(rt2x00dev, 47, savebbpr47);
|
||||
+ rt2800_bbp_write(rt2x00dev, 49, savebbpr49);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, MAC_RF_BYPASS0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, MAC_RF_CONTROL0);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl);
|
||||
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, MAC_PWR_PIN_CFG);
|
||||
+}
|
||||
+
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9108,6 +9240,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
|
||||
rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
|
||||
|
||||
+ rt2800_r_calibration(rt2x00dev);
|
||||
rt2800_rf_self_txdc_cal(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
@ -1,117 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:27:56 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979248
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:27:56 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 07/16] rt2x00: add RXDCOC calibration for MT7620
|
||||
Message-ID:
|
||||
<850b30f652e88de30d79e968af4eb47aa5bc2511.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
From: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
|
||||
Add RXDCOC calibration code from mtk driver.
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
[fixed typo reported by Serge Vasilugin <vasilugin@yandex.ru>]
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 60 +++++++++++++++++++
|
||||
1 file changed, 60 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -8633,6 +8633,65 @@ static void rt2800_r_calibration(struct
|
||||
rt2800_register_write(rt2x00dev, PWR_PIN_CFG, MAC_PWR_PIN_CFG);
|
||||
}
|
||||
|
||||
+static void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ u8 bbpreg = 0;
|
||||
+ u32 macvalue = 0;
|
||||
+ u8 saverfb0r2, saverfb5r4, saverfb7r4, rfvalue;
|
||||
+ int i;
|
||||
+
|
||||
+ saverfb0r2 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2);
|
||||
+ rfvalue = saverfb0r2;
|
||||
+ rfvalue |= 0x03;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfvalue);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 141);
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbpreg |= 0x10;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x8);
|
||||
+
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_TX)))
|
||||
+ rt2x00_warn(rt2x00dev, "RF TX busy in RX RXDCOC calibration\n");
|
||||
+
|
||||
+ saverfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
|
||||
+ saverfb7r4 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 4);
|
||||
+ saverfb5r4 = saverfb5r4 & (~0x40);
|
||||
+ saverfb7r4 = saverfb7r4 & (~0x40);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x64);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, saverfb5r4);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 4, saverfb7r4);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 141);
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbpreg = bbpreg & (~0x40);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+ bbpreg |= 0x48;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ if ((bbpreg & 0x40) == 0)
|
||||
+ break;
|
||||
+ usleep_range(50, 100);
|
||||
+ }
|
||||
+
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbpreg = bbpreg & (~0x40);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 141);
|
||||
+ bbpreg = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbpreg &= (~0x10);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbpreg);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, saverfb0r2);
|
||||
+}
|
||||
+
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9242,6 +9301,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
|
||||
rt2800_r_calibration(rt2x00dev);
|
||||
rt2800_rf_self_txdc_cal(rt2x00dev);
|
||||
+ rt2800_rxdcoc_calibration(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
}
|
@ -1,434 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:28:10 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979249
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:28:10 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 08/16] rt2x00: add RXIQ calibration for MT7620
|
||||
Message-ID:
|
||||
<033a39a697d51f6df258acea4c33608e0944fe4c.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
From: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
|
||||
Add RXIQ calibration found in mtk driver. With old openwrt builds this
|
||||
gets us ~8Mbps more of RX bandwidth (test with iPA/eLNA layout).
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
v2: use rt2800_wait_bbp_rf_ready(), fix indentation
|
||||
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 375 ++++++++++++++++++
|
||||
1 file changed, 375 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -8692,6 +8692,380 @@ static void rt2800_rxdcoc_calibration(st
|
||||
rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, saverfb0r2);
|
||||
}
|
||||
|
||||
+static u32 rt2800_do_sqrt_accumulation(u32 si)
|
||||
+{
|
||||
+ u32 root, root_pre, bit;
|
||||
+ char i;
|
||||
+
|
||||
+ bit = 1 << 15;
|
||||
+ root = 0;
|
||||
+ for (i = 15; i >= 0; i = i - 1) {
|
||||
+ root_pre = root + bit;
|
||||
+ if ((root_pre * root_pre) <= si)
|
||||
+ root = root_pre;
|
||||
+ bit = bit >> 1;
|
||||
+ }
|
||||
+
|
||||
+ return root;
|
||||
+}
|
||||
+
|
||||
+static void rt2800_rxiq_calibration(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ u8 rfb0r1, rfb0r2, rfb0r42;
|
||||
+ u8 rfb4r0, rfb4r19;
|
||||
+ u8 rfb5r3, rfb5r4, rfb5r17, rfb5r18, rfb5r19, rfb5r20;
|
||||
+ u8 rfb6r0, rfb6r19;
|
||||
+ u8 rfb7r3, rfb7r4, rfb7r17, rfb7r18, rfb7r19, rfb7r20;
|
||||
+
|
||||
+ u8 bbp1, bbp4;
|
||||
+ u8 bbpr241, bbpr242;
|
||||
+ u32 i;
|
||||
+ u8 ch_idx;
|
||||
+ u8 bbpval;
|
||||
+ u8 rfval, vga_idx = 0;
|
||||
+ int mi = 0, mq = 0, si = 0, sq = 0, riq = 0;
|
||||
+ int sigma_i, sigma_q, r_iq, g_rx;
|
||||
+ int g_imb;
|
||||
+ int ph_rx;
|
||||
+ u32 savemacsysctrl = 0;
|
||||
+ u32 orig_RF_CONTROL0 = 0;
|
||||
+ u32 orig_RF_BYPASS0 = 0;
|
||||
+ u32 orig_RF_CONTROL1 = 0;
|
||||
+ u32 orig_RF_BYPASS1 = 0;
|
||||
+ u32 orig_RF_CONTROL3 = 0;
|
||||
+ u32 orig_RF_BYPASS3 = 0;
|
||||
+ u32 bbpval1 = 0;
|
||||
+ static const u8 rf_vga_table[] = {0x20, 0x21, 0x22, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f};
|
||||
+
|
||||
+ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ orig_RF_CONTROL0 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
|
||||
+ orig_RF_BYPASS0 = rt2800_register_read(rt2x00dev, RF_BYPASS0);
|
||||
+ orig_RF_CONTROL1 = rt2800_register_read(rt2x00dev, RF_CONTROL1);
|
||||
+ orig_RF_BYPASS1 = rt2800_register_read(rt2x00dev, RF_BYPASS1);
|
||||
+ orig_RF_CONTROL3 = rt2800_register_read(rt2x00dev, RF_CONTROL3);
|
||||
+ orig_RF_BYPASS3 = rt2800_register_read(rt2x00dev, RF_BYPASS3);
|
||||
+
|
||||
+ bbp1 = rt2800_bbp_read(rt2x00dev, 1);
|
||||
+ bbp4 = rt2800_bbp_read(rt2x00dev, 4);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x0);
|
||||
+
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY)))
|
||||
+ rt2x00_warn(rt2x00dev, "Timeout waiting for MAC status in RXIQ calibration\n");
|
||||
+
|
||||
+ bbpval = bbp4 & (~0x18);
|
||||
+ bbpval = bbp4 | 0x00;
|
||||
+ rt2800_bbp_write(rt2x00dev, 4, bbpval);
|
||||
+
|
||||
+ bbpval = rt2800_bbp_read(rt2x00dev, 21);
|
||||
+ bbpval = bbpval | 1;
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bbpval);
|
||||
+ bbpval = bbpval & 0xfe;
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bbpval);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL1, 0x00000202);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS1, 0x00000303);
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags))
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0101);
|
||||
+ else
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0000);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0xf1f1);
|
||||
+
|
||||
+ rfb0r1 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1);
|
||||
+ rfb0r2 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2);
|
||||
+ rfb0r42 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 42);
|
||||
+ rfb4r0 = rt2800_rfcsr_read_bank(rt2x00dev, 4, 0);
|
||||
+ rfb4r19 = rt2800_rfcsr_read_bank(rt2x00dev, 4, 19);
|
||||
+ rfb5r3 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3);
|
||||
+ rfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
|
||||
+ rfb5r17 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17);
|
||||
+ rfb5r18 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18);
|
||||
+ rfb5r19 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19);
|
||||
+ rfb5r20 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20);
|
||||
+
|
||||
+ rfb6r0 = rt2800_rfcsr_read_bank(rt2x00dev, 6, 0);
|
||||
+ rfb6r19 = rt2800_rfcsr_read_bank(rt2x00dev, 6, 19);
|
||||
+ rfb7r3 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 3);
|
||||
+ rfb7r4 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 4);
|
||||
+ rfb7r17 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 17);
|
||||
+ rfb7r18 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 18);
|
||||
+ rfb7r19 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 19);
|
||||
+ rfb7r20 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 20);
|
||||
+
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x87);
|
||||
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0x27);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x38);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x38);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x80);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 18, 0xC1);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 19, 0x60);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 20, 0x00);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x0);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x0);
|
||||
+
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 5, 0x0);
|
||||
+
|
||||
+ bbpr241 = rt2800_bbp_read(rt2x00dev, 241);
|
||||
+ bbpr242 = rt2800_bbp_read(rt2x00dev, 242);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 241, 0x10);
|
||||
+ rt2800_bbp_write(rt2x00dev, 242, 0x84);
|
||||
+ rt2800_bbp_write(rt2x00dev, 244, 0x31);
|
||||
+
|
||||
+ bbpval = rt2800_bbp_dcoc_read(rt2x00dev, 3);
|
||||
+ bbpval = bbpval & (~0x7);
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 3, bbpval);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000006);
|
||||
+ usleep_range(1, 200);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00003376);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001006);
|
||||
+ udelay(1);
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x06);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x06);
|
||||
+ } else {
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x02);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x02);
|
||||
+ }
|
||||
+
|
||||
+ for (ch_idx = 0; ch_idx < 2; ch_idx = ch_idx + 1) {
|
||||
+ if (ch_idx == 0) {
|
||||
+ rfval = rfb0r1 & (~0x3);
|
||||
+ rfval = rfb0r1 | 0x1;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, rfval);
|
||||
+ rfval = rfb0r2 & (~0x33);
|
||||
+ rfval = rfb0r2 | 0x11;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfval);
|
||||
+ rfval = rfb0r42 & (~0x50);
|
||||
+ rfval = rfb0r42 | 0x10;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfval);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001006);
|
||||
+ udelay(1);
|
||||
+
|
||||
+ bbpval = bbp1 & (~0x18);
|
||||
+ bbpval = bbpval | 0x00;
|
||||
+ rt2800_bbp_write(rt2x00dev, 1, bbpval);
|
||||
+
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 1, 0x00);
|
||||
+ } else {
|
||||
+ rfval = rfb0r1 & (~0x3);
|
||||
+ rfval = rfb0r1 | 0x2;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, rfval);
|
||||
+ rfval = rfb0r2 & (~0x33);
|
||||
+ rfval = rfb0r2 | 0x22;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfval);
|
||||
+ rfval = rfb0r42 & (~0x50);
|
||||
+ rfval = rfb0r42 | 0x40;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfval);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00002006);
|
||||
+ udelay(1);
|
||||
+
|
||||
+ bbpval = bbp1 & (~0x18);
|
||||
+ bbpval = bbpval | 0x08;
|
||||
+ rt2800_bbp_write(rt2x00dev, 1, bbpval);
|
||||
+
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 1, 0x01);
|
||||
+ }
|
||||
+ usleep_range(500, 1500);
|
||||
+
|
||||
+ vga_idx = 0;
|
||||
+ while (vga_idx < 11) {
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 3, rf_vga_table[vga_idx]);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, rf_vga_table[vga_idx]);
|
||||
+
|
||||
+ rt2800_bbp_dcoc_write(rt2x00dev, 0, 0x93);
|
||||
+
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ bbpval = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ if ((bbpval & 0xff) == 0x93)
|
||||
+ usleep_range(50, 100);
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if ((bbpval & 0xff) == 0x93) {
|
||||
+ rt2x00_warn(rt2x00dev, "Fatal Error: Calibration doesn't finish");
|
||||
+ goto restore_value;
|
||||
+ }
|
||||
+ for (i = 0; i < 5; i++) {
|
||||
+ u32 bbptemp = 0;
|
||||
+ u8 value = 0;
|
||||
+ int result = 0;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x1e);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, i);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x22);
|
||||
+ value = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbptemp = bbptemp + (value << 24);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x21);
|
||||
+ value = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbptemp = bbptemp + (value << 16);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x20);
|
||||
+ value = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbptemp = bbptemp + (value << 8);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x1f);
|
||||
+ value = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbptemp = bbptemp + value;
|
||||
+
|
||||
+ if (i < 2 && (bbptemp & 0x800000))
|
||||
+ result = (bbptemp & 0xffffff) - 0x1000000;
|
||||
+ else if (i == 4)
|
||||
+ result = bbptemp;
|
||||
+ else
|
||||
+ result = bbptemp;
|
||||
+
|
||||
+ if (i == 0)
|
||||
+ mi = result / 4096;
|
||||
+ else if (i == 1)
|
||||
+ mq = result / 4096;
|
||||
+ else if (i == 2)
|
||||
+ si = bbptemp / 4096;
|
||||
+ else if (i == 3)
|
||||
+ sq = bbptemp / 4096;
|
||||
+ else
|
||||
+ riq = result / 4096;
|
||||
+ }
|
||||
+
|
||||
+ bbpval1 = si - mi * mi;
|
||||
+ rt2x00_dbg(rt2x00dev,
|
||||
+ "RXIQ si=%d, sq=%d, riq=%d, bbpval %d, vga_idx %d",
|
||||
+ si, sq, riq, bbpval1, vga_idx);
|
||||
+
|
||||
+ if (bbpval1 >= (100 * 100))
|
||||
+ break;
|
||||
+
|
||||
+ if (bbpval1 <= 100)
|
||||
+ vga_idx = vga_idx + 9;
|
||||
+ else if (bbpval1 <= 158)
|
||||
+ vga_idx = vga_idx + 8;
|
||||
+ else if (bbpval1 <= 251)
|
||||
+ vga_idx = vga_idx + 7;
|
||||
+ else if (bbpval1 <= 398)
|
||||
+ vga_idx = vga_idx + 6;
|
||||
+ else if (bbpval1 <= 630)
|
||||
+ vga_idx = vga_idx + 5;
|
||||
+ else if (bbpval1 <= 1000)
|
||||
+ vga_idx = vga_idx + 4;
|
||||
+ else if (bbpval1 <= 1584)
|
||||
+ vga_idx = vga_idx + 3;
|
||||
+ else if (bbpval1 <= 2511)
|
||||
+ vga_idx = vga_idx + 2;
|
||||
+ else
|
||||
+ vga_idx = vga_idx + 1;
|
||||
+ }
|
||||
+
|
||||
+ sigma_i = rt2800_do_sqrt_accumulation(100 * (si - mi * mi));
|
||||
+ sigma_q = rt2800_do_sqrt_accumulation(100 * (sq - mq * mq));
|
||||
+ r_iq = 10 * (riq - (mi * mq));
|
||||
+
|
||||
+ rt2x00_dbg(rt2x00dev, "Sigma_i=%d, Sigma_q=%d, R_iq=%d", sigma_i, sigma_q, r_iq);
|
||||
+
|
||||
+ if (sigma_i <= 1400 && sigma_i >= 1000 &&
|
||||
+ (sigma_i - sigma_q) <= 112 &&
|
||||
+ (sigma_i - sigma_q) >= -112 &&
|
||||
+ mi <= 32 && mi >= -32 &&
|
||||
+ mq <= 32 && mq >= -32) {
|
||||
+ r_iq = 10 * (riq - (mi * mq));
|
||||
+ rt2x00_dbg(rt2x00dev, "RXIQ Sigma_i=%d, Sigma_q=%d, R_iq=%d\n",
|
||||
+ sigma_i, sigma_q, r_iq);
|
||||
+
|
||||
+ g_rx = (1000 * sigma_q) / sigma_i;
|
||||
+ g_imb = ((-2) * 128 * (1000 - g_rx)) / (1000 + g_rx);
|
||||
+ ph_rx = (r_iq * 2292) / (sigma_i * sigma_q);
|
||||
+
|
||||
+ if (ph_rx > 20 || ph_rx < -20) {
|
||||
+ ph_rx = 0;
|
||||
+ rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
|
||||
+ }
|
||||
+
|
||||
+ if (g_imb > 12 || g_imb < -12) {
|
||||
+ g_imb = 0;
|
||||
+ rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
|
||||
+ }
|
||||
+ } else {
|
||||
+ g_imb = 0;
|
||||
+ ph_rx = 0;
|
||||
+ rt2x00_dbg(rt2x00dev, "RXIQ Sigma_i=%d, Sigma_q=%d, R_iq=%d\n",
|
||||
+ sigma_i, sigma_q, r_iq);
|
||||
+ rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
|
||||
+ }
|
||||
+
|
||||
+ if (ch_idx == 0) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x37);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, g_imb & 0x3f);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x35);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, ph_rx & 0x3f);
|
||||
+ } else {
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x55);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, g_imb & 0x3f);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x53);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, ph_rx & 0x3f);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+restore_value:
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x3);
|
||||
+ bbpval = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, (bbpval | 0x07));
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 1, bbp1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 4, bbp4);
|
||||
+ rt2800_bbp_write(rt2x00dev, 241, bbpr241);
|
||||
+ rt2800_bbp_write(rt2x00dev, 242, bbpr242);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 244, 0x00);
|
||||
+ bbpval = rt2800_bbp_read(rt2x00dev, 21);
|
||||
+ bbpval |= 0x1;
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bbpval);
|
||||
+ usleep_range(10, 200);
|
||||
+ bbpval &= 0xfe;
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, bbpval);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, rfb0r1);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfb0r2);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfb0r42);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 0, rfb4r0);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 19, rfb4r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 3, rfb5r3);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, rfb5r4);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, rfb5r17);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, rfb5r18);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, rfb5r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, rfb5r20);
|
||||
+
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 0, rfb6r0);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 19, rfb6r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 3, rfb7r3);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 4, rfb7r4);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 17, rfb7r17);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 18, rfb7r18);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 19, rfb7r19);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 20, rfb7r20);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000006);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, orig_RF_CONTROL0);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, orig_RF_BYPASS0);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL1, orig_RF_CONTROL1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS1, orig_RF_BYPASS1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, orig_RF_CONTROL3);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, orig_RF_BYPASS3);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl);
|
||||
+}
|
||||
+
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9304,6 +9678,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rxdcoc_calibration(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
+ rt2800_rxiq_calibration(rt2x00dev);
|
||||
}
|
||||
|
||||
static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
@ -1,982 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:28:43 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979251
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:28:43 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 10/16] rt2x00: add TX LOFT calibration for MT7620
|
||||
Message-ID:
|
||||
<d9295a9138a1f552b648aacb84e1419d38f5c896.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
From: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
|
||||
Add TX LOFT calibration from mtk driver.
|
||||
|
||||
Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
v2: use helper functions, make tables static const, remove useless
|
||||
debug prints
|
||||
v3: don't export function not used anywhere else
|
||||
Reported-by: kernel test robot <lkp@intel.com>
|
||||
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 902 ++++++++++++++++++
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.h | 10 +
|
||||
2 files changed, 912 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -9066,6 +9066,907 @@ restore_value:
|
||||
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl);
|
||||
}
|
||||
|
||||
+static void rt2800_rf_configstore(struct rt2x00_dev *rt2x00dev,
|
||||
+ struct rf_reg_pair rf_reg_record[][13], u8 chain)
|
||||
+{
|
||||
+ u8 rfvalue = 0;
|
||||
+
|
||||
+ if (chain == CHAIN_0) {
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1);
|
||||
+ rf_reg_record[CHAIN_0][0].bank = 0;
|
||||
+ rf_reg_record[CHAIN_0][0].reg = 1;
|
||||
+ rf_reg_record[CHAIN_0][0].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2);
|
||||
+ rf_reg_record[CHAIN_0][1].bank = 0;
|
||||
+ rf_reg_record[CHAIN_0][1].reg = 2;
|
||||
+ rf_reg_record[CHAIN_0][1].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 35);
|
||||
+ rf_reg_record[CHAIN_0][2].bank = 0;
|
||||
+ rf_reg_record[CHAIN_0][2].reg = 35;
|
||||
+ rf_reg_record[CHAIN_0][2].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 42);
|
||||
+ rf_reg_record[CHAIN_0][3].bank = 0;
|
||||
+ rf_reg_record[CHAIN_0][3].reg = 42;
|
||||
+ rf_reg_record[CHAIN_0][3].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 4, 0);
|
||||
+ rf_reg_record[CHAIN_0][4].bank = 4;
|
||||
+ rf_reg_record[CHAIN_0][4].reg = 0;
|
||||
+ rf_reg_record[CHAIN_0][4].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 4, 2);
|
||||
+ rf_reg_record[CHAIN_0][5].bank = 4;
|
||||
+ rf_reg_record[CHAIN_0][5].reg = 2;
|
||||
+ rf_reg_record[CHAIN_0][5].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 4, 34);
|
||||
+ rf_reg_record[CHAIN_0][6].bank = 4;
|
||||
+ rf_reg_record[CHAIN_0][6].reg = 34;
|
||||
+ rf_reg_record[CHAIN_0][6].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3);
|
||||
+ rf_reg_record[CHAIN_0][7].bank = 5;
|
||||
+ rf_reg_record[CHAIN_0][7].reg = 3;
|
||||
+ rf_reg_record[CHAIN_0][7].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
|
||||
+ rf_reg_record[CHAIN_0][8].bank = 5;
|
||||
+ rf_reg_record[CHAIN_0][8].reg = 4;
|
||||
+ rf_reg_record[CHAIN_0][8].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17);
|
||||
+ rf_reg_record[CHAIN_0][9].bank = 5;
|
||||
+ rf_reg_record[CHAIN_0][9].reg = 17;
|
||||
+ rf_reg_record[CHAIN_0][9].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18);
|
||||
+ rf_reg_record[CHAIN_0][10].bank = 5;
|
||||
+ rf_reg_record[CHAIN_0][10].reg = 18;
|
||||
+ rf_reg_record[CHAIN_0][10].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19);
|
||||
+ rf_reg_record[CHAIN_0][11].bank = 5;
|
||||
+ rf_reg_record[CHAIN_0][11].reg = 19;
|
||||
+ rf_reg_record[CHAIN_0][11].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20);
|
||||
+ rf_reg_record[CHAIN_0][12].bank = 5;
|
||||
+ rf_reg_record[CHAIN_0][12].reg = 20;
|
||||
+ rf_reg_record[CHAIN_0][12].value = rfvalue;
|
||||
+ } else if (chain == CHAIN_1) {
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1);
|
||||
+ rf_reg_record[CHAIN_1][0].bank = 0;
|
||||
+ rf_reg_record[CHAIN_1][0].reg = 1;
|
||||
+ rf_reg_record[CHAIN_1][0].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2);
|
||||
+ rf_reg_record[CHAIN_1][1].bank = 0;
|
||||
+ rf_reg_record[CHAIN_1][1].reg = 2;
|
||||
+ rf_reg_record[CHAIN_1][1].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 35);
|
||||
+ rf_reg_record[CHAIN_1][2].bank = 0;
|
||||
+ rf_reg_record[CHAIN_1][2].reg = 35;
|
||||
+ rf_reg_record[CHAIN_1][2].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 42);
|
||||
+ rf_reg_record[CHAIN_1][3].bank = 0;
|
||||
+ rf_reg_record[CHAIN_1][3].reg = 42;
|
||||
+ rf_reg_record[CHAIN_1][3].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 6, 0);
|
||||
+ rf_reg_record[CHAIN_1][4].bank = 6;
|
||||
+ rf_reg_record[CHAIN_1][4].reg = 0;
|
||||
+ rf_reg_record[CHAIN_1][4].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 6, 2);
|
||||
+ rf_reg_record[CHAIN_1][5].bank = 6;
|
||||
+ rf_reg_record[CHAIN_1][5].reg = 2;
|
||||
+ rf_reg_record[CHAIN_1][5].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 6, 34);
|
||||
+ rf_reg_record[CHAIN_1][6].bank = 6;
|
||||
+ rf_reg_record[CHAIN_1][6].reg = 34;
|
||||
+ rf_reg_record[CHAIN_1][6].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 3);
|
||||
+ rf_reg_record[CHAIN_1][7].bank = 7;
|
||||
+ rf_reg_record[CHAIN_1][7].reg = 3;
|
||||
+ rf_reg_record[CHAIN_1][7].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 4);
|
||||
+ rf_reg_record[CHAIN_1][8].bank = 7;
|
||||
+ rf_reg_record[CHAIN_1][8].reg = 4;
|
||||
+ rf_reg_record[CHAIN_1][8].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 17);
|
||||
+ rf_reg_record[CHAIN_1][9].bank = 7;
|
||||
+ rf_reg_record[CHAIN_1][9].reg = 17;
|
||||
+ rf_reg_record[CHAIN_1][9].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 18);
|
||||
+ rf_reg_record[CHAIN_1][10].bank = 7;
|
||||
+ rf_reg_record[CHAIN_1][10].reg = 18;
|
||||
+ rf_reg_record[CHAIN_1][10].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 19);
|
||||
+ rf_reg_record[CHAIN_1][11].bank = 7;
|
||||
+ rf_reg_record[CHAIN_1][11].reg = 19;
|
||||
+ rf_reg_record[CHAIN_1][11].value = rfvalue;
|
||||
+ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 20);
|
||||
+ rf_reg_record[CHAIN_1][12].bank = 7;
|
||||
+ rf_reg_record[CHAIN_1][12].reg = 20;
|
||||
+ rf_reg_record[CHAIN_1][12].value = rfvalue;
|
||||
+ } else {
|
||||
+ rt2x00_warn(rt2x00dev, "Unknown chain = %u\n", chain);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void rt2800_rf_configrecover(struct rt2x00_dev *rt2x00dev,
|
||||
+ struct rf_reg_pair rf_record[][13])
|
||||
+{
|
||||
+ u8 chain_index = 0, record_index = 0;
|
||||
+ u8 bank = 0, rf_register = 0, value = 0;
|
||||
+
|
||||
+ for (chain_index = 0; chain_index < 2; chain_index++) {
|
||||
+ for (record_index = 0; record_index < 13; record_index++) {
|
||||
+ bank = rf_record[chain_index][record_index].bank;
|
||||
+ rf_register = rf_record[chain_index][record_index].reg;
|
||||
+ value = rf_record[chain_index][record_index].value;
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, bank, rf_register, value);
|
||||
+ rt2x00_dbg(rt2x00dev, "bank: %d, rf_register: %d, value: %x\n",
|
||||
+ bank, rf_register, value);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void rt2800_setbbptonegenerator(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xAA);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xAB);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x0A);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xAC);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x3F);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xAD);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x3F);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 244, 0x40);
|
||||
+}
|
||||
+
|
||||
+static u32 rt2800_do_fft_accumulation(struct rt2x00_dev *rt2x00dev, u8 tidx, u8 read_neg)
|
||||
+{
|
||||
+ u32 macvalue = 0;
|
||||
+ int fftout_i = 0, fftout_q = 0;
|
||||
+ u32 ptmp = 0, pint = 0;
|
||||
+ u8 bbp = 0;
|
||||
+ u8 tidxi;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x9b);
|
||||
+
|
||||
+ bbp = 0x9b;
|
||||
+
|
||||
+ while (bbp == 0x9b) {
|
||||
+ usleep_range(10, 50);
|
||||
+ bbp = rt2800_bbp_read(rt2x00dev, 159);
|
||||
+ bbp = bbp & 0xff;
|
||||
+ }
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xba);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, tidx);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, tidx);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, tidx);
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, 0x057C);
|
||||
+
|
||||
+ fftout_i = (macvalue >> 16);
|
||||
+ fftout_i = (fftout_i & 0x8000) ? (fftout_i - 0x10000) : fftout_i;
|
||||
+ fftout_q = (macvalue & 0xffff);
|
||||
+ fftout_q = (fftout_q & 0x8000) ? (fftout_q - 0x10000) : fftout_q;
|
||||
+ ptmp = (fftout_i * fftout_i);
|
||||
+ ptmp = ptmp + (fftout_q * fftout_q);
|
||||
+ pint = ptmp;
|
||||
+ rt2x00_dbg(rt2x00dev, "I = %d, Q = %d, power = %x\n", fftout_i, fftout_q, pint);
|
||||
+ if (read_neg) {
|
||||
+ pint = pint >> 1;
|
||||
+ tidxi = 0x40 - tidx;
|
||||
+ tidxi = tidxi & 0x3f;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xba);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, tidxi);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, tidxi);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, tidxi);
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, 0x057C);
|
||||
+
|
||||
+ fftout_i = (macvalue >> 16);
|
||||
+ fftout_i = (fftout_i & 0x8000) ? (fftout_i - 0x10000) : fftout_i;
|
||||
+ fftout_q = (macvalue & 0xffff);
|
||||
+ fftout_q = (fftout_q & 0x8000) ? (fftout_q - 0x10000) : fftout_q;
|
||||
+ ptmp = (fftout_i * fftout_i);
|
||||
+ ptmp = ptmp + (fftout_q * fftout_q);
|
||||
+ ptmp = ptmp >> 1;
|
||||
+ pint = pint + ptmp;
|
||||
+ }
|
||||
+
|
||||
+ return pint;
|
||||
+}
|
||||
+
|
||||
+static u32 rt2800_read_fft_accumulation(struct rt2x00_dev *rt2x00dev, u8 tidx)
|
||||
+{
|
||||
+ u32 macvalue = 0;
|
||||
+ int fftout_i = 0, fftout_q = 0;
|
||||
+ u32 ptmp = 0, pint = 0;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xBA);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, tidx);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, tidx);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, tidx);
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, 0x057C);
|
||||
+
|
||||
+ fftout_i = (macvalue >> 16);
|
||||
+ fftout_i = (fftout_i & 0x8000) ? (fftout_i - 0x10000) : fftout_i;
|
||||
+ fftout_q = (macvalue & 0xffff);
|
||||
+ fftout_q = (fftout_q & 0x8000) ? (fftout_q - 0x10000) : fftout_q;
|
||||
+ ptmp = (fftout_i * fftout_i);
|
||||
+ ptmp = ptmp + (fftout_q * fftout_q);
|
||||
+ pint = ptmp;
|
||||
+
|
||||
+ return pint;
|
||||
+}
|
||||
+
|
||||
+static void rt2800_write_dc(struct rt2x00_dev *rt2x00dev, u8 ch_idx, u8 alc, u8 iorq, u8 dc)
|
||||
+{
|
||||
+ u8 bbp = 0;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xb0);
|
||||
+ bbp = alc | 0x80;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+
|
||||
+ if (ch_idx == 0)
|
||||
+ bbp = (iorq == 0) ? 0xb1 : 0xb2;
|
||||
+ else
|
||||
+ bbp = (iorq == 0) ? 0xb8 : 0xb9;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ bbp = dc;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+}
|
||||
+
|
||||
+static void rt2800_loft_search(struct rt2x00_dev *rt2x00dev, u8 ch_idx,
|
||||
+ u8 alc_idx, u8 dc_result[][RF_ALC_NUM][2])
|
||||
+{
|
||||
+ u32 p0 = 0, p1 = 0, pf = 0;
|
||||
+ char idx0 = 0, idx1 = 0;
|
||||
+ u8 idxf[] = {0x00, 0x00};
|
||||
+ u8 ibit = 0x20;
|
||||
+ u8 iorq;
|
||||
+ char bidx;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xb0);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x80);
|
||||
+
|
||||
+ for (bidx = 5; bidx >= 0; bidx--) {
|
||||
+ for (iorq = 0; iorq <= 1; iorq++) {
|
||||
+ if (idxf[iorq] == 0x20) {
|
||||
+ idx0 = 0x20;
|
||||
+ p0 = pf;
|
||||
+ } else {
|
||||
+ idx0 = idxf[iorq] - ibit;
|
||||
+ idx0 = idx0 & 0x3F;
|
||||
+ rt2800_write_dc(rt2x00dev, ch_idx, 0, iorq, idx0);
|
||||
+ p0 = rt2800_do_fft_accumulation(rt2x00dev, 0x0A, 0);
|
||||
+ }
|
||||
+
|
||||
+ idx1 = idxf[iorq] + (bidx == 5 ? 0 : ibit);
|
||||
+ idx1 = idx1 & 0x3F;
|
||||
+ rt2800_write_dc(rt2x00dev, ch_idx, 0, iorq, idx1);
|
||||
+ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x0A, 0);
|
||||
+
|
||||
+ rt2x00_dbg(rt2x00dev, "alc=%u, IorQ=%u, idx_final=%2x\n",
|
||||
+ alc_idx, iorq, idxf[iorq]);
|
||||
+ rt2x00_dbg(rt2x00dev, "p0=%x, p1=%x, pf=%x, idx_0=%x, idx_1=%x, ibit=%x\n",
|
||||
+ p0, p1, pf, idx0, idx1, ibit);
|
||||
+
|
||||
+ if (bidx != 5 && pf <= p0 && pf < p1) {
|
||||
+ idxf[iorq] = idxf[iorq];
|
||||
+ } else if (p0 < p1) {
|
||||
+ pf = p0;
|
||||
+ idxf[iorq] = idx0 & 0x3F;
|
||||
+ } else {
|
||||
+ pf = p1;
|
||||
+ idxf[iorq] = idx1 & 0x3F;
|
||||
+ }
|
||||
+ rt2x00_dbg(rt2x00dev, "IorQ=%u, idx_final[%u]:%x, pf:%8x\n",
|
||||
+ iorq, iorq, idxf[iorq], pf);
|
||||
+
|
||||
+ rt2800_write_dc(rt2x00dev, ch_idx, 0, iorq, idxf[iorq]);
|
||||
+ }
|
||||
+ ibit = ibit >> 1;
|
||||
+ }
|
||||
+ dc_result[ch_idx][alc_idx][0] = idxf[0];
|
||||
+ dc_result[ch_idx][alc_idx][1] = idxf[1];
|
||||
+}
|
||||
+
|
||||
+static void rt2800_iq_search(struct rt2x00_dev *rt2x00dev, u8 ch_idx, u8 *ges, u8 *pes)
|
||||
+{
|
||||
+ u32 p0 = 0, p1 = 0, pf = 0;
|
||||
+ char perr = 0, gerr = 0, iq_err = 0;
|
||||
+ char pef = 0, gef = 0;
|
||||
+ char psta, pend;
|
||||
+ char gsta, gend;
|
||||
+
|
||||
+ u8 ibit = 0x20;
|
||||
+ u8 first_search = 0x00, touch_neg_max = 0x00;
|
||||
+ char idx0 = 0, idx1 = 0;
|
||||
+ u8 gop;
|
||||
+ u8 bbp = 0;
|
||||
+ char bidx;
|
||||
+
|
||||
+ for (bidx = 5; bidx >= 1; bidx--) {
|
||||
+ for (gop = 0; gop < 2; gop++) {
|
||||
+ if (gop == 1 || bidx < 4) {
|
||||
+ if (gop == 0)
|
||||
+ iq_err = gerr;
|
||||
+ else
|
||||
+ iq_err = perr;
|
||||
+
|
||||
+ first_search = (gop == 0) ? (bidx == 3) : (bidx == 5);
|
||||
+ touch_neg_max = (gop) ? ((iq_err & 0x0F) == 0x08) :
|
||||
+ ((iq_err & 0x3F) == 0x20);
|
||||
+
|
||||
+ if (touch_neg_max) {
|
||||
+ p0 = pf;
|
||||
+ idx0 = iq_err;
|
||||
+ } else {
|
||||
+ idx0 = iq_err - ibit;
|
||||
+ bbp = (ch_idx == 0) ? ((gop == 0) ? 0x28 : 0x29) :
|
||||
+ ((gop == 0) ? 0x46 : 0x47);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, idx0);
|
||||
+
|
||||
+ p0 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 1);
|
||||
+ }
|
||||
+
|
||||
+ idx1 = iq_err + (first_search ? 0 : ibit);
|
||||
+ idx1 = (gop == 0) ? (idx1 & 0x0F) : (idx1 & 0x3F);
|
||||
+
|
||||
+ bbp = (ch_idx == 0) ? (gop == 0) ? 0x28 : 0x29 :
|
||||
+ (gop == 0) ? 0x46 : 0x47;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, idx1);
|
||||
+
|
||||
+ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 1);
|
||||
+
|
||||
+ rt2x00_dbg(rt2x00dev,
|
||||
+ "p0=%x, p1=%x, pwer_final=%x, idx0=%x, idx1=%x, iq_err=%x, gop=%d, ibit=%x\n",
|
||||
+ p0, p1, pf, idx0, idx1, iq_err, gop, ibit);
|
||||
+
|
||||
+ if (!(!first_search && pf <= p0 && pf < p1)) {
|
||||
+ if (p0 < p1) {
|
||||
+ pf = p0;
|
||||
+ iq_err = idx0;
|
||||
+ } else {
|
||||
+ pf = p1;
|
||||
+ iq_err = idx1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ bbp = (ch_idx == 0) ? (gop == 0) ? 0x28 : 0x29 :
|
||||
+ (gop == 0) ? 0x46 : 0x47;
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, iq_err);
|
||||
+
|
||||
+ if (gop == 0)
|
||||
+ gerr = iq_err;
|
||||
+ else
|
||||
+ perr = iq_err;
|
||||
+
|
||||
+ rt2x00_dbg(rt2x00dev, "IQCalibration pf=%8x (%2x, %2x) !\n",
|
||||
+ pf, gerr & 0x0F, perr & 0x3F);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (bidx > 0)
|
||||
+ ibit = (ibit >> 1);
|
||||
+ }
|
||||
+ gerr = (gerr & 0x08) ? (gerr & 0x0F) - 0x10 : (gerr & 0x0F);
|
||||
+ perr = (perr & 0x20) ? (perr & 0x3F) - 0x40 : (perr & 0x3F);
|
||||
+
|
||||
+ gerr = (gerr < -0x07) ? -0x07 : (gerr > 0x05) ? 0x05 : gerr;
|
||||
+ gsta = gerr - 1;
|
||||
+ gend = gerr + 2;
|
||||
+
|
||||
+ perr = (perr < -0x1f) ? -0x1f : (perr > 0x1d) ? 0x1d : perr;
|
||||
+ psta = perr - 1;
|
||||
+ pend = perr + 2;
|
||||
+
|
||||
+ for (gef = gsta; gef <= gend; gef = gef + 1)
|
||||
+ for (pef = psta; pef <= pend; pef = pef + 1) {
|
||||
+ bbp = (ch_idx == 0) ? 0x28 : 0x46;
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, gef & 0x0F);
|
||||
+
|
||||
+ bbp = (ch_idx == 0) ? 0x29 : 0x47;
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, pef & 0x3F);
|
||||
+
|
||||
+ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 1);
|
||||
+ if (gef == gsta && pef == psta) {
|
||||
+ pf = p1;
|
||||
+ gerr = gef;
|
||||
+ perr = pef;
|
||||
+ } else if (pf > p1) {
|
||||
+ pf = p1;
|
||||
+ gerr = gef;
|
||||
+ perr = pef;
|
||||
+ }
|
||||
+ rt2x00_dbg(rt2x00dev, "Fine IQCalibration p1=%8x pf=%8x (%2x, %2x) !\n",
|
||||
+ p1, pf, gef & 0x0F, pef & 0x3F);
|
||||
+ }
|
||||
+
|
||||
+ ges[ch_idx] = gerr & 0x0F;
|
||||
+ pes[ch_idx] = perr & 0x3F;
|
||||
+}
|
||||
+
|
||||
+static void rt2800_rf_aux_tx0_loopback(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, 0x21);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, 0x10);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x00);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, 0x1b);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 0, 0x81);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 2, 0x81);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 34, 0xee);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 3, 0x2d);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, 0x2d);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, 0x80);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, 0xd7);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0xa2);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x20);
|
||||
+}
|
||||
+
|
||||
+static void rt2800_rf_aux_tx1_loopback(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, 0x22);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, 0x20);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x00);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, 0x4b);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 0, 0x81);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 2, 0x81);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 34, 0xee);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 3, 0x2d);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 4, 0x2d);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 17, 0x80);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 18, 0xd7);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 19, 0xa2);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 20, 0x20);
|
||||
+}
|
||||
+
|
||||
+static void rt2800_loft_iq_calibration(struct rt2x00_dev *rt2x00dev)
|
||||
+{
|
||||
+ struct rf_reg_pair rf_store[CHAIN_NUM][13];
|
||||
+ u32 macorg1 = 0;
|
||||
+ u32 macorg2 = 0;
|
||||
+ u32 macorg3 = 0;
|
||||
+ u32 macorg4 = 0;
|
||||
+ u32 macorg5 = 0;
|
||||
+ u32 orig528 = 0;
|
||||
+ u32 orig52c = 0;
|
||||
+
|
||||
+ u32 savemacsysctrl = 0;
|
||||
+ u32 macvalue = 0;
|
||||
+ u32 mac13b8 = 0;
|
||||
+ u32 p0 = 0, p1 = 0;
|
||||
+ u32 p0_idx10 = 0, p1_idx10 = 0;
|
||||
+
|
||||
+ u8 rfvalue;
|
||||
+ u8 loft_dc_search_result[CHAIN_NUM][RF_ALC_NUM][2];
|
||||
+ u8 ger[CHAIN_NUM], per[CHAIN_NUM];
|
||||
+
|
||||
+ u8 vga_gain[] = {14, 14};
|
||||
+ u8 bbp = 0, ch_idx = 0, rf_alc_idx = 0, idx = 0;
|
||||
+ u8 bbpr30, rfb0r39, rfb0r42;
|
||||
+ u8 bbpr1;
|
||||
+ u8 bbpr4;
|
||||
+ u8 bbpr241, bbpr242;
|
||||
+ u8 count_step;
|
||||
+
|
||||
+ static const u8 rf_gain[] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x0c};
|
||||
+ static const u8 rfvga_gain_table[] = {0x24, 0x25, 0x26, 0x27, 0x28, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||
+ 0x31, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3F};
|
||||
+ static const u8 bbp_2324gain[] = {0x16, 0x14, 0x12, 0x10, 0x0c, 0x08};
|
||||
+
|
||||
+ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ macorg1 = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
|
||||
+ macorg2 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
|
||||
+ macorg3 = rt2800_register_read(rt2x00dev, RF_BYPASS0);
|
||||
+ macorg4 = rt2800_register_read(rt2x00dev, RF_CONTROL3);
|
||||
+ macorg5 = rt2800_register_read(rt2x00dev, RF_BYPASS3);
|
||||
+ mac13b8 = rt2800_register_read(rt2x00dev, 0x13b8);
|
||||
+ orig528 = rt2800_register_read(rt2x00dev, RF_CONTROL2);
|
||||
+ orig52c = rt2800_register_read(rt2x00dev, RF_BYPASS2);
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ macvalue &= (~0x04);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue);
|
||||
+
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_TX)))
|
||||
+ rt2x00_warn(rt2x00dev, "RF TX busy in LOFT IQ calibration\n");
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ macvalue &= (~0x08);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue);
|
||||
+
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_RX)))
|
||||
+ rt2x00_warn(rt2x00dev, "RF RX busy in LOFT IQ calibration\n");
|
||||
+
|
||||
+ for (ch_idx = 0; ch_idx < 2; ch_idx++)
|
||||
+ rt2800_rf_configstore(rt2x00dev, rf_store, ch_idx);
|
||||
+
|
||||
+ bbpr30 = rt2800_bbp_read(rt2x00dev, 30);
|
||||
+ rfb0r39 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 39);
|
||||
+ rfb0r42 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 42);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 30, 0x1F);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 39, 0x80);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, 0x5B);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x00);
|
||||
+
|
||||
+ rt2800_setbbptonegenerator(rt2x00dev);
|
||||
+
|
||||
+ for (ch_idx = 0; ch_idx < 2; ch_idx++) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x00);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00);
|
||||
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x0000000F);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00003306);
|
||||
+ rt2800_register_write(rt2x00dev, 0x13b8, 0x10);
|
||||
+ udelay(1);
|
||||
+
|
||||
+ if (ch_idx == 0)
|
||||
+ rt2800_rf_aux_tx0_loopback(rt2x00dev);
|
||||
+ else
|
||||
+ rt2800_rf_aux_tx1_loopback(rt2x00dev);
|
||||
+
|
||||
+ udelay(1);
|
||||
+
|
||||
+ if (ch_idx == 0)
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001004);
|
||||
+ else
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00002004);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x05);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x01);
|
||||
+ if (ch_idx == 0)
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+ else
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x01);
|
||||
+
|
||||
+ vga_gain[ch_idx] = 18;
|
||||
+ for (rf_alc_idx = 0; rf_alc_idx < 3; rf_alc_idx++) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, bbp_2324gain[rf_alc_idx]);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, bbp_2324gain[rf_alc_idx]);
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, RF_CONTROL3);
|
||||
+ macvalue &= (~0x0000F1F1);
|
||||
+ macvalue |= (rf_gain[rf_alc_idx] << 4);
|
||||
+ macvalue |= (rf_gain[rf_alc_idx] << 12);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, macvalue);
|
||||
+ macvalue = (0x0000F1F1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, macvalue);
|
||||
+
|
||||
+ if (rf_alc_idx == 0) {
|
||||
+ rt2800_write_dc(rt2x00dev, ch_idx, 0, 1, 0x21);
|
||||
+ for (; vga_gain[ch_idx] > 0;
|
||||
+ vga_gain[ch_idx] = vga_gain[ch_idx] - 2) {
|
||||
+ rfvalue = rfvga_gain_table[vga_gain[ch_idx]];
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 3, rfvalue);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, rfvalue);
|
||||
+ rt2800_write_dc(rt2x00dev, ch_idx, 0, 1, 0x00);
|
||||
+ rt2800_write_dc(rt2x00dev, ch_idx, 0, 0, 0x00);
|
||||
+ p0 = rt2800_do_fft_accumulation(rt2x00dev, 0x0A, 0);
|
||||
+ rt2800_write_dc(rt2x00dev, ch_idx, 0, 0, 0x21);
|
||||
+ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x0A, 0);
|
||||
+ rt2x00_dbg(rt2x00dev, "LOFT AGC %d %d\n", p0, p1);
|
||||
+ if ((p0 < 7000 * 7000) && (p1 < (7000 * 7000)))
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rt2800_write_dc(rt2x00dev, ch_idx, 0, 0, 0x00);
|
||||
+ rt2800_write_dc(rt2x00dev, ch_idx, 0, 1, 0x00);
|
||||
+
|
||||
+ rt2x00_dbg(rt2x00dev, "Used VGA %d %x\n", vga_gain[ch_idx],
|
||||
+ rfvga_gain_table[vga_gain[ch_idx]]);
|
||||
+
|
||||
+ if (vga_gain[ch_idx] < 0)
|
||||
+ vga_gain[ch_idx] = 0;
|
||||
+ }
|
||||
+
|
||||
+ rfvalue = rfvga_gain_table[vga_gain[ch_idx]];
|
||||
+
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 3, rfvalue);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, rfvalue);
|
||||
+
|
||||
+ rt2800_loft_search(rt2x00dev, ch_idx, rf_alc_idx, loft_dc_search_result);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (rf_alc_idx = 0; rf_alc_idx < 3; rf_alc_idx++) {
|
||||
+ for (idx = 0; idx < 4; idx++) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xB0);
|
||||
+ bbp = (idx << 2) + rf_alc_idx;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+ rt2x00_dbg(rt2x00dev, " ALC %2x,", bbp);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xb1);
|
||||
+ bbp = loft_dc_search_result[CHAIN_0][rf_alc_idx][0x00];
|
||||
+ bbp = bbp & 0x3F;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+ rt2x00_dbg(rt2x00dev, " I0 %2x,", bbp);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xb2);
|
||||
+ bbp = loft_dc_search_result[CHAIN_0][rf_alc_idx][0x01];
|
||||
+ bbp = bbp & 0x3F;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+ rt2x00_dbg(rt2x00dev, " Q0 %2x,", bbp);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xb8);
|
||||
+ bbp = loft_dc_search_result[CHAIN_1][rf_alc_idx][0x00];
|
||||
+ bbp = bbp & 0x3F;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+ rt2x00_dbg(rt2x00dev, " I1 %2x,", bbp);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xb9);
|
||||
+ bbp = loft_dc_search_result[CHAIN_1][rf_alc_idx][0x01];
|
||||
+ bbp = bbp & 0x3F;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+ rt2x00_dbg(rt2x00dev, " Q1 %2x\n", bbp);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x00);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x04);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+
|
||||
+ bbp = 0x00;
|
||||
+ rt2800_bbp_write(rt2x00dev, 244, 0x00);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, 0x01);
|
||||
+ udelay(1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, 0x00);
|
||||
+
|
||||
+ rt2800_rf_configrecover(rt2x00dev, rf_store);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, macorg1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x04);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, macorg2);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, macorg3);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, macorg4);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, macorg5);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL2, orig528);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS2, orig52c);
|
||||
+ rt2800_register_write(rt2x00dev, 0x13b8, mac13b8);
|
||||
+
|
||||
+ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ macorg1 = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
|
||||
+ macorg2 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
|
||||
+ macorg3 = rt2800_register_read(rt2x00dev, RF_BYPASS0);
|
||||
+ macorg4 = rt2800_register_read(rt2x00dev, RF_CONTROL3);
|
||||
+ macorg5 = rt2800_register_read(rt2x00dev, RF_BYPASS3);
|
||||
+
|
||||
+ bbpr1 = rt2800_bbp_read(rt2x00dev, 1);
|
||||
+ bbpr4 = rt2800_bbp_read(rt2x00dev, 4);
|
||||
+ bbpr241 = rt2800_bbp_read(rt2x00dev, 241);
|
||||
+ bbpr242 = rt2800_bbp_read(rt2x00dev, 242);
|
||||
+ mac13b8 = rt2800_register_read(rt2x00dev, 0x13b8);
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ macvalue &= (~0x04);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue);
|
||||
+
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_TX)))
|
||||
+ rt2x00_warn(rt2x00dev, "RF TX busy in LOFT IQ calibration\n");
|
||||
+
|
||||
+ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
|
||||
+ macvalue &= (~0x08);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue);
|
||||
+
|
||||
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_RX)))
|
||||
+ rt2x00_warn(rt2x00dev, "RF RX busy in LOFT IQ calibration\n");
|
||||
+
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x00000101);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0000F1F1);
|
||||
+ }
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x00);
|
||||
+
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 4, bbpr4 & (~0x18));
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, 0x01);
|
||||
+ udelay(1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, 0x00);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 241, 0x14);
|
||||
+ rt2800_bbp_write(rt2x00dev, 242, 0x80);
|
||||
+ rt2800_bbp_write(rt2x00dev, 244, 0x31);
|
||||
+ } else {
|
||||
+ rt2800_setbbptonegenerator(rt2x00dev);
|
||||
+ }
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00003306);
|
||||
+ udelay(1);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x0000000F);
|
||||
+
|
||||
+ if (!test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x00000000);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0000F1F1);
|
||||
+ }
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, 0x13b8, 0x00000010);
|
||||
+
|
||||
+ for (ch_idx = 0; ch_idx < 2; ch_idx++)
|
||||
+ rt2800_rf_configstore(rt2x00dev, rf_store, ch_idx);
|
||||
+
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x3B);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x3B);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x03);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x60);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xB0);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x80);
|
||||
+
|
||||
+ for (ch_idx = 0; ch_idx < 2; ch_idx++) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x00);
|
||||
+
|
||||
+ if (ch_idx == 0) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x01);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ bbp = bbpr1 & (~0x18);
|
||||
+ bbp = bbp | 0x00;
|
||||
+ rt2800_bbp_write(rt2x00dev, 1, bbp);
|
||||
+ }
|
||||
+ rt2800_rf_aux_tx0_loopback(rt2x00dev);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001004);
|
||||
+ } else {
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x01);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x01);
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX1, &rt2x00dev->cap_flags)) {
|
||||
+ bbp = bbpr1 & (~0x18);
|
||||
+ bbp = bbp | 0x08;
|
||||
+ rt2800_bbp_write(rt2x00dev, 1, bbp);
|
||||
+ }
|
||||
+ rt2800_rf_aux_tx1_loopback(rt2x00dev);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00002004);
|
||||
+ }
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x05);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x04);
|
||||
+
|
||||
+ bbp = (ch_idx == 0) ? 0x28 : 0x46;
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x06);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x06);
|
||||
+ count_step = 1;
|
||||
+ } else {
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x1F);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x1F);
|
||||
+ count_step = 2;
|
||||
+ }
|
||||
+
|
||||
+ for (; vga_gain[ch_idx] < 19; vga_gain[ch_idx] = (vga_gain[ch_idx] + count_step)) {
|
||||
+ rfvalue = rfvga_gain_table[vga_gain[ch_idx]];
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 3, rfvalue);
|
||||
+ rt2800_rfcsr_write_dccal(rt2x00dev, 4, rfvalue);
|
||||
+
|
||||
+ bbp = (ch_idx == 0) ? 0x29 : 0x47;
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+ p0 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 0);
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags))
|
||||
+ p0_idx10 = rt2800_read_fft_accumulation(rt2x00dev, 0x0A);
|
||||
+
|
||||
+ bbp = (ch_idx == 0) ? 0x29 : 0x47;
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x21);
|
||||
+ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 0);
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX1, &rt2x00dev->cap_flags))
|
||||
+ p1_idx10 = rt2800_read_fft_accumulation(rt2x00dev, 0x0A);
|
||||
+
|
||||
+ rt2x00_dbg(rt2x00dev, "IQ AGC %d %d\n", p0, p1);
|
||||
+
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ rt2x00_dbg(rt2x00dev, "IQ AGC IDX 10 %d %d\n", p0_idx10, p1_idx10);
|
||||
+ if ((p0_idx10 > 7000 * 7000) || (p1_idx10 > 7000 * 7000)) {
|
||||
+ if (vga_gain[ch_idx] != 0)
|
||||
+ vga_gain[ch_idx] = vga_gain[ch_idx] - 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((p0 > 2500 * 2500) || (p1 > 2500 * 2500))
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (vga_gain[ch_idx] > 18)
|
||||
+ vga_gain[ch_idx] = 18;
|
||||
+ rt2x00_dbg(rt2x00dev, "Used VGA %d %x\n", vga_gain[ch_idx],
|
||||
+ rfvga_gain_table[vga_gain[ch_idx]]);
|
||||
+
|
||||
+ bbp = (ch_idx == 0) ? 0x29 : 0x47;
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, bbp);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+
|
||||
+ rt2800_iq_search(rt2x00dev, ch_idx, ger, per);
|
||||
+ }
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 23, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 24, 0x00);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x04);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x28);
|
||||
+ bbp = ger[CHAIN_0] & 0x0F;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x29);
|
||||
+ bbp = per[CHAIN_0] & 0x3F;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x46);
|
||||
+ bbp = ger[CHAIN_1] & 0x0F;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x47);
|
||||
+ bbp = per[CHAIN_1] & 0x3F;
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, bbp);
|
||||
+
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) {
|
||||
+ rt2800_bbp_write(rt2x00dev, 1, bbpr1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 241, bbpr241);
|
||||
+ rt2800_bbp_write(rt2x00dev, 242, bbpr242);
|
||||
+ }
|
||||
+ rt2800_bbp_write(rt2x00dev, 244, 0x00);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, 0xB0);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, 0x00);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 30, bbpr30);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 39, rfb0r39);
|
||||
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfb0r42);
|
||||
+
|
||||
+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags))
|
||||
+ rt2800_bbp_write(rt2x00dev, 4, bbpr4);
|
||||
+
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, 0x01);
|
||||
+ udelay(1);
|
||||
+ rt2800_bbp_write(rt2x00dev, 21, 0x00);
|
||||
+
|
||||
+ rt2800_rf_configrecover(rt2x00dev, rf_store);
|
||||
+
|
||||
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, macorg1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL0, macorg2);
|
||||
+ udelay(1);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS0, macorg3);
|
||||
+ rt2800_register_write(rt2x00dev, RF_CONTROL3, macorg4);
|
||||
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, macorg5);
|
||||
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl);
|
||||
+ rt2800_register_write(rt2x00dev, 0x13b8, mac13b8);
|
||||
+}
|
||||
+
|
||||
static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
|
||||
bool set_bw, bool is_ht40)
|
||||
{
|
||||
@@ -9678,6 +10579,7 @@ static void rt2800_init_rfcsr_6352(struc
|
||||
rt2800_rxdcoc_calibration(rt2x00dev);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, true);
|
||||
rt2800_bw_filter_calibration(rt2x00dev, false);
|
||||
+ rt2800_loft_iq_calibration(rt2x00dev);
|
||||
rt2800_rxiq_calibration(rt2x00dev);
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
|
||||
@@ -17,6 +17,16 @@
|
||||
#define WCID_START 33
|
||||
#define WCID_END 222
|
||||
#define STA_IDS_SIZE (WCID_END - WCID_START + 2)
|
||||
+#define CHAIN_0 0x0
|
||||
+#define CHAIN_1 0x1
|
||||
+#define RF_ALC_NUM 6
|
||||
+#define CHAIN_NUM 2
|
||||
+
|
||||
+struct rf_reg_pair {
|
||||
+ u8 bank;
|
||||
+ u8 reg;
|
||||
+ u8 value;
|
||||
+};
|
||||
|
||||
/* RT2800 driver data structure */
|
||||
struct rt2800_drv_data {
|
@ -1,94 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:28:58 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979252
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:28:58 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 11/16] rt2x00: move helper functions up in file
|
||||
Message-ID:
|
||||
<c27baa8efd5c29e2bcb2432925d9cdc5c913a125.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
Move register access helper functions up to the head of the file so
|
||||
they can be used in all functions.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
.../net/wireless/ralink/rt2x00/rt2800lib.c | 40 +++++++++----------
|
||||
1 file changed, 20 insertions(+), 20 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -198,6 +198,26 @@ static void rt2800_rfcsr_write_dccal(str
|
||||
rt2800_rfcsr_write_bank(rt2x00dev, 7, reg, value);
|
||||
}
|
||||
|
||||
+static void rt2800_bbp_dcoc_write(struct rt2x00_dev *rt2x00dev,
|
||||
+ const u8 reg, const u8 value)
|
||||
+{
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, reg);
|
||||
+ rt2800_bbp_write(rt2x00dev, 159, value);
|
||||
+}
|
||||
+
|
||||
+static u8 rt2800_bbp_dcoc_read(struct rt2x00_dev *rt2x00dev, const u8 reg)
|
||||
+{
|
||||
+ rt2800_bbp_write(rt2x00dev, 158, reg);
|
||||
+ return rt2800_bbp_read(rt2x00dev, 159);
|
||||
+}
|
||||
+
|
||||
+static void rt2800_bbp_glrt_write(struct rt2x00_dev *rt2x00dev,
|
||||
+ const u8 reg, const u8 value)
|
||||
+{
|
||||
+ rt2800_bbp_write(rt2x00dev, 195, reg);
|
||||
+ rt2800_bbp_write(rt2x00dev, 196, value);
|
||||
+}
|
||||
+
|
||||
static u8 rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word)
|
||||
{
|
||||
@@ -6972,26 +6992,6 @@ static void rt2800_init_bbp_5592(struct
|
||||
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
|
||||
}
|
||||
|
||||
-static void rt2800_bbp_glrt_write(struct rt2x00_dev *rt2x00dev,
|
||||
- const u8 reg, const u8 value)
|
||||
-{
|
||||
- rt2800_bbp_write(rt2x00dev, 195, reg);
|
||||
- rt2800_bbp_write(rt2x00dev, 196, value);
|
||||
-}
|
||||
-
|
||||
-static void rt2800_bbp_dcoc_write(struct rt2x00_dev *rt2x00dev,
|
||||
- const u8 reg, const u8 value)
|
||||
-{
|
||||
- rt2800_bbp_write(rt2x00dev, 158, reg);
|
||||
- rt2800_bbp_write(rt2x00dev, 159, value);
|
||||
-}
|
||||
-
|
||||
-static u8 rt2800_bbp_dcoc_read(struct rt2x00_dev *rt2x00dev, const u8 reg)
|
||||
-{
|
||||
- rt2800_bbp_write(rt2x00dev, 158, reg);
|
||||
- return rt2800_bbp_read(rt2x00dev, 159);
|
||||
-}
|
||||
-
|
||||
static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u8 bbp;
|
@ -1,56 +0,0 @@
|
||||
From patchwork Sat Sep 17 20:29:13 2022
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
||||
X-Patchwork-Id: 12979253
|
||||
X-Patchwork-Delegate: kvalo@adurom.com
|
||||
Return-Path: <linux-wireless-owner@kernel.org>
|
||||
Date: Sat, 17 Sep 2022 21:29:13 +0100
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
To: linux-wireless@vger.kernel.org, Stanislaw Gruszka <stf_xl@wp.pl>,
|
||||
Helmut Schaa <helmut.schaa@googlemail.com>
|
||||
Cc: Kalle Valo <kvalo@kernel.org>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>,
|
||||
Paolo Abeni <pabeni@redhat.com>,
|
||||
Johannes Berg <johannes.berg@intel.com>
|
||||
Subject: [PATCH v3 12/16] rt2x00: fix HT20/HT40 bandwidth switch on MT7620
|
||||
Message-ID:
|
||||
<1664d89ba149f7b0bcec18b2a2abaedf49654507.1663445157.git.daniel@makrotopia.org>
|
||||
References: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
In-Reply-To: <cover.1663445157.git.daniel@makrotopia.org>
|
||||
Precedence: bulk
|
||||
List-ID: <linux-wireless.vger.kernel.org>
|
||||
X-Mailing-List: linux-wireless@vger.kernel.org
|
||||
|
||||
Add missing configuration of the channel bandwidth filter to the
|
||||
channel setup function for MT7620.
|
||||
|
||||
Reported-by: Serge Vasilugin <vasilugin@yandex.ru>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
---
|
||||
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
||||
@@ -3855,6 +3855,14 @@ static void rt2800_config_channel_rf7620
|
||||
rfcsr |= tx_agc_fc;
|
||||
rt2800_rfcsr_write_bank(rt2x00dev, 7, 59, rfcsr);
|
||||
}
|
||||
+
|
||||
+ if (conf_is_ht40(conf)) {
|
||||
+ rt2800_bbp_glrt_write(rt2x00dev, 141, 0x10);
|
||||
+ rt2800_bbp_glrt_write(rt2x00dev, 157, 0x2f);
|
||||
+ } else {
|
||||
+ rt2800_bbp_glrt_write(rt2x00dev, 141, 0x1a);
|
||||
+ rt2800_bbp_glrt_write(rt2x00dev, 157, 0x40);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
|
@ -1,6 +1,6 @@
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -345,6 +345,7 @@ RT2X00_LIB_FIRMWARE=
|
||||
@@ -354,6 +354,7 @@ RT2X00_LIB_FIRMWARE=
|
||||
RT2X00_LIB_CRYPTO=
|
||||
RT2X00_LIB_LEDS=
|
||||
RT2X00_LIB_DEBUGFS=
|
||||
@ -95,7 +95,7 @@
|
||||
/* Firmware functions */
|
||||
static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
@@ -167,7 +154,6 @@ static const struct rt2800_ops rt2800soc
|
||||
@@ -168,7 +155,6 @@ static const struct rt2800_ops rt2800soc
|
||||
.register_multiread = rt2x00mmio_register_multiread,
|
||||
.register_multiwrite = rt2x00mmio_register_multiwrite,
|
||||
.regbusy_read = rt2x00mmio_regbusy_read,
|
||||
|
@ -13,7 +13,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -224,10 +224,17 @@ static int rt2800soc_probe(struct platfo
|
||||
@@ -225,10 +225,17 @@ static int rt2800soc_probe(struct platfo
|
||||
return rt2x00soc_probe(pdev, &rt2800soc_ops);
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,8 @@
|
||||
+
|
||||
static const struct ieee80211_ops rt2800pci_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
.start = rt2x00mac_start,
|
||||
@@ -328,6 +332,9 @@ static const struct rt2800_ops rt2800pci
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
@@ -329,6 +333,9 @@ static const struct rt2800_ops rt2800pci
|
||||
.drv_init_registers = rt2800mmio_init_registers,
|
||||
.drv_get_txwi = rt2800mmio_get_txwi,
|
||||
.drv_get_dma_done = rt2800mmio_get_dma_done,
|
||||
@ -103,8 +103,8 @@
|
||||
+
|
||||
static const struct ieee80211_ops rt2800soc_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
.start = rt2x00mac_start,
|
||||
@@ -159,6 +186,9 @@ static const struct rt2800_ops rt2800soc
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
@@ -160,6 +187,9 @@ static const struct rt2800_ops rt2800soc
|
||||
.drv_init_registers = rt2800mmio_init_registers,
|
||||
.drv_get_txwi = rt2800mmio_get_txwi,
|
||||
.drv_get_dma_done = rt2800mmio_get_dma_done,
|
||||
@ -126,8 +126,8 @@
|
||||
+
|
||||
static const struct ieee80211_ops rt2800usb_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
.start = rt2x00mac_start,
|
||||
@@ -671,6 +675,9 @@ static const struct rt2800_ops rt2800usb
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
@@ -672,6 +676,9 @@ static const struct rt2800_ops rt2800usb
|
||||
.drv_init_registers = rt2800usb_init_registers,
|
||||
.drv_get_txwi = rt2800usb_get_txwi,
|
||||
.drv_get_dma_done = rt2800usb_get_dma_done,
|
||||
|
@ -9,11 +9,11 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnect
|
||||
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -1319,7 +1319,6 @@ static int ieee80211_stop_ap(struct wiph
|
||||
sdata->vif.bss_conf.ftmr_params = NULL;
|
||||
@@ -1512,7 +1512,6 @@ static int ieee80211_stop_ap(struct wiph
|
||||
link_conf->ftmr_params = NULL;
|
||||
|
||||
__sta_info_flush(sdata, true);
|
||||
- ieee80211_free_keys(sdata, true);
|
||||
|
||||
sdata->vif.bss_conf.enable_beacon = false;
|
||||
link_conf->enable_beacon = false;
|
||||
sdata->beacon_rate_set = false;
|
||||
|
@ -1,75 +0,0 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Sun, 24 Feb 2013 00:00:00 +0100
|
||||
Subject: [PATCH] mac80211: disable ipv4/ipv6 address notifiers
|
||||
|
||||
---
|
||||
net/mac80211/main.c | 18 +++++++++---------
|
||||
1 file changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -337,7 +337,7 @@ void ieee80211_restart_hw(struct ieee802
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_restart_hw);
|
||||
|
||||
-#ifdef CONFIG_INET
|
||||
+#ifdef __disabled__CONFIG_INET
|
||||
static int ieee80211_ifa_changed(struct notifier_block *nb,
|
||||
unsigned long data, void *arg)
|
||||
{
|
||||
@@ -396,7 +396,7 @@ static int ieee80211_ifa_changed(struct
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if IS_ENABLED(CONFIG_IPV6)
|
||||
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
|
||||
static int ieee80211_ifa6_changed(struct notifier_block *nb,
|
||||
unsigned long data, void *arg)
|
||||
{
|
||||
@@ -1321,14 +1321,14 @@ int ieee80211_register_hw(struct ieee802
|
||||
wiphy_unlock(hw->wiphy);
|
||||
rtnl_unlock();
|
||||
|
||||
-#ifdef CONFIG_INET
|
||||
+#ifdef __disabled__CONFIG_INET
|
||||
local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
|
||||
result = register_inetaddr_notifier(&local->ifa_notifier);
|
||||
if (result)
|
||||
goto fail_ifa;
|
||||
#endif
|
||||
|
||||
-#if IS_ENABLED(CONFIG_IPV6)
|
||||
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
|
||||
local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
|
||||
result = register_inet6addr_notifier(&local->ifa6_notifier);
|
||||
if (result)
|
||||
@@ -1337,13 +1337,13 @@ int ieee80211_register_hw(struct ieee802
|
||||
|
||||
return 0;
|
||||
|
||||
-#if IS_ENABLED(CONFIG_IPV6)
|
||||
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
|
||||
fail_ifa6:
|
||||
-#ifdef CONFIG_INET
|
||||
+#ifdef __disabled__CONFIG_INET
|
||||
unregister_inetaddr_notifier(&local->ifa_notifier);
|
||||
#endif
|
||||
#endif
|
||||
-#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
|
||||
+#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6)
|
||||
fail_ifa:
|
||||
#endif
|
||||
wiphy_unregister(local->hw.wiphy);
|
||||
@@ -1373,10 +1373,10 @@ void ieee80211_unregister_hw(struct ieee
|
||||
tasklet_kill(&local->tx_pending_tasklet);
|
||||
tasklet_kill(&local->tasklet);
|
||||
|
||||
-#ifdef CONFIG_INET
|
||||
+#ifdef __disabled__CONFIG_INET
|
||||
unregister_inetaddr_notifier(&local->ifa_notifier);
|
||||
#endif
|
||||
-#if IS_ENABLED(CONFIG_IPV6)
|
||||
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
|
||||
unregister_inet6addr_notifier(&local->ifa6_notifier);
|
||||
#endif
|
||||
|
@ -8,12 +8,12 @@ Subject: [PATCH] mac80211: allow scans in access point mode (for site survey)
|
||||
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -2497,7 +2497,7 @@ static int ieee80211_scan(struct wiphy *
|
||||
* the frames sent while scanning on other channel will be
|
||||
* lost)
|
||||
@@ -2720,6 +2720,8 @@ static int ieee80211_scan(struct wiphy *
|
||||
*/
|
||||
- if (sdata->u.ap.beacon &&
|
||||
+ if (0 && sdata->u.ap.beacon &&
|
||||
(!(wiphy->features & NL80211_FEATURE_AP_SCAN) ||
|
||||
!(req->flags & NL80211_SCAN_FLAG_AP)))
|
||||
return -EOPNOTSUPP;
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
+ /* skip check */
|
||||
+ break;
|
||||
/*
|
||||
* If the scan has been forced (and the driver supports
|
||||
* forcing), don't care about being beaconing already.
|
||||
|
@ -28,7 +28,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
|
||||
--- a/net/mac80211/sta_info.c
|
||||
+++ b/net/mac80211/sta_info.c
|
||||
@@ -357,6 +357,7 @@ struct sta_info *sta_info_alloc(struct i
|
||||
@@ -554,6 +554,7 @@ __sta_info_alloc(struct ieee80211_sub_if
|
||||
INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
|
||||
INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
|
||||
mutex_init(&sta->ampdu_mlme.mtx);
|
||||
|
@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -703,7 +703,8 @@ minstrel_ht_calc_rate_stats(struct minst
|
||||
@@ -769,7 +769,8 @@ minstrel_ht_calc_rate_stats(struct minst
|
||||
unsigned int cur_prob;
|
||||
|
||||
if (unlikely(mrs->attempts > 0)) {
|
@ -1,62 +0,0 @@
|
||||
From: Xing Song <xing.song@mediatek.com>
|
||||
Date: Tue, 23 Nov 2021 11:31:23 +0800
|
||||
Subject: [PATCH] mac80211: set up the fwd_skb->dev for mesh forwarding
|
||||
|
||||
Mesh forwarding requires that the fwd_skb->dev is set up for TX handling,
|
||||
otherwise the following warning will be generated, so set it up for the
|
||||
pending frames.
|
||||
|
||||
[ 72.835674 ] WARNING: CPU: 0 PID: 1193 at __skb_flow_dissect+0x284/0x1298
|
||||
[ 72.842379 ] Modules linked in: ksmbd pppoe ppp_async l2tp_ppp ...
|
||||
[ 72.962020 ] CPU: 0 PID: 1193 Comm: kworker/u5:1 Tainted: P S 5.4.137 #0
|
||||
[ 72.969938 ] Hardware name: MT7622_MT7531 RFB (DT)
|
||||
[ 72.974659 ] Workqueue: napi_workq napi_workfn
|
||||
[ 72.979025 ] pstate: 60000005 (nZCv daif -PAN -UAO)
|
||||
[ 72.983822 ] pc : __skb_flow_dissect+0x284/0x1298
|
||||
[ 72.988444 ] lr : __skb_flow_dissect+0x54/0x1298
|
||||
[ 72.992977 ] sp : ffffffc010c738c0
|
||||
[ 72.996293 ] x29: ffffffc010c738c0 x28: 0000000000000000
|
||||
[ 73.001615 ] x27: 000000000000ffc2 x26: ffffff800c2eb818
|
||||
[ 73.006937 ] x25: ffffffc010a987c8 x24: 00000000000000ce
|
||||
[ 73.012259 ] x23: ffffffc010c73a28 x22: ffffffc010a99c60
|
||||
[ 73.017581 ] x21: 000000000000ffc2 x20: ffffff80094da800
|
||||
[ 73.022903 ] x19: 0000000000000000 x18: 0000000000000014
|
||||
[ 73.028226 ] x17: 00000000084d16af x16: 00000000d1fc0bab
|
||||
[ 73.033548 ] x15: 00000000715f6034 x14: 000000009dbdd301
|
||||
[ 73.038870 ] x13: 00000000ea4dcbc3 x12: 0000000000000040
|
||||
[ 73.044192 ] x11: 000000000eb00ff0 x10: 0000000000000000
|
||||
[ 73.049513 ] x9 : 000000000eb00073 x8 : 0000000000000088
|
||||
[ 73.054834 ] x7 : 0000000000000000 x6 : 0000000000000001
|
||||
[ 73.060155 ] x5 : 0000000000000000 x4 : 0000000000000000
|
||||
[ 73.065476 ] x3 : ffffffc010a98000 x2 : 0000000000000000
|
||||
[ 73.070797 ] x1 : 0000000000000000 x0 : 0000000000000000
|
||||
[ 73.076120 ] Call trace:
|
||||
[ 73.078572 ] __skb_flow_dissect+0x284/0x1298
|
||||
[ 73.082846 ] __skb_get_hash+0x7c/0x228
|
||||
[ 73.086629 ] ieee80211_txq_may_transmit+0x7fc/0x17b8 [mac80211]
|
||||
[ 73.092564 ] ieee80211_tx_prepare_skb+0x20c/0x268 [mac80211]
|
||||
[ 73.098238 ] ieee80211_tx_pending+0x144/0x330 [mac80211]
|
||||
[ 73.103560 ] tasklet_action_common.isra.16+0xb4/0x158
|
||||
[ 73.108618 ] tasklet_action+0x2c/0x38
|
||||
[ 73.112286 ] __do_softirq+0x168/0x3b0
|
||||
[ 73.115954 ] do_softirq.part.15+0x88/0x98
|
||||
[ 73.119969 ] __local_bh_enable_ip+0xb0/0xb8
|
||||
[ 73.124156 ] napi_workfn+0x58/0x90
|
||||
[ 73.127565 ] process_one_work+0x20c/0x478
|
||||
[ 73.131579 ] worker_thread+0x50/0x4f0
|
||||
[ 73.135249 ] kthread+0x124/0x128
|
||||
[ 73.138484 ] ret_from_fork+0x10/0x1c
|
||||
|
||||
Signed-off-by: Xing Song <xing.song@mediatek.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -2950,6 +2950,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
|
||||
if (!fwd_skb)
|
||||
goto out;
|
||||
|
||||
+ fwd_skb->dev = sdata->dev;
|
||||
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
|
||||
fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
|
||||
info = IEEE80211_SKB_CB(fwd_skb);
|
@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -514,6 +514,14 @@ minstrel_ht_set_best_prob_rate(struct mi
|
||||
@@ -580,6 +580,14 @@ minstrel_ht_set_best_prob_rate(struct mi
|
||||
int cur_tp_avg, cur_group, cur_idx;
|
||||
int max_gpr_group, max_gpr_idx;
|
||||
int max_gpr_tp_avg, max_gpr_prob;
|
||||
@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
cur_group = MI_RATE_GROUP(index);
|
||||
cur_idx = MI_RATE_IDX(index);
|
||||
@@ -535,11 +543,6 @@ minstrel_ht_set_best_prob_rate(struct mi
|
||||
@@ -601,11 +609,6 @@ minstrel_ht_set_best_prob_rate(struct mi
|
||||
!minstrel_ht_is_legacy_group(max_tp_group))
|
||||
return;
|
||||
|
||||
@ -45,7 +45,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate);
|
||||
max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate);
|
||||
max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg;
|
||||
@@ -597,40 +600,6 @@ minstrel_ht_assign_best_tp_rates(struct
|
||||
@@ -663,40 +666,6 @@ minstrel_ht_assign_best_tp_rates(struct
|
||||
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
- int tmp_max_streams, group, tmp_idx, tmp_prob;
|
||||
- int tmp_tp = 0;
|
||||
-
|
||||
- if (!mi->sta->ht_cap.ht_supported)
|
||||
- if (!mi->sta->deflink.ht_cap.ht_supported)
|
||||
- return;
|
||||
-
|
||||
- group = MI_RATE_GROUP(mi->max_tp_rate[0]);
|
||||
@ -86,7 +86,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
static u16
|
||||
__minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi,
|
||||
enum minstrel_sample_type type)
|
||||
@@ -1110,8 +1079,6 @@ minstrel_ht_update_stats(struct minstrel
|
||||
@@ -1176,8 +1145,6 @@ minstrel_ht_update_stats(struct minstrel
|
||||
|
||||
mi->max_prob_rate = tmp_max_prob_rate;
|
||||
|
||||
@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
minstrel_ht_refill_sample_rates(mi);
|
||||
|
||||
#ifdef CPTCFG_MAC80211_DEBUGFS
|
||||
@@ -1156,7 +1123,7 @@ minstrel_ht_txstat_valid(struct minstrel
|
||||
@@ -1256,7 +1223,7 @@ minstrel_ht_ri_txstat_valid(struct minst
|
||||
}
|
||||
|
||||
static void
|
||||
@ -104,7 +104,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
{
|
||||
int group, orig_group;
|
||||
|
||||
@@ -1171,11 +1138,7 @@ minstrel_downgrade_rate(struct minstrel_
|
||||
@@ -1271,11 +1238,7 @@ minstrel_downgrade_rate(struct minstrel_
|
||||
minstrel_mcs_groups[orig_group].streams)
|
||||
continue;
|
||||
|
||||
@ -117,7 +117,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1186,7 +1149,7 @@ minstrel_ht_tx_status(void *priv, struct
|
||||
@@ -1286,7 +1249,7 @@ minstrel_ht_tx_status(void *priv, struct
|
||||
struct ieee80211_tx_info *info = st->info;
|
||||
struct minstrel_ht_sta *mi = priv_sta;
|
||||
struct ieee80211_tx_rate *ar = info->status.rates;
|
||||
@ -126,7 +126,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
struct minstrel_priv *mp = priv;
|
||||
u32 update_interval = mp->update_interval;
|
||||
bool last, update = false;
|
||||
@@ -1236,18 +1199,13 @@ minstrel_ht_tx_status(void *priv, struct
|
||||
@@ -1354,18 +1317,13 @@ minstrel_ht_tx_status(void *priv, struct
|
||||
/*
|
||||
* check for sudden death of spatial multiplexing,
|
||||
* downgrade to a lower number of streams if necessary.
|
@ -23,7 +23,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3894,7 +3894,7 @@ struct ieee80211_txq *ieee80211_next_txq
|
||||
@@ -3976,7 +3976,7 @@ struct ieee80211_txq *ieee80211_next_txq
|
||||
|
||||
if (deficit < 0)
|
||||
sta->airtime[txqi->txq.ac].deficit +=
|
||||
@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
if (deficit < 0 || !aql_check) {
|
||||
list_move_tail(&txqi->schedule_order,
|
||||
@@ -4037,7 +4037,8 @@ bool ieee80211_txq_may_transmit(struct i
|
||||
@@ -4119,7 +4119,8 @@ bool ieee80211_txq_may_transmit(struct i
|
||||
}
|
||||
sta = container_of(iter->txq.sta, struct sta_info, sta);
|
||||
if (ieee80211_sta_deficit(sta, ac) < 0)
|
||||
@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
|
||||
}
|
||||
|
||||
@@ -4045,7 +4046,7 @@ bool ieee80211_txq_may_transmit(struct i
|
||||
@@ -4127,7 +4128,7 @@ bool ieee80211_txq_may_transmit(struct i
|
||||
if (sta->airtime[ac].deficit >= 0)
|
||||
goto out;
|
||||
|
@ -0,0 +1,192 @@
|
||||
From: Alexander Wetzel <alexander@wetzel-home.de>
|
||||
Date: Sun, 9 Oct 2022 18:30:38 +0200
|
||||
Subject: [PATCH] wifi: mac80211: add internal handler for wake_tx_queue
|
||||
|
||||
Start to align the TX handling to only use internal TX queues (iTXQs):
|
||||
|
||||
Provide a handler for drivers not having a custom wake_tx_queue
|
||||
callback and update the documentation.
|
||||
|
||||
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -89,15 +89,13 @@
|
||||
/**
|
||||
* DOC: mac80211 software tx queueing
|
||||
*
|
||||
- * mac80211 provides an optional intermediate queueing implementation designed
|
||||
- * to allow the driver to keep hardware queues short and provide some fairness
|
||||
- * between different stations/interfaces.
|
||||
- * In this model, the driver pulls data frames from the mac80211 queue instead
|
||||
- * of letting mac80211 push them via drv_tx().
|
||||
- * Other frames (e.g. control or management) are still pushed using drv_tx().
|
||||
+ * mac80211 uses an intermediate queueing implementation, designed to allow the
|
||||
+ * driver to keep hardware queues short and to provide some fairness between
|
||||
+ * different stations/interfaces.
|
||||
*
|
||||
- * Drivers indicate that they use this model by implementing the .wake_tx_queue
|
||||
- * driver operation.
|
||||
+ * Drivers must provide the .wake_tx_queue driver operation by either
|
||||
+ * linking it to ieee80211_handle_wake_tx_queue() or implementing a custom
|
||||
+ * handler.
|
||||
*
|
||||
* Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with
|
||||
* another per-sta for non-data/non-mgmt and bufferable management frames, and
|
||||
@@ -106,9 +104,12 @@
|
||||
* The driver is expected to initialize its private per-queue data for stations
|
||||
* and interfaces in the .add_interface and .sta_add ops.
|
||||
*
|
||||
- * The driver can't access the queue directly. To dequeue a frame from a
|
||||
- * txq, it calls ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a
|
||||
- * queue, it calls the .wake_tx_queue driver op.
|
||||
+ * The driver can't access the internal TX queues (iTXQs) directly.
|
||||
+ * Whenever mac80211 adds a new frame to a queue, it calls the .wake_tx_queue
|
||||
+ * driver op.
|
||||
+ * Drivers implementing a custom .wake_tx_queue op can get them by calling
|
||||
+ * ieee80211_tx_dequeue(). Drivers using ieee80211_handle_wake_tx_queue() will
|
||||
+ * simply get the individual frames pushed via the .tx driver operation.
|
||||
*
|
||||
* Drivers can optionally delegate responsibility for scheduling queues to
|
||||
* mac80211, to take advantage of airtime fairness accounting. In this case, to
|
||||
@@ -1826,7 +1827,7 @@ struct ieee80211_vif_cfg {
|
||||
* for this interface.
|
||||
* @drv_priv: data area for driver use, will always be aligned to
|
||||
* sizeof(void \*).
|
||||
- * @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
|
||||
+ * @txq: the multicast data TX queue
|
||||
* @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
|
||||
* protected by fq->lock.
|
||||
* @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
|
||||
@@ -2252,8 +2253,8 @@ struct ieee80211_link_sta {
|
||||
* For non MLO STA it will point to the deflink data. For MLO STA
|
||||
* ieee80211_sta_recalc_aggregates() must be called to update it.
|
||||
* @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
|
||||
- * @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
|
||||
- * the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
|
||||
+ * @txq: per-TID data TX queues; note that the last entry (%IEEE80211_NUM_TIDS)
|
||||
+ * is used for non-data frames
|
||||
* @deflink: This holds the default link STA information, for non MLO STA all link
|
||||
* specific STA information is accessed through @deflink or through
|
||||
* link[0] which points to address of @deflink. For MLO Link STA
|
||||
@@ -5691,7 +5692,7 @@ void ieee80211_key_replay(struct ieee802
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
||||
* @queue: queue number (counted from zero).
|
||||
*
|
||||
- * Drivers should use this function instead of netif_wake_queue.
|
||||
+ * Drivers must use this function instead of netif_wake_queue.
|
||||
*/
|
||||
void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
|
||||
|
||||
@@ -5700,7 +5701,7 @@ void ieee80211_wake_queue(struct ieee802
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
||||
* @queue: queue number (counted from zero).
|
||||
*
|
||||
- * Drivers should use this function instead of netif_stop_queue.
|
||||
+ * Drivers must use this function instead of netif_stop_queue.
|
||||
*/
|
||||
void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
|
||||
|
||||
@@ -5709,7 +5710,7 @@ void ieee80211_stop_queue(struct ieee802
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
||||
* @queue: queue number (counted from zero).
|
||||
*
|
||||
- * Drivers should use this function instead of netif_stop_queue.
|
||||
+ * Drivers must use this function instead of netif_queue_stopped.
|
||||
*
|
||||
* Return: %true if the queue is stopped. %false otherwise.
|
||||
*/
|
||||
@@ -5720,7 +5721,7 @@ int ieee80211_queue_stopped(struct ieee8
|
||||
* ieee80211_stop_queues - stop all queues
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
||||
*
|
||||
- * Drivers should use this function instead of netif_stop_queue.
|
||||
+ * Drivers must use this function instead of netif_tx_stop_all_queues.
|
||||
*/
|
||||
void ieee80211_stop_queues(struct ieee80211_hw *hw);
|
||||
|
||||
@@ -5728,7 +5729,7 @@ void ieee80211_stop_queues(struct ieee80
|
||||
* ieee80211_wake_queues - wake all queues
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
||||
*
|
||||
- * Drivers should use this function instead of netif_wake_queue.
|
||||
+ * Drivers must use this function instead of netif_tx_wake_all_queues.
|
||||
*/
|
||||
void ieee80211_wake_queues(struct ieee80211_hw *hw);
|
||||
|
||||
@@ -6950,6 +6951,18 @@ static inline struct sk_buff *ieee80211_
|
||||
}
|
||||
|
||||
/**
|
||||
+ * ieee80211_handle_wake_tx_queue - mac80211 handler for wake_tx_queue callback
|
||||
+ *
|
||||
+ * @hw: pointer as obtained from wake_tx_queue() callback().
|
||||
+ * @txq: pointer as obtained from wake_tx_queue() callback().
|
||||
+ *
|
||||
+ * Drivers can use this function for the mandatory mac80211 wake_tx_queue
|
||||
+ * callback in struct ieee80211_ops. They should not call this function.
|
||||
+ */
|
||||
+void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_txq *txq);
|
||||
+
|
||||
+/**
|
||||
* ieee80211_next_txq - get next tx queue to pull packets from
|
||||
*
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw()
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -288,6 +288,52 @@ __le16 ieee80211_ctstoself_duration(stru
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_ctstoself_duration);
|
||||
|
||||
+static void wake_tx_push_queue(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sub_if_data *sdata,
|
||||
+ struct ieee80211_txq *queue)
|
||||
+{
|
||||
+ int q = sdata->vif.hw_queue[queue->ac];
|
||||
+ struct ieee80211_tx_control control = {
|
||||
+ .sta = queue->sta,
|
||||
+ };
|
||||
+ struct sk_buff *skb;
|
||||
+ unsigned long flags;
|
||||
+ bool q_stopped;
|
||||
+
|
||||
+ while (1) {
|
||||
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
+ q_stopped = local->queue_stop_reasons[q];
|
||||
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
+
|
||||
+ if (q_stopped)
|
||||
+ break;
|
||||
+
|
||||
+ skb = ieee80211_tx_dequeue(&local->hw, queue);
|
||||
+ if (!skb)
|
||||
+ break;
|
||||
+
|
||||
+ drv_tx(local, &control, skb);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* wake_tx_queue handler for driver not implementing a custom one*/
|
||||
+void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_txq *txq)
|
||||
+{
|
||||
+ struct ieee80211_local *local = hw_to_local(hw);
|
||||
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
|
||||
+ struct ieee80211_txq *queue;
|
||||
+
|
||||
+ /* Use ieee80211_next_txq() for airtime fairness accounting */
|
||||
+ ieee80211_txq_schedule_start(hw, txq->ac);
|
||||
+ while ((queue = ieee80211_next_txq(hw, txq->ac))) {
|
||||
+ wake_tx_push_queue(local, sdata, queue);
|
||||
+ ieee80211_return_txq(hw, queue, false);
|
||||
+ }
|
||||
+ ieee80211_txq_schedule_end(hw, txq->ac);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
|
||||
+
|
||||
static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
@ -0,0 +1,396 @@
|
||||
From: Alexander Wetzel <alexander@wetzel-home.de>
|
||||
Date: Sun, 9 Oct 2022 18:30:39 +0200
|
||||
Subject: [PATCH] wifi: mac80211: add wake_tx_queue callback to drivers
|
||||
|
||||
mac80211 is fully switching over to the internal TX queue (iTXQ)
|
||||
implementation. Update all drivers not yet providing the now mandatory
|
||||
wake_tx_queue() callback.
|
||||
|
||||
As an side effect the netdev interfaces of all updated drivers will
|
||||
switch to the noqueue qdisc.
|
||||
|
||||
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
|
||||
[add staging drivers]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/admtek/adm8211.c
|
||||
+++ b/drivers/net/wireless/admtek/adm8211.c
|
||||
@@ -1760,6 +1760,7 @@ static int adm8211_alloc_rings(struct ie
|
||||
|
||||
static const struct ieee80211_ops adm8211_ops = {
|
||||
.tx = adm8211_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = adm8211_start,
|
||||
.stop = adm8211_stop,
|
||||
.add_interface = adm8211_add_interface,
|
||||
--- a/drivers/net/wireless/ath/ar5523/ar5523.c
|
||||
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
|
||||
@@ -1355,6 +1355,7 @@ static const struct ieee80211_ops ar5523
|
||||
.start = ar5523_start,
|
||||
.stop = ar5523_stop,
|
||||
.tx = ar5523_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.set_rts_threshold = ar5523_set_rts_threshold,
|
||||
.add_interface = ar5523_add_interface,
|
||||
.remove_interface = ar5523_remove_interface,
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -8539,6 +8539,7 @@ err_fallback:
|
||||
|
||||
static const struct ieee80211_ops ath11k_ops = {
|
||||
.tx = ath11k_mac_op_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = ath11k_mac_op_start,
|
||||
.stop = ath11k_mac_op_stop,
|
||||
.reconfig_complete = ath11k_mac_op_reconfig_complete,
|
||||
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
|
||||
@@ -781,6 +781,7 @@ static int ath5k_set_ringparam(struct ie
|
||||
|
||||
const struct ieee80211_ops ath5k_hw_ops = {
|
||||
.tx = ath5k_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = ath5k_start,
|
||||
.stop = ath5k_stop,
|
||||
.add_interface = ath5k_add_interface,
|
||||
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
|
||||
@@ -1870,6 +1870,7 @@ static void ath9k_htc_channel_switch_bea
|
||||
|
||||
struct ieee80211_ops ath9k_htc_ops = {
|
||||
.tx = ath9k_htc_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = ath9k_htc_start,
|
||||
.stop = ath9k_htc_stop,
|
||||
.add_interface = ath9k_htc_add_interface,
|
||||
--- a/drivers/net/wireless/ath/carl9170/main.c
|
||||
+++ b/drivers/net/wireless/ath/carl9170/main.c
|
||||
@@ -1715,6 +1715,7 @@ static const struct ieee80211_ops carl91
|
||||
.start = carl9170_op_start,
|
||||
.stop = carl9170_op_stop,
|
||||
.tx = carl9170_op_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.flush = carl9170_op_flush,
|
||||
.add_interface = carl9170_op_add_interface,
|
||||
.remove_interface = carl9170_op_remove_interface,
|
||||
--- a/drivers/net/wireless/ath/wcn36xx/main.c
|
||||
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
|
||||
@@ -1362,6 +1362,7 @@ static const struct ieee80211_ops wcn36x
|
||||
.prepare_multicast = wcn36xx_prepare_multicast,
|
||||
.configure_filter = wcn36xx_configure_filter,
|
||||
.tx = wcn36xx_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.set_key = wcn36xx_set_key,
|
||||
.hw_scan = wcn36xx_hw_scan,
|
||||
.cancel_hw_scan = wcn36xx_cancel_hw_scan,
|
||||
--- a/drivers/net/wireless/atmel/at76c50x-usb.c
|
||||
+++ b/drivers/net/wireless/atmel/at76c50x-usb.c
|
||||
@@ -2187,6 +2187,7 @@ static int at76_set_key(struct ieee80211
|
||||
|
||||
static const struct ieee80211_ops at76_ops = {
|
||||
.tx = at76_mac80211_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.add_interface = at76_add_interface,
|
||||
.remove_interface = at76_remove_interface,
|
||||
.config = at76_config,
|
||||
--- a/drivers/net/wireless/broadcom/b43/main.c
|
||||
+++ b/drivers/net/wireless/broadcom/b43/main.c
|
||||
@@ -5171,6 +5171,7 @@ static int b43_op_get_survey(struct ieee
|
||||
|
||||
static const struct ieee80211_ops b43_hw_ops = {
|
||||
.tx = b43_op_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.conf_tx = b43_op_conf_tx,
|
||||
.add_interface = b43_op_add_interface,
|
||||
.remove_interface = b43_op_remove_interface,
|
||||
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
|
||||
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
|
||||
@@ -3532,6 +3532,7 @@ static int b43legacy_op_get_survey(struc
|
||||
|
||||
static const struct ieee80211_ops b43legacy_hw_ops = {
|
||||
.tx = b43legacy_op_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.conf_tx = b43legacy_op_conf_tx,
|
||||
.add_interface = b43legacy_op_add_interface,
|
||||
.remove_interface = b43legacy_op_remove_interface,
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
|
||||
@@ -962,6 +962,7 @@ static int brcms_ops_beacon_set_tim(stru
|
||||
|
||||
static const struct ieee80211_ops brcms_ops = {
|
||||
.tx = brcms_ops_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = brcms_ops_start,
|
||||
.stop = brcms_ops_stop,
|
||||
.add_interface = brcms_ops_add_interface,
|
||||
--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
|
||||
+++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
|
||||
@@ -3435,6 +3435,7 @@ static const struct attribute_group il39
|
||||
|
||||
static struct ieee80211_ops il3945_mac_ops __ro_after_init = {
|
||||
.tx = il3945_mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = il3945_mac_start,
|
||||
.stop = il3945_mac_stop,
|
||||
.add_interface = il_mac_add_interface,
|
||||
--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
|
||||
+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
|
||||
@@ -6304,6 +6304,7 @@ il4965_tx_queue_set_status(struct il_pri
|
||||
|
||||
static const struct ieee80211_ops il4965_mac_ops = {
|
||||
.tx = il4965_mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = il4965_mac_start,
|
||||
.stop = il4965_mac_stop,
|
||||
.add_interface = il_mac_add_interface,
|
||||
--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
|
||||
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
|
||||
@@ -1571,6 +1571,7 @@ static void iwlagn_mac_sta_notify(struct
|
||||
|
||||
const struct ieee80211_ops iwlagn_hw_ops = {
|
||||
.tx = iwlagn_mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = iwlagn_mac_start,
|
||||
.stop = iwlagn_mac_stop,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
--- a/drivers/net/wireless/intersil/p54/main.c
|
||||
+++ b/drivers/net/wireless/intersil/p54/main.c
|
||||
@@ -705,6 +705,7 @@ static void p54_set_coverage_class(struc
|
||||
|
||||
static const struct ieee80211_ops p54_ops = {
|
||||
.tx = p54_tx_80211,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = p54_start,
|
||||
.stop = p54_stop,
|
||||
.add_interface = p54_add_interface,
|
||||
--- a/drivers/net/wireless/mac80211_hwsim.c
|
||||
+++ b/drivers/net/wireless/mac80211_hwsim.c
|
||||
@@ -3109,6 +3109,7 @@ static int mac80211_hwsim_change_sta_lin
|
||||
|
||||
#define HWSIM_COMMON_OPS \
|
||||
.tx = mac80211_hwsim_tx, \
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue, \
|
||||
.start = mac80211_hwsim_start, \
|
||||
.stop = mac80211_hwsim_stop, \
|
||||
.add_interface = mac80211_hwsim_add_interface, \
|
||||
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
|
||||
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
|
||||
@@ -474,6 +474,7 @@ static int lbtf_op_get_survey(struct iee
|
||||
|
||||
static const struct ieee80211_ops lbtf_ops = {
|
||||
.tx = lbtf_op_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = lbtf_op_start,
|
||||
.stop = lbtf_op_stop,
|
||||
.add_interface = lbtf_op_add_interface,
|
||||
--- a/drivers/net/wireless/marvell/mwl8k.c
|
||||
+++ b/drivers/net/wireless/marvell/mwl8k.c
|
||||
@@ -5611,6 +5611,7 @@ static void mwl8k_sw_scan_complete(struc
|
||||
|
||||
static const struct ieee80211_ops mwl8k_ops = {
|
||||
.tx = mwl8k_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = mwl8k_start,
|
||||
.stop = mwl8k_stop,
|
||||
.add_interface = mwl8k_add_interface,
|
||||
--- a/drivers/net/wireless/mediatek/mt7601u/main.c
|
||||
+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
|
||||
@@ -406,6 +406,7 @@ out:
|
||||
|
||||
const struct ieee80211_ops mt7601u_ops = {
|
||||
.tx = mt7601u_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = mt7601u_start,
|
||||
.stop = mt7601u_stop,
|
||||
.add_interface = mt7601u_add_interface,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
|
||||
@@ -1706,6 +1706,7 @@ static int rt2400pci_tx_last_beacon(stru
|
||||
|
||||
static const struct ieee80211_ops rt2400pci_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rt2x00mac_start,
|
||||
.stop = rt2x00mac_stop,
|
||||
.add_interface = rt2x00mac_add_interface,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
|
||||
@@ -2004,6 +2004,7 @@ static int rt2500pci_tx_last_beacon(stru
|
||||
|
||||
static const struct ieee80211_ops rt2500pci_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rt2x00mac_start,
|
||||
.stop = rt2x00mac_stop,
|
||||
.add_interface = rt2x00mac_add_interface,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
|
||||
@@ -1795,6 +1795,7 @@ static int rt2500usb_probe_hw(struct rt2
|
||||
|
||||
static const struct ieee80211_ops rt2500usb_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rt2x00mac_start,
|
||||
.stop = rt2x00mac_stop,
|
||||
.add_interface = rt2x00mac_add_interface,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
|
||||
@@ -288,6 +288,7 @@ static int rt2800pci_read_eeprom(struct
|
||||
|
||||
static const struct ieee80211_ops rt2800pci_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rt2x00mac_start,
|
||||
.stop = rt2x00mac_stop,
|
||||
.add_interface = rt2x00mac_add_interface,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
|
||||
@@ -133,6 +133,7 @@ static int rt2800soc_write_firmware(stru
|
||||
|
||||
static const struct ieee80211_ops rt2800soc_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rt2x00mac_start,
|
||||
.stop = rt2x00mac_stop,
|
||||
.add_interface = rt2x00mac_add_interface,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
@@ -630,6 +630,7 @@ static int rt2800usb_probe_hw(struct rt2
|
||||
|
||||
static const struct ieee80211_ops rt2800usb_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rt2x00mac_start,
|
||||
.stop = rt2x00mac_stop,
|
||||
.add_interface = rt2x00mac_add_interface,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
|
||||
@@ -2873,6 +2873,7 @@ static u64 rt61pci_get_tsf(struct ieee80
|
||||
|
||||
static const struct ieee80211_ops rt61pci_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rt2x00mac_start,
|
||||
.stop = rt2x00mac_stop,
|
||||
.add_interface = rt2x00mac_add_interface,
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
|
||||
@@ -2292,6 +2292,7 @@ static u64 rt73usb_get_tsf(struct ieee80
|
||||
|
||||
static const struct ieee80211_ops rt73usb_mac80211_ops = {
|
||||
.tx = rt2x00mac_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rt2x00mac_start,
|
||||
.stop = rt2x00mac_stop,
|
||||
.add_interface = rt2x00mac_add_interface,
|
||||
--- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
|
||||
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
|
||||
@@ -1608,6 +1608,7 @@ static void rtl8180_configure_filter(str
|
||||
|
||||
static const struct ieee80211_ops rtl8180_ops = {
|
||||
.tx = rtl8180_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rtl8180_start,
|
||||
.stop = rtl8180_stop,
|
||||
.add_interface = rtl8180_add_interface,
|
||||
--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
|
||||
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
|
||||
@@ -1378,6 +1378,7 @@ static int rtl8187_conf_tx(struct ieee80
|
||||
|
||||
static const struct ieee80211_ops rtl8187_ops = {
|
||||
.tx = rtl8187_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rtl8187_start,
|
||||
.stop = rtl8187_stop,
|
||||
.add_interface = rtl8187_add_interface,
|
||||
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
|
||||
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
|
||||
@@ -6561,6 +6561,7 @@ static void rtl8xxxu_stop(struct ieee802
|
||||
|
||||
static const struct ieee80211_ops rtl8xxxu_ops = {
|
||||
.tx = rtl8xxxu_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.add_interface = rtl8xxxu_add_interface,
|
||||
.remove_interface = rtl8xxxu_remove_interface,
|
||||
.config = rtl8xxxu_config,
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
|
||||
@@ -1912,6 +1912,7 @@ const struct ieee80211_ops rtl_ops = {
|
||||
.start = rtl_op_start,
|
||||
.stop = rtl_op_stop,
|
||||
.tx = rtl_op_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.add_interface = rtl_op_add_interface,
|
||||
.remove_interface = rtl_op_remove_interface,
|
||||
.change_interface = rtl_op_change_interface,
|
||||
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
|
||||
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
|
||||
@@ -896,6 +896,7 @@ static void rtw_ops_sta_rc_update(struct
|
||||
|
||||
const struct ieee80211_ops rtw_ops = {
|
||||
.tx = rtw_ops_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.wake_tx_queue = rtw_ops_wake_tx_queue,
|
||||
.start = rtw_ops_start,
|
||||
.stop = rtw_ops_stop,
|
||||
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
|
||||
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
|
||||
@@ -918,6 +918,7 @@ static int rtw89_ops_set_tid_config(stru
|
||||
|
||||
const struct ieee80211_ops rtw89_ops = {
|
||||
.tx = rtw89_ops_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.wake_tx_queue = rtw89_ops_wake_tx_queue,
|
||||
.start = rtw89_ops_start,
|
||||
.stop = rtw89_ops_stop,
|
||||
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
|
||||
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
|
||||
@@ -1958,6 +1958,7 @@ static int rsi_mac80211_resume(struct ie
|
||||
|
||||
static const struct ieee80211_ops mac80211_ops = {
|
||||
.tx = rsi_mac80211_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = rsi_mac80211_start,
|
||||
.stop = rsi_mac80211_stop,
|
||||
.add_interface = rsi_mac80211_add_interface,
|
||||
--- a/drivers/net/wireless/st/cw1200/main.c
|
||||
+++ b/drivers/net/wireless/st/cw1200/main.c
|
||||
@@ -209,6 +209,7 @@ static const struct ieee80211_ops cw1200
|
||||
.remove_interface = cw1200_remove_interface,
|
||||
.change_interface = cw1200_change_interface,
|
||||
.tx = cw1200_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.hw_scan = cw1200_hw_scan,
|
||||
.set_tim = cw1200_set_tim,
|
||||
.sta_notify = cw1200_sta_notify,
|
||||
--- a/drivers/net/wireless/ti/wl1251/main.c
|
||||
+++ b/drivers/net/wireless/ti/wl1251/main.c
|
||||
@@ -1359,6 +1359,7 @@ static const struct ieee80211_ops wl1251
|
||||
.prepare_multicast = wl1251_op_prepare_multicast,
|
||||
.configure_filter = wl1251_op_configure_filter,
|
||||
.tx = wl1251_op_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.set_key = wl1251_op_set_key,
|
||||
.hw_scan = wl1251_op_hw_scan,
|
||||
.bss_info_changed = wl1251_op_bss_info_changed,
|
||||
--- a/drivers/net/wireless/ti/wlcore/main.c
|
||||
+++ b/drivers/net/wireless/ti/wlcore/main.c
|
||||
@@ -5942,6 +5942,7 @@ static const struct ieee80211_ops wl1271
|
||||
.prepare_multicast = wl1271_op_prepare_multicast,
|
||||
.configure_filter = wl1271_op_configure_filter,
|
||||
.tx = wl1271_op_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.set_key = wlcore_op_set_key,
|
||||
.hw_scan = wl1271_op_hw_scan,
|
||||
.cancel_hw_scan = wl1271_op_cancel_hw_scan,
|
||||
--- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
|
||||
+++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
|
||||
@@ -1344,6 +1344,7 @@ static u64 zd_op_get_tsf(struct ieee8021
|
||||
|
||||
static const struct ieee80211_ops zd_ops = {
|
||||
.tx = zd_op_tx,
|
||||
+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = zd_op_start,
|
||||
.stop = zd_op_stop,
|
||||
.add_interface = zd_op_add_interface,
|
@ -0,0 +1,655 @@
|
||||
From: Alexander Wetzel <alexander@wetzel-home.de>
|
||||
Date: Sun, 9 Oct 2022 18:30:40 +0200
|
||||
Subject: [PATCH] wifi: mac80211: Drop support for TX push path
|
||||
|
||||
All drivers are now using mac80211 internal queues (iTXQs).
|
||||
Drop mac80211 internal support for the old push path.
|
||||
|
||||
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -4339,9 +4339,6 @@ static int ieee80211_get_txq_stats(struc
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
int ret = 0;
|
||||
|
||||
- if (!local->ops->wake_tx_queue)
|
||||
- return 1;
|
||||
-
|
||||
spin_lock_bh(&local->fq.lock);
|
||||
rcu_read_lock();
|
||||
|
||||
--- a/net/mac80211/debugfs.c
|
||||
+++ b/net/mac80211/debugfs.c
|
||||
@@ -663,9 +663,7 @@ void debugfs_hw_add(struct ieee80211_loc
|
||||
DEBUGFS_ADD_MODE(force_tx_status, 0600);
|
||||
DEBUGFS_ADD_MODE(aql_enable, 0600);
|
||||
DEBUGFS_ADD(aql_pending);
|
||||
-
|
||||
- if (local->ops->wake_tx_queue)
|
||||
- DEBUGFS_ADD_MODE(aqm, 0600);
|
||||
+ DEBUGFS_ADD_MODE(aqm, 0600);
|
||||
|
||||
DEBUGFS_ADD_MODE(airtime_flags, 0600);
|
||||
|
||||
--- a/net/mac80211/debugfs_netdev.c
|
||||
+++ b/net/mac80211/debugfs_netdev.c
|
||||
@@ -677,8 +677,7 @@ static void add_common_files(struct ieee
|
||||
DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz);
|
||||
DEBUGFS_ADD(hw_queues);
|
||||
|
||||
- if (sdata->local->ops->wake_tx_queue &&
|
||||
- sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
|
||||
+ if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
|
||||
sdata->vif.type != NL80211_IFTYPE_NAN)
|
||||
DEBUGFS_ADD(aqm);
|
||||
}
|
||||
--- a/net/mac80211/debugfs_sta.c
|
||||
+++ b/net/mac80211/debugfs_sta.c
|
||||
@@ -1056,10 +1056,8 @@ void ieee80211_sta_debugfs_add(struct st
|
||||
DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments);
|
||||
DEBUGFS_ADD_COUNTER(tx_filtered, deflink.status_stats.filtered);
|
||||
|
||||
- if (local->ops->wake_tx_queue) {
|
||||
- DEBUGFS_ADD(aqm);
|
||||
- DEBUGFS_ADD(airtime);
|
||||
- }
|
||||
+ DEBUGFS_ADD(aqm);
|
||||
+ DEBUGFS_ADD(airtime);
|
||||
|
||||
if (wiphy_ext_feature_isset(local->hw.wiphy,
|
||||
NL80211_EXT_FEATURE_AQL))
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -2290,7 +2290,6 @@ void ieee80211_wake_queue_by_reason(stru
|
||||
void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
enum queue_stop_reason reason,
|
||||
bool refcounted);
|
||||
-void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
|
||||
void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
struct sk_buff *skb);
|
||||
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -458,12 +458,6 @@ static void ieee80211_do_stop(struct iee
|
||||
if (cancel_scan)
|
||||
ieee80211_scan_cancel(local);
|
||||
|
||||
- /*
|
||||
- * Stop TX on this interface first.
|
||||
- */
|
||||
- if (!local->ops->wake_tx_queue && sdata->dev)
|
||||
- netif_tx_stop_all_queues(sdata->dev);
|
||||
-
|
||||
ieee80211_roc_purge(local, sdata);
|
||||
|
||||
switch (sdata->vif.type) {
|
||||
@@ -811,13 +805,6 @@ static void ieee80211_uninit(struct net_
|
||||
ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev));
|
||||
}
|
||||
|
||||
-static u16 ieee80211_netdev_select_queue(struct net_device *dev,
|
||||
- struct sk_buff *skb,
|
||||
- struct net_device *sb_dev)
|
||||
-{
|
||||
- return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
|
||||
-}
|
||||
-
|
||||
static void
|
||||
ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
@@ -831,7 +818,6 @@ static const struct net_device_ops ieee8
|
||||
.ndo_start_xmit = ieee80211_subif_start_xmit,
|
||||
.ndo_set_rx_mode = ieee80211_set_multicast_list,
|
||||
.ndo_set_mac_address = ieee80211_change_mac,
|
||||
- .ndo_select_queue = ieee80211_netdev_select_queue,
|
||||
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||
};
|
||||
|
||||
@@ -939,7 +925,6 @@ static const struct net_device_ops ieee8
|
||||
.ndo_start_xmit = ieee80211_subif_start_xmit_8023,
|
||||
.ndo_set_rx_mode = ieee80211_set_multicast_list,
|
||||
.ndo_set_mac_address = ieee80211_change_mac,
|
||||
- .ndo_select_queue = ieee80211_netdev_select_queue,
|
||||
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||
.ndo_fill_forward_path = ieee80211_netdev_fill_forward_path,
|
||||
};
|
||||
@@ -1441,35 +1426,6 @@ int ieee80211_do_open(struct wireless_de
|
||||
|
||||
ieee80211_recalc_ps(local);
|
||||
|
||||
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
|
||||
- sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
|
||||
- local->ops->wake_tx_queue) {
|
||||
- /* XXX: for AP_VLAN, actually track AP queues */
|
||||
- if (dev)
|
||||
- netif_tx_start_all_queues(dev);
|
||||
- } else if (dev) {
|
||||
- unsigned long flags;
|
||||
- int n_acs = IEEE80211_NUM_ACS;
|
||||
- int ac;
|
||||
-
|
||||
- if (local->hw.queues < IEEE80211_NUM_ACS)
|
||||
- n_acs = 1;
|
||||
-
|
||||
- spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
- if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE ||
|
||||
- (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 &&
|
||||
- skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) {
|
||||
- for (ac = 0; ac < n_acs; ac++) {
|
||||
- int ac_queue = sdata->vif.hw_queue[ac];
|
||||
-
|
||||
- if (local->queue_stop_reasons[ac_queue] == 0 &&
|
||||
- skb_queue_empty(&local->pending[ac_queue]))
|
||||
- netif_start_subqueue(dev, ac);
|
||||
- }
|
||||
- }
|
||||
- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
- }
|
||||
-
|
||||
set_bit(SDATA_STATE_RUNNING, &sdata->state);
|
||||
|
||||
return 0;
|
||||
@@ -1499,17 +1455,12 @@ static void ieee80211_if_setup(struct ne
|
||||
{
|
||||
ether_setup(dev);
|
||||
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
||||
+ dev->priv_flags |= IFF_NO_QUEUE;
|
||||
dev->netdev_ops = &ieee80211_dataif_ops;
|
||||
dev->needs_free_netdev = true;
|
||||
dev->priv_destructor = ieee80211_if_free;
|
||||
}
|
||||
|
||||
-static void ieee80211_if_setup_no_queue(struct net_device *dev)
|
||||
-{
|
||||
- ieee80211_if_setup(dev);
|
||||
- dev->priv_flags |= IFF_NO_QUEUE;
|
||||
-}
|
||||
-
|
||||
static void ieee80211_iface_process_skb(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb)
|
||||
@@ -2094,9 +2045,7 @@ int ieee80211_if_add(struct ieee80211_lo
|
||||
struct net_device *ndev = NULL;
|
||||
struct ieee80211_sub_if_data *sdata = NULL;
|
||||
struct txq_info *txqi;
|
||||
- void (*if_setup)(struct net_device *dev);
|
||||
int ret, i;
|
||||
- int txqs = 1;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
@@ -2119,30 +2068,18 @@ int ieee80211_if_add(struct ieee80211_lo
|
||||
sizeof(void *));
|
||||
int txq_size = 0;
|
||||
|
||||
- if (local->ops->wake_tx_queue &&
|
||||
- type != NL80211_IFTYPE_AP_VLAN &&
|
||||
+ if (type != NL80211_IFTYPE_AP_VLAN &&
|
||||
(type != NL80211_IFTYPE_MONITOR ||
|
||||
(params->flags & MONITOR_FLAG_ACTIVE)))
|
||||
txq_size += sizeof(struct txq_info) +
|
||||
local->hw.txq_data_size;
|
||||
|
||||
- if (local->ops->wake_tx_queue) {
|
||||
- if_setup = ieee80211_if_setup_no_queue;
|
||||
- } else {
|
||||
- if_setup = ieee80211_if_setup;
|
||||
- if (local->hw.queues >= IEEE80211_NUM_ACS)
|
||||
- txqs = IEEE80211_NUM_ACS;
|
||||
- }
|
||||
-
|
||||
ndev = alloc_netdev_mqs(size + txq_size,
|
||||
name, name_assign_type,
|
||||
- if_setup, txqs, 1);
|
||||
+ ieee80211_if_setup, 1, 1);
|
||||
if (!ndev)
|
||||
return -ENOMEM;
|
||||
|
||||
- if (!local->ops->wake_tx_queue && local->hw.wiphy->tx_queue_len)
|
||||
- ndev->tx_queue_len = local->hw.wiphy->tx_queue_len;
|
||||
-
|
||||
dev_net_set(ndev, wiphy_net(local->hw.wiphy));
|
||||
|
||||
ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -630,7 +630,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
|
||||
|
||||
if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config ||
|
||||
!ops->add_interface || !ops->remove_interface ||
|
||||
- !ops->configure_filter))
|
||||
+ !ops->configure_filter || !ops->wake_tx_queue))
|
||||
return NULL;
|
||||
|
||||
if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
|
||||
@@ -719,9 +719,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
|
||||
if (!ops->set_key)
|
||||
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||
|
||||
- if (ops->wake_tx_queue)
|
||||
- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS);
|
||||
-
|
||||
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
|
||||
|
||||
wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
|
||||
@@ -834,10 +832,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
|
||||
atomic_set(&local->agg_queue_stop[i], 0);
|
||||
}
|
||||
tasklet_setup(&local->tx_pending_tasklet, ieee80211_tx_pending);
|
||||
-
|
||||
- if (ops->wake_tx_queue)
|
||||
- tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs);
|
||||
-
|
||||
+ tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs);
|
||||
tasklet_setup(&local->tasklet, ieee80211_tasklet_handler);
|
||||
|
||||
skb_queue_head_init(&local->skb_queue);
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -1571,9 +1571,6 @@ static void sta_ps_start(struct sta_info
|
||||
|
||||
ieee80211_clear_fast_xmit(sta);
|
||||
|
||||
- if (!sta->sta.txq[0])
|
||||
- return;
|
||||
-
|
||||
for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
|
||||
struct ieee80211_txq *txq = sta->sta.txq[tid];
|
||||
struct txq_info *txqi = to_txq_info(txq);
|
||||
--- a/net/mac80211/sta_info.c
|
||||
+++ b/net/mac80211/sta_info.c
|
||||
@@ -140,17 +140,15 @@ static void __cleanup_single_sta(struct
|
||||
atomic_dec(&ps->num_sta_ps);
|
||||
}
|
||||
|
||||
- if (sta->sta.txq[0]) {
|
||||
- for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
|
||||
- struct txq_info *txqi;
|
||||
+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
|
||||
+ struct txq_info *txqi;
|
||||
|
||||
- if (!sta->sta.txq[i])
|
||||
- continue;
|
||||
+ if (!sta->sta.txq[i])
|
||||
+ continue;
|
||||
|
||||
- txqi = to_txq_info(sta->sta.txq[i]);
|
||||
+ txqi = to_txq_info(sta->sta.txq[i]);
|
||||
|
||||
- ieee80211_txq_purge(local, txqi);
|
||||
- }
|
||||
+ ieee80211_txq_purge(local, txqi);
|
||||
}
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
@@ -425,8 +423,7 @@ void sta_info_free(struct ieee80211_loca
|
||||
|
||||
sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
|
||||
|
||||
- if (sta->sta.txq[0])
|
||||
- kfree(to_txq_info(sta->sta.txq[0]));
|
||||
+ kfree(to_txq_info(sta->sta.txq[0]));
|
||||
kfree(rcu_dereference_raw(sta->sta.rates));
|
||||
#ifdef CPTCFG_MAC80211_MESH
|
||||
kfree(sta->mesh);
|
||||
@@ -527,6 +524,8 @@ __sta_info_alloc(struct ieee80211_sub_if
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
struct sta_info *sta;
|
||||
+ void *txq_data;
|
||||
+ int size;
|
||||
int i;
|
||||
|
||||
sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
|
||||
@@ -597,21 +596,18 @@ __sta_info_alloc(struct ieee80211_sub_if
|
||||
|
||||
sta->last_connected = ktime_get_seconds();
|
||||
|
||||
- if (local->ops->wake_tx_queue) {
|
||||
- void *txq_data;
|
||||
- int size = sizeof(struct txq_info) +
|
||||
- ALIGN(hw->txq_data_size, sizeof(void *));
|
||||
+ size = sizeof(struct txq_info) +
|
||||
+ ALIGN(hw->txq_data_size, sizeof(void *));
|
||||
|
||||
- txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
|
||||
- if (!txq_data)
|
||||
- goto free;
|
||||
+ txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
|
||||
+ if (!txq_data)
|
||||
+ goto free;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
|
||||
- struct txq_info *txq = txq_data + i * size;
|
||||
+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
|
||||
+ struct txq_info *txq = txq_data + i * size;
|
||||
|
||||
- /* might not do anything for the bufferable MMPDU TXQ */
|
||||
- ieee80211_txq_init(sdata, sta, txq, i);
|
||||
- }
|
||||
+ /* might not do anything for the (bufferable) MMPDU TXQ */
|
||||
+ ieee80211_txq_init(sdata, sta, txq, i);
|
||||
}
|
||||
|
||||
if (sta_prepare_rate_control(local, sta, gfp))
|
||||
@@ -685,8 +681,7 @@ __sta_info_alloc(struct ieee80211_sub_if
|
||||
return sta;
|
||||
|
||||
free_txq:
|
||||
- if (sta->sta.txq[0])
|
||||
- kfree(to_txq_info(sta->sta.txq[0]));
|
||||
+ kfree(to_txq_info(sta->sta.txq[0]));
|
||||
free:
|
||||
sta_info_free_link(&sta->deflink);
|
||||
#ifdef CPTCFG_MAC80211_MESH
|
||||
@@ -1959,9 +1954,6 @@ ieee80211_sta_ps_deliver_response(struct
|
||||
* TIM recalculation.
|
||||
*/
|
||||
|
||||
- if (!sta->sta.txq[0])
|
||||
- return;
|
||||
-
|
||||
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
|
||||
if (!sta->sta.txq[tid] ||
|
||||
!(driver_release_tids & BIT(tid)) ||
|
||||
@@ -2446,7 +2438,7 @@ static void sta_set_tidstats(struct sta_
|
||||
tidstats->tx_msdu_failed = sta->deflink.status_stats.msdu_failed[tid];
|
||||
}
|
||||
|
||||
- if (local->ops->wake_tx_queue && tid < IEEE80211_NUM_TIDS) {
|
||||
+ if (tid < IEEE80211_NUM_TIDS) {
|
||||
spin_lock_bh(&local->fq.lock);
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -2774,9 +2766,6 @@ unsigned long ieee80211_sta_last_active(
|
||||
|
||||
static void sta_update_codel_params(struct sta_info *sta, u32 thr)
|
||||
{
|
||||
- if (!sta->sdata->local->ops->wake_tx_queue)
|
||||
- return;
|
||||
-
|
||||
if (thr && thr < STA_SLOW_THRESHOLD * sta->local->num_sta) {
|
||||
sta->cparams.target = MS2TIME(50);
|
||||
sta->cparams.interval = MS2TIME(300);
|
||||
--- a/net/mac80211/tdls.c
|
||||
+++ b/net/mac80211/tdls.c
|
||||
@@ -1016,7 +1016,6 @@ ieee80211_tdls_prep_mgmt_packet(struct w
|
||||
skb->priority = 256 + 5;
|
||||
break;
|
||||
}
|
||||
- skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
|
||||
|
||||
/*
|
||||
* Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress.
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1599,9 +1599,6 @@ int ieee80211_txq_setup_flows(struct iee
|
||||
bool supp_vht = false;
|
||||
enum nl80211_band band;
|
||||
|
||||
- if (!local->ops->wake_tx_queue)
|
||||
- return 0;
|
||||
-
|
||||
ret = fq_init(fq, 4096);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1649,9 +1646,6 @@ void ieee80211_txq_teardown_flows(struct
|
||||
{
|
||||
struct fq *fq = &local->fq;
|
||||
|
||||
- if (!local->ops->wake_tx_queue)
|
||||
- return;
|
||||
-
|
||||
kfree(local->cvars);
|
||||
local->cvars = NULL;
|
||||
|
||||
@@ -1668,8 +1662,7 @@ static bool ieee80211_queue_skb(struct i
|
||||
struct ieee80211_vif *vif;
|
||||
struct txq_info *txqi;
|
||||
|
||||
- if (!local->ops->wake_tx_queue ||
|
||||
- sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
||||
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
||||
return false;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
@@ -4185,12 +4178,7 @@ void __ieee80211_subif_start_xmit(struct
|
||||
if (IS_ERR(sta))
|
||||
sta = NULL;
|
||||
|
||||
- if (local->ops->wake_tx_queue) {
|
||||
- u16 queue = __ieee80211_select_queue(sdata, sta, skb);
|
||||
- skb_set_queue_mapping(skb, queue);
|
||||
- skb_get_hash(skb);
|
||||
- }
|
||||
-
|
||||
+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
|
||||
ieee80211_aggr_check(sdata, sta, skb);
|
||||
|
||||
sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
|
||||
@@ -4501,11 +4489,7 @@ static void ieee80211_8023_xmit(struct i
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
u8 tid;
|
||||
|
||||
- if (local->ops->wake_tx_queue) {
|
||||
- u16 queue = __ieee80211_select_queue(sdata, sta, skb);
|
||||
- skb_set_queue_mapping(skb, queue);
|
||||
- skb_get_hash(skb);
|
||||
- }
|
||||
+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
|
||||
|
||||
if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
|
||||
test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
|
||||
@@ -4759,9 +4743,6 @@ void ieee80211_tx_pending(struct tasklet
|
||||
if (!txok)
|
||||
break;
|
||||
}
|
||||
-
|
||||
- if (skb_queue_empty(&local->pending[i]))
|
||||
- ieee80211_propagate_queue_wake(local, i);
|
||||
}
|
||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
|
||||
@@ -5954,10 +5935,9 @@ int ieee80211_tx_control_port(struct wip
|
||||
}
|
||||
|
||||
if (!IS_ERR(sta)) {
|
||||
- u16 queue = __ieee80211_select_queue(sdata, sta, skb);
|
||||
+ u16 queue = ieee80211_select_queue(sdata, sta, skb);
|
||||
|
||||
skb_set_queue_mapping(skb, queue);
|
||||
- skb_get_hash(skb);
|
||||
|
||||
/*
|
||||
* for MLO STA, the SA should be the AP MLD address, but
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -446,39 +446,6 @@ void ieee80211_wake_txqs(struct tasklet_
|
||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
}
|
||||
|
||||
-void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
|
||||
-{
|
||||
- struct ieee80211_sub_if_data *sdata;
|
||||
- int n_acs = IEEE80211_NUM_ACS;
|
||||
-
|
||||
- if (local->ops->wake_tx_queue)
|
||||
- return;
|
||||
-
|
||||
- if (local->hw.queues < IEEE80211_NUM_ACS)
|
||||
- n_acs = 1;
|
||||
-
|
||||
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
- int ac;
|
||||
-
|
||||
- if (!sdata->dev)
|
||||
- continue;
|
||||
-
|
||||
- if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE &&
|
||||
- local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
|
||||
- continue;
|
||||
-
|
||||
- for (ac = 0; ac < n_acs; ac++) {
|
||||
- int ac_queue = sdata->vif.hw_queue[ac];
|
||||
-
|
||||
- if (ac_queue == queue ||
|
||||
- (sdata->vif.cab_queue == queue &&
|
||||
- local->queue_stop_reasons[ac_queue] == 0 &&
|
||||
- skb_queue_empty(&local->pending[ac_queue])))
|
||||
- netif_wake_subqueue(sdata->dev, ac);
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
|
||||
enum queue_stop_reason reason,
|
||||
bool refcounted,
|
||||
@@ -509,11 +476,7 @@ static void __ieee80211_wake_queue(struc
|
||||
/* someone still has this queue stopped */
|
||||
return;
|
||||
|
||||
- if (skb_queue_empty(&local->pending[queue])) {
|
||||
- rcu_read_lock();
|
||||
- ieee80211_propagate_queue_wake(local, queue);
|
||||
- rcu_read_unlock();
|
||||
- } else
|
||||
+ if (!skb_queue_empty(&local->pending[queue]))
|
||||
tasklet_schedule(&local->tx_pending_tasklet);
|
||||
|
||||
/*
|
||||
@@ -523,12 +486,10 @@ static void __ieee80211_wake_queue(struc
|
||||
* release someone's lock, but it is fine because all the callers of
|
||||
* __ieee80211_wake_queue call it right before releasing the lock.
|
||||
*/
|
||||
- if (local->ops->wake_tx_queue) {
|
||||
- if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
|
||||
- tasklet_schedule(&local->wake_txqs_tasklet);
|
||||
- else
|
||||
- _ieee80211_wake_txqs(local, flags);
|
||||
- }
|
||||
+ if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
|
||||
+ tasklet_schedule(&local->wake_txqs_tasklet);
|
||||
+ else
|
||||
+ _ieee80211_wake_txqs(local, flags);
|
||||
}
|
||||
|
||||
void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
@@ -585,10 +546,6 @@ static void __ieee80211_stop_queue(struc
|
||||
for (ac = 0; ac < n_acs; ac++) {
|
||||
if (sdata->vif.hw_queue[ac] == queue ||
|
||||
sdata->vif.cab_queue == queue) {
|
||||
- if (!local->ops->wake_tx_queue) {
|
||||
- netif_stop_subqueue(sdata->dev, ac);
|
||||
- continue;
|
||||
- }
|
||||
spin_lock(&local->fq.lock);
|
||||
sdata->vif.txqs_stopped[ac] = true;
|
||||
spin_unlock(&local->fq.lock);
|
||||
--- a/net/mac80211/wme.c
|
||||
+++ b/net/mac80211/wme.c
|
||||
@@ -122,6 +122,9 @@ u16 ieee80211_select_queue_80211(struct
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
u8 *p;
|
||||
|
||||
+ /* Ensure hash is set prior to potential SW encryption */
|
||||
+ skb_get_hash(skb);
|
||||
+
|
||||
if ((info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER) ||
|
||||
local->hw.queues < IEEE80211_NUM_ACS)
|
||||
return 0;
|
||||
@@ -141,12 +144,15 @@ u16 ieee80211_select_queue_80211(struct
|
||||
return ieee80211_downgrade_queue(sdata, NULL, skb);
|
||||
}
|
||||
|
||||
-u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
||||
- struct sta_info *sta, struct sk_buff *skb)
|
||||
+u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct sta_info *sta, struct sk_buff *skb)
|
||||
{
|
||||
struct mac80211_qos_map *qos_map;
|
||||
bool qos;
|
||||
|
||||
+ /* Ensure hash is set prior to potential SW encryption */
|
||||
+ skb_get_hash(skb);
|
||||
+
|
||||
/* all mesh/ocb stations are required to support WME */
|
||||
if (sta && (sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
|
||||
sdata->vif.type == NL80211_IFTYPE_OCB))
|
||||
@@ -176,59 +182,6 @@ u16 __ieee80211_select_queue(struct ieee
|
||||
return ieee80211_downgrade_queue(sdata, sta, skb);
|
||||
}
|
||||
|
||||
-
|
||||
-/* Indicate which queue to use. */
|
||||
-u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
||||
- struct sk_buff *skb)
|
||||
-{
|
||||
- struct ieee80211_local *local = sdata->local;
|
||||
- struct sta_info *sta = NULL;
|
||||
- const u8 *ra = NULL;
|
||||
- u16 ret;
|
||||
-
|
||||
- /* when using iTXQ, we can do this later */
|
||||
- if (local->ops->wake_tx_queue)
|
||||
- return 0;
|
||||
-
|
||||
- if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
|
||||
- skb->priority = 0; /* required for correct WPA/11i MIC */
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- rcu_read_lock();
|
||||
- switch (sdata->vif.type) {
|
||||
- case NL80211_IFTYPE_AP_VLAN:
|
||||
- sta = rcu_dereference(sdata->u.vlan.sta);
|
||||
- if (sta)
|
||||
- break;
|
||||
- fallthrough;
|
||||
- case NL80211_IFTYPE_AP:
|
||||
- ra = skb->data;
|
||||
- break;
|
||||
- case NL80211_IFTYPE_STATION:
|
||||
- /* might be a TDLS station */
|
||||
- sta = sta_info_get(sdata, skb->data);
|
||||
- if (sta)
|
||||
- break;
|
||||
-
|
||||
- ra = sdata->deflink.u.mgd.bssid;
|
||||
- break;
|
||||
- case NL80211_IFTYPE_ADHOC:
|
||||
- ra = skb->data;
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (!sta && ra && !is_multicast_ether_addr(ra))
|
||||
- sta = sta_info_get(sdata, ra);
|
||||
-
|
||||
- ret = __ieee80211_select_queue(sdata, sta, skb);
|
||||
-
|
||||
- rcu_read_unlock();
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
/**
|
||||
* ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
|
||||
*
|
||||
--- a/net/mac80211/wme.h
|
||||
+++ b/net/mac80211/wme.h
|
||||
@@ -13,10 +13,8 @@
|
||||
u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_hdr *hdr);
|
||||
-u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
||||
- struct sta_info *sta, struct sk_buff *skb);
|
||||
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
||||
- struct sk_buff *skb);
|
||||
+ struct sta_info *sta, struct sk_buff *skb);
|
||||
void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb);
|
||||
|
@ -0,0 +1,32 @@
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Mon, 10 Oct 2022 19:17:46 +0200
|
||||
Subject: [PATCH] wifi: realtek: remove duplicated wake_tx_queue
|
||||
|
||||
By accident, the previous patch duplicated the initialization
|
||||
of the wake_tx_queue callback. Fix that by removing the new
|
||||
initializations.
|
||||
|
||||
Fixes: a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to drivers")
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
|
||||
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
|
||||
@@ -896,7 +896,6 @@ static void rtw_ops_sta_rc_update(struct
|
||||
|
||||
const struct ieee80211_ops rtw_ops = {
|
||||
.tx = rtw_ops_tx,
|
||||
- .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.wake_tx_queue = rtw_ops_wake_tx_queue,
|
||||
.start = rtw_ops_start,
|
||||
.stop = rtw_ops_stop,
|
||||
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
|
||||
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
|
||||
@@ -918,7 +918,6 @@ static int rtw89_ops_set_tid_config(stru
|
||||
|
||||
const struct ieee80211_ops rtw89_ops = {
|
||||
.tx = rtw89_ops_tx,
|
||||
- .wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.wake_tx_queue = rtw89_ops_wake_tx_queue,
|
||||
.start = rtw89_ops_start,
|
||||
.stop = rtw89_ops_stop,
|
@ -1,60 +0,0 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Tue, 14 Dec 2021 17:53:12 +0100
|
||||
Subject: [PATCH] mac80211: use coarse boottime for airtime fairness code
|
||||
|
||||
The time values used by the airtime fairness code only need to be accurate
|
||||
enough to cover station activity detection.
|
||||
Using ktime_get_coarse_boottime_ns instead of ktime_get_boottime_ns will
|
||||
drop the accuracy down to jiffies intervals, but at the same time saves
|
||||
a lot of CPU cycles in a hot path
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3820,7 +3820,7 @@ struct ieee80211_txq *ieee80211_next_txq
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct airtime_sched_info *air_sched;
|
||||
- u64 now = ktime_get_boottime_ns();
|
||||
+ u64 now = ktime_get_coarse_boottime_ns();
|
||||
struct ieee80211_txq *ret = NULL;
|
||||
struct airtime_info *air_info;
|
||||
struct txq_info *txqi = NULL;
|
||||
@@ -3947,7 +3947,7 @@ void ieee80211_update_airtime_weight(str
|
||||
u64 weight_sum = 0;
|
||||
|
||||
if (unlikely(!now))
|
||||
- now = ktime_get_boottime_ns();
|
||||
+ now = ktime_get_coarse_boottime_ns();
|
||||
|
||||
lockdep_assert_held(&air_sched->lock);
|
||||
|
||||
@@ -3973,7 +3973,7 @@ void ieee80211_schedule_txq(struct ieee8
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct txq_info *txqi = to_txq_info(txq);
|
||||
struct airtime_sched_info *air_sched;
|
||||
- u64 now = ktime_get_boottime_ns();
|
||||
+ u64 now = ktime_get_coarse_boottime_ns();
|
||||
struct airtime_info *air_info;
|
||||
u8 ac = txq->ac;
|
||||
bool was_active;
|
||||
@@ -4031,7 +4031,7 @@ static void __ieee80211_unschedule_txq(s
|
||||
|
||||
if (!purge)
|
||||
airtime_set_active(air_sched, air_info,
|
||||
- ktime_get_boottime_ns());
|
||||
+ ktime_get_coarse_boottime_ns());
|
||||
|
||||
rb_erase_cached(&txqi->schedule_order,
|
||||
&air_sched->active_txqs);
|
||||
@@ -4119,7 +4119,7 @@ bool ieee80211_txq_may_transmit(struct i
|
||||
if (RB_EMPTY_NODE(&txqi->schedule_order))
|
||||
goto out;
|
||||
|
||||
- now = ktime_get_boottime_ns();
|
||||
+ now = ktime_get_coarse_boottime_ns();
|
||||
|
||||
/* Like in ieee80211_next_txq(), make sure the first station in the
|
||||
* scheduling order is eligible for transmission to avoid starvation.
|
@ -1,74 +0,0 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Mon, 24 May 2021 11:46:09 +0200
|
||||
Subject: [PATCH] mac80211_hwsim: make 6 GHz channels usable
|
||||
|
||||
The previous commit that claimed to add 6 GHz channels didn't actually make
|
||||
them usable, since the 6 GHz band was not registered with mac80211.
|
||||
|
||||
Fixes: 28881922abd7 ("mac80211_hwsim: add 6GHz channels")
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/mac80211_hwsim.c
|
||||
+++ b/drivers/net/wireless/mac80211_hwsim.c
|
||||
@@ -3008,15 +3008,19 @@ static void mac80211_hwsim_he_capab(stru
|
||||
{
|
||||
u16 n_iftype_data;
|
||||
|
||||
- if (sband->band == NL80211_BAND_2GHZ) {
|
||||
+ switch (sband->band) {
|
||||
+ case NL80211_BAND_2GHZ:
|
||||
n_iftype_data = ARRAY_SIZE(he_capa_2ghz);
|
||||
sband->iftype_data =
|
||||
(struct ieee80211_sband_iftype_data *)he_capa_2ghz;
|
||||
- } else if (sband->band == NL80211_BAND_5GHZ) {
|
||||
+ break;
|
||||
+ case NL80211_BAND_5GHZ:
|
||||
+ case NL80211_BAND_6GHZ:
|
||||
n_iftype_data = ARRAY_SIZE(he_capa_5ghz);
|
||||
sband->iftype_data =
|
||||
(struct ieee80211_sband_iftype_data *)he_capa_5ghz;
|
||||
- } else {
|
||||
+ break;
|
||||
+ default:
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3306,6 +3310,12 @@ static int mac80211_hwsim_new_radio(stru
|
||||
sband->vht_cap.vht_mcs.tx_mcs_map =
|
||||
sband->vht_cap.vht_mcs.rx_mcs_map;
|
||||
break;
|
||||
+ case NL80211_BAND_6GHZ:
|
||||
+ sband->channels = data->channels_6ghz;
|
||||
+ sband->n_channels = ARRAY_SIZE(hwsim_channels_6ghz);
|
||||
+ sband->bitrates = data->rates + 4;
|
||||
+ sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4;
|
||||
+ break;
|
||||
case NL80211_BAND_S1GHZ:
|
||||
memcpy(&sband->s1g_cap, &hwsim_s1g_cap,
|
||||
sizeof(sband->s1g_cap));
|
||||
@@ -3316,6 +3326,13 @@ static int mac80211_hwsim_new_radio(stru
|
||||
continue;
|
||||
}
|
||||
|
||||
+ mac80211_hwsim_he_capab(sband);
|
||||
+
|
||||
+ hw->wiphy->bands[band] = sband;
|
||||
+
|
||||
+ if (band == NL80211_BAND_6GHZ)
|
||||
+ continue;
|
||||
+
|
||||
sband->ht_cap.ht_supported = true;
|
||||
sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
|
||||
IEEE80211_HT_CAP_GRN_FLD |
|
||||
@@ -3329,10 +3346,6 @@ static int mac80211_hwsim_new_radio(stru
|
||||
sband->ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
sband->ht_cap.mcs.rx_mask[1] = 0xff;
|
||||
sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
|
||||
-
|
||||
- mac80211_hwsim_he_capab(sband);
|
||||
-
|
||||
- hw->wiphy->bands[band] = sband;
|
||||
}
|
||||
|
||||
/* By default all radios belong to the first group */
|
@ -1,178 +0,0 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Fri, 12 Nov 2021 12:22:23 +0100
|
||||
Subject: [PATCH] mac80211: add support for .ndo_fill_forward_path
|
||||
|
||||
This allows drivers to provide a destination device + info for flow offload
|
||||
Only supported in combination with 802.3 encap offload
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
Tested-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20211112112223.1209-1-nbd@nbd.name
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -3937,6 +3937,8 @@ struct ieee80211_prep_tx_info {
|
||||
* twt structure.
|
||||
* @twt_teardown_request: Update the hw with TWT teardown request received
|
||||
* from the peer.
|
||||
+ * @net_fill_forward_path: Called from .ndo_fill_forward_path in order to
|
||||
+ * resolve a path for hardware flow offloading
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
@@ -4265,6 +4267,13 @@ struct ieee80211_ops {
|
||||
struct ieee80211_twt_setup *twt);
|
||||
void (*twt_teardown_request)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, u8 flowid);
|
||||
+#if LINUX_VERSION_IS_GEQ(5,10,0)
|
||||
+ int (*net_fill_forward_path)(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_vif *vif,
|
||||
+ struct ieee80211_sta *sta,
|
||||
+ struct net_device_path_ctx *ctx,
|
||||
+ struct net_device_path *path);
|
||||
+#endif
|
||||
};
|
||||
|
||||
/**
|
||||
--- a/net/mac80211/driver-ops.h
|
||||
+++ b/net/mac80211/driver-ops.h
|
||||
@@ -1486,4 +1486,28 @@ static inline void drv_twt_teardown_requ
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
+#if LINUX_VERSION_IS_GEQ(5,10,0)
|
||||
+static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sub_if_data *sdata,
|
||||
+ struct ieee80211_sta *sta,
|
||||
+ struct net_device_path_ctx *ctx,
|
||||
+ struct net_device_path *path)
|
||||
+{
|
||||
+ int ret = -EOPNOTSUPP;
|
||||
+
|
||||
+ sdata = get_bss_sdata(sdata);
|
||||
+ if (!check_sdata_in_driver(sdata))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ trace_drv_net_fill_forward_path(local, sdata, sta);
|
||||
+ if (local->ops->net_fill_forward_path)
|
||||
+ ret = local->ops->net_fill_forward_path(&local->hw,
|
||||
+ &sdata->vif, sta,
|
||||
+ ctx, path);
|
||||
+ trace_drv_return_int(local, ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -1489,7 +1489,7 @@ struct ieee80211_local {
|
||||
};
|
||||
|
||||
static inline struct ieee80211_sub_if_data *
|
||||
-IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
|
||||
+IEEE80211_DEV_TO_SUB_IF(const struct net_device *dev)
|
||||
{
|
||||
return netdev_priv(dev);
|
||||
}
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -822,6 +822,66 @@ static const struct net_device_ops ieee8
|
||||
|
||||
};
|
||||
|
||||
+#if LINUX_VERSION_IS_GEQ(5,10,0)
|
||||
+static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx,
|
||||
+ struct net_device_path *path)
|
||||
+{
|
||||
+ struct ieee80211_sub_if_data *sdata;
|
||||
+ struct ieee80211_local *local;
|
||||
+ struct sta_info *sta;
|
||||
+ int ret = -ENOENT;
|
||||
+
|
||||
+ sdata = IEEE80211_DEV_TO_SUB_IF(ctx->dev);
|
||||
+ local = sdata->local;
|
||||
+
|
||||
+ if (!local->ops->net_fill_forward_path)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ switch (sdata->vif.type) {
|
||||
+ case NL80211_IFTYPE_AP_VLAN:
|
||||
+ sta = rcu_dereference(sdata->u.vlan.sta);
|
||||
+ if (sta)
|
||||
+ break;
|
||||
+ if (sdata->wdev.use_4addr)
|
||||
+ goto out;
|
||||
+ if (is_multicast_ether_addr(ctx->daddr))
|
||||
+ goto out;
|
||||
+ sta = sta_info_get_bss(sdata, ctx->daddr);
|
||||
+ break;
|
||||
+ case NL80211_IFTYPE_AP:
|
||||
+ if (is_multicast_ether_addr(ctx->daddr))
|
||||
+ goto out;
|
||||
+ sta = sta_info_get(sdata, ctx->daddr);
|
||||
+ break;
|
||||
+ case NL80211_IFTYPE_STATION:
|
||||
+ if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
|
||||
+ sta = sta_info_get(sdata, ctx->daddr);
|
||||
+ if (sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
|
||||
+ if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
||||
+ goto out;
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ sta = sta_info_get(sdata, sdata->u.mgd.bssid);
|
||||
+ break;
|
||||
+ default:
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (!sta)
|
||||
+ goto out;
|
||||
+
|
||||
+ ret = drv_net_fill_forward_path(local, sdata, &sta->sta, ctx, path);
|
||||
+out:
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static const struct net_device_ops ieee80211_dataif_8023_ops = {
|
||||
#if LINUX_VERSION_IS_LESS(4,10,0)
|
||||
.ndo_change_mtu = __change_mtu,
|
||||
@@ -839,7 +899,9 @@ static const struct net_device_ops ieee8
|
||||
#else
|
||||
.ndo_get_stats64 = bp_ieee80211_get_stats64,
|
||||
#endif
|
||||
-
|
||||
+#if LINUX_VERSION_IS_GEQ(5,10,0)
|
||||
+ .ndo_fill_forward_path = ieee80211_netdev_fill_forward_path,
|
||||
+#endif
|
||||
};
|
||||
|
||||
static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
|
||||
--- a/net/mac80211/trace.h
|
||||
+++ b/net/mac80211/trace.h
|
||||
@@ -2892,6 +2892,15 @@ TRACE_EVENT(drv_twt_teardown_request,
|
||||
)
|
||||
);
|
||||
|
||||
+#if LINUX_VERSION_IS_GEQ(5,10,0)
|
||||
+DEFINE_EVENT(sta_event, drv_net_fill_forward_path,
|
||||
+ TP_PROTO(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sub_if_data *sdata,
|
||||
+ struct ieee80211_sta *sta),
|
||||
+ TP_ARGS(local, sdata, sta)
|
||||
+);
|
||||
+#endif
|
||||
+
|
||||
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
@ -59,10 +59,10 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
flow = fq_find_fattest_flow(fq);
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -1685,6 +1685,10 @@ enum ieee80211_offload_flags {
|
||||
* write-protected by sdata_lock and local->mtx so holding either is fine
|
||||
* for read access.
|
||||
* @mu_mimo_owner: indicates interface owns MU-MIMO capability
|
||||
@@ -1807,6 +1807,10 @@ struct ieee80211_vif_cfg {
|
||||
* @addr: address of this interface
|
||||
* @p2p: indicates whether this AP or STA interface is a p2p
|
||||
* interface, i.e. a GO or p2p-sta respectively
|
||||
+ * @netdev_features: tx netdev features supported by the hardware for this
|
||||
+ * vif. mac80211 initializes this to hw->netdev_features, and the driver
|
||||
+ * can mask out specific tx features. mac80211 will handle software fixup
|
||||
@ -70,9 +70,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
* @driver_flags: flags/capabilities the driver has for this interface,
|
||||
* these need to be set (or cleared) when the interface is added
|
||||
* or, if supported by the driver, the interface type is changed
|
||||
@@ -1736,6 +1740,7 @@ struct ieee80211_vif {
|
||||
@@ -1848,6 +1852,7 @@ struct ieee80211_vif {
|
||||
|
||||
struct ieee80211_chanctx_conf __rcu *chanctx_conf;
|
||||
struct ieee80211_txq *txq;
|
||||
|
||||
+ netdev_features_t netdev_features;
|
||||
u32 driver_flags;
|
||||
@ -80,8 +80,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -2209,6 +2209,7 @@ int ieee80211_if_add(struct ieee80211_lo
|
||||
ndev->features |= local->hw.netdev_features;
|
||||
@@ -2179,6 +2179,7 @@ int ieee80211_if_add(struct ieee80211_lo
|
||||
ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
|
||||
ndev->hw_features |= ndev->features &
|
||||
MAC80211_SUPPORTED_FEATURES_TX;
|
||||
+ sdata->vif.netdev_features = local->hw.netdev_features;
|
||||
@ -90,7 +90,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1310,7 +1310,11 @@ static struct txq_info *ieee80211_get_tx
|
||||
@@ -1355,7 +1355,11 @@ static struct txq_info *ieee80211_get_tx
|
||||
|
||||
static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb)
|
||||
{
|
||||
@ -103,7 +103,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
}
|
||||
|
||||
static u32 codel_skb_len_func(const struct sk_buff *skb)
|
||||
@@ -3499,47 +3503,71 @@ ieee80211_xmit_fast_finish(struct ieee80
|
||||
@@ -3578,55 +3582,79 @@ ieee80211_xmit_fast_finish(struct ieee80
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
@ -167,8 +167,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+
|
||||
+ consume_skb(skb);
|
||||
+ return segs;
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
- /* after this point (skb is modified) we cannot return false */
|
||||
+ if (skb_needs_linearize(skb, features) && __skb_linearize(skb))
|
||||
+ goto free;
|
||||
+
|
||||
@ -182,9 +183,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+
|
||||
+ if (skb_csum_hwoffload_help(skb, features))
|
||||
+ goto free;
|
||||
}
|
||||
|
||||
- /* after this point (skb is modified) we cannot return false */
|
||||
+ }
|
||||
+
|
||||
+ skb_mark_not_on_list(skb);
|
||||
+ return skb;
|
||||
+
|
||||
@ -207,15 +207,10 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+ int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
|
||||
+ struct ethhdr eth;
|
||||
|
||||
if (skb_shared(skb)) {
|
||||
struct sk_buff *tmp_skb = skb;
|
||||
@@ -3548,12 +3576,12 @@ static bool ieee80211_xmit_fast(struct i
|
||||
kfree_skb(tmp_skb);
|
||||
|
||||
if (!skb)
|
||||
- return true;
|
||||
+ return;
|
||||
}
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
if (unlikely(!skb))
|
||||
- return true;
|
||||
+ return;
|
||||
|
||||
if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) &&
|
||||
ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb))
|
||||
@ -224,7 +219,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
/* will not be crypto-handled beyond what we do here, so use false
|
||||
* as the may-encrypt argument for the resize to not account for
|
||||
@@ -3562,10 +3590,8 @@ static bool ieee80211_xmit_fast(struct i
|
||||
@@ -3635,10 +3663,8 @@ static bool ieee80211_xmit_fast(struct i
|
||||
if (unlikely(ieee80211_skb_resize(sdata, skb,
|
||||
max_t(int, extra_head + hw_headroom -
|
||||
skb_headroom(skb), 0),
|
||||
@ -237,16 +232,16 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
memcpy(ð, skb->data, ETH_HLEN - 2);
|
||||
hdr = skb_push(skb, extra_head);
|
||||
@@ -3579,7 +3605,7 @@ static bool ieee80211_xmit_fast(struct i
|
||||
@@ -3652,7 +3678,7 @@ static bool ieee80211_xmit_fast(struct i
|
||||
info->control.vif = &sdata->vif;
|
||||
info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
|
||||
IEEE80211_TX_CTL_DONTFRAG |
|
||||
- (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
|
||||
+ (ampdu ? IEEE80211_TX_CTL_AMPDU : 0);
|
||||
info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
|
||||
|
||||
#ifdef CPTCFG_MAC80211_DEBUGFS
|
||||
@@ -3601,16 +3627,14 @@ static bool ieee80211_xmit_fast(struct i
|
||||
info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT |
|
||||
u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
|
||||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
@@ -3676,16 +3702,14 @@ static bool ieee80211_xmit_fast(struct i
|
||||
tx.key = fast_tx->key;
|
||||
|
||||
if (ieee80211_queue_skb(local, sdata, sta, skb))
|
||||
@ -266,7 +261,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
sdata = container_of(sdata->bss,
|
||||
@@ -3618,6 +3642,55 @@ static bool ieee80211_xmit_fast(struct i
|
||||
@@ -3693,6 +3717,56 @@ static bool ieee80211_xmit_fast(struct i
|
||||
|
||||
__skb_queue_tail(&tx.skbs, skb);
|
||||
ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false);
|
||||
@ -310,6 +305,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* after this point (skb is modified) we cannot return false */
|
||||
+ skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
|
||||
+ if (!skb)
|
||||
+ return true;
|
||||
@ -322,7 +318,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4123,31 +4196,14 @@ void __ieee80211_subif_start_xmit(struct
|
||||
@@ -4193,31 +4267,14 @@ void __ieee80211_subif_start_xmit(struct
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -362,7 +358,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
}
|
||||
|
||||
skb_list_walk_safe(skb, skb, next) {
|
||||
@@ -4310,9 +4366,11 @@ netdev_tx_t ieee80211_subif_start_xmit(s
|
||||
@@ -4435,9 +4492,11 @@ normal:
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
@ -377,7 +373,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_tx_control control = {};
|
||||
@@ -4321,14 +4379,6 @@ static bool ieee80211_tx_8023(struct iee
|
||||
@@ -4446,14 +4505,6 @@ static bool ieee80211_tx_8023(struct iee
|
||||
unsigned long flags;
|
||||
int q = info->hw_queue;
|
||||
|
||||
@ -392,7 +388,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
|
||||
if (local->queue_stop_reasons[q] ||
|
||||
@@ -4355,27 +4405,50 @@ static bool ieee80211_tx_8023(struct iee
|
||||
@@ -4480,6 +4531,26 @@ static bool ieee80211_tx_8023(struct iee
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -419,9 +415,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
|
||||
struct net_device *dev, struct sta_info *sta,
|
||||
struct ieee80211_key *key, struct sk_buff *skb)
|
||||
{
|
||||
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
+ struct ieee80211_tx_info *info;
|
||||
@@ -4487,9 +4558,13 @@ static void ieee80211_8023_xmit(struct i
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
+ struct sk_buff *seg, *next;
|
||||
@ -429,25 +424,23 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+ u16 queue;
|
||||
u8 tid;
|
||||
|
||||
if (local->ops->wake_tx_queue) {
|
||||
- u16 queue = __ieee80211_select_queue(sdata, sta, skb);
|
||||
+ queue = __ieee80211_select_queue(sdata, sta, skb);
|
||||
skb_set_queue_mapping(skb, queue);
|
||||
skb_get_hash(skb);
|
||||
+ } else {
|
||||
+ queue = skb_get_queue_mapping(skb);
|
||||
}
|
||||
- skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
|
||||
+ queue = ieee80211_select_queue(sdata, sta, skb);
|
||||
+ skb_set_queue_mapping(skb, queue);
|
||||
|
||||
if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
|
||||
test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
|
||||
goto out_free;
|
||||
@@ -4499,9 +4574,6 @@ static void ieee80211_8023_xmit(struct i
|
||||
if (unlikely(!skb))
|
||||
return;
|
||||
|
||||
- info = IEEE80211_SKB_CB(skb);
|
||||
- memset(info, 0, sizeof(*info));
|
||||
-
|
||||
ieee80211_aggr_check(sdata, sta, skb);
|
||||
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
@@ -4387,22 +4460,20 @@ static void ieee80211_8023_xmit(struct i
|
||||
@@ -4515,22 +4587,20 @@ static void ieee80211_8023_xmit(struct i
|
||||
return;
|
||||
}
|
||||
|
||||
@ -472,13 +465,13 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
- dev_sw_netstats_tx_add(dev, 1, skb->len);
|
||||
-
|
||||
- sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
|
||||
- sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
|
||||
- sta->deflink.tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
|
||||
- sta->deflink.tx_stats.packets[skb_get_queue_mapping(skb)]++;
|
||||
+ info->hw_queue = sdata->vif.hw_queue[queue];
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
sdata = container_of(sdata->bss,
|
||||
@@ -4414,6 +4485,24 @@ static void ieee80211_8023_xmit(struct i
|
||||
@@ -4542,6 +4612,24 @@ static void ieee80211_8023_xmit(struct i
|
||||
if (key)
|
||||
info->control.hw_key = &key->conf;
|
||||
|
||||
@ -495,15 +488,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
+ &info->flags, NULL);
|
||||
+
|
||||
+ dev_sw_netstats_tx_add(dev, skbs, len);
|
||||
+ sta->tx_stats.packets[queue] += skbs;
|
||||
+ sta->tx_stats.bytes[queue] += len;
|
||||
+ sta->deflink.tx_stats.packets[queue] += skbs;
|
||||
+ sta->deflink.tx_stats.bytes[queue] += len;
|
||||
+
|
||||
+ ieee80211_tpt_led_trig_tx(local, len);
|
||||
+
|
||||
ieee80211_tx_8023(sdata, skb, sta, false);
|
||||
|
||||
return;
|
||||
@@ -4455,6 +4544,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8
|
||||
@@ -4583,6 +4671,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8
|
||||
key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
|
||||
goto skip_offload;
|
||||
|
@ -1,262 +0,0 @@
|
||||
From: Aloka Dixit <alokad@codeaurora.org>
|
||||
Date: Tue, 5 Oct 2021 21:09:36 -0700
|
||||
Subject: [PATCH] mac80211: split beacon retrieval functions
|
||||
|
||||
Split __ieee80211_beacon_get() into a separate function for AP mode
|
||||
ieee80211_beacon_get_ap().
|
||||
Also, move the code common to all modes (AP, adhoc and mesh) to
|
||||
a separate function ieee80211_beacon_get_finish().
|
||||
|
||||
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
|
||||
Link: https://lore.kernel.org/r/20211006040938.9531-2-alokad@codeaurora.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -4987,6 +4987,115 @@ static int ieee80211_beacon_protect(stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void
|
||||
+ieee80211_beacon_get_finish(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_vif *vif,
|
||||
+ struct ieee80211_mutable_offsets *offs,
|
||||
+ struct beacon_data *beacon,
|
||||
+ struct sk_buff *skb,
|
||||
+ struct ieee80211_chanctx_conf *chanctx_conf,
|
||||
+ u16 csa_off_base)
|
||||
+{
|
||||
+ struct ieee80211_local *local = hw_to_local(hw);
|
||||
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
+ struct ieee80211_tx_info *info;
|
||||
+ enum nl80211_band band;
|
||||
+ struct ieee80211_tx_rate_control txrc;
|
||||
+
|
||||
+ /* CSA offsets */
|
||||
+ if (offs && beacon) {
|
||||
+ u16 i;
|
||||
+
|
||||
+ for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) {
|
||||
+ u16 csa_off = beacon->cntdwn_counter_offsets[i];
|
||||
+
|
||||
+ if (!csa_off)
|
||||
+ continue;
|
||||
+
|
||||
+ offs->cntdwn_counter_offs[i] = csa_off_base + csa_off;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ band = chanctx_conf->def.chan->band;
|
||||
+ info = IEEE80211_SKB_CB(skb);
|
||||
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
+ info->band = band;
|
||||
+
|
||||
+ memset(&txrc, 0, sizeof(txrc));
|
||||
+ txrc.hw = hw;
|
||||
+ txrc.sband = local->hw.wiphy->bands[band];
|
||||
+ txrc.bss_conf = &sdata->vif.bss_conf;
|
||||
+ txrc.skb = skb;
|
||||
+ txrc.reported_rate.idx = -1;
|
||||
+ if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band])
|
||||
+ txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band];
|
||||
+ else
|
||||
+ txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
|
||||
+ txrc.bss = true;
|
||||
+ rate_control_get_rate(sdata, NULL, &txrc);
|
||||
+
|
||||
+ info->control.vif = vif;
|
||||
+ info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
|
||||
+ IEEE80211_TX_CTL_ASSIGN_SEQ |
|
||||
+ IEEE80211_TX_CTL_FIRST_FRAGMENT;
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *
|
||||
+ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_vif *vif,
|
||||
+ struct ieee80211_mutable_offsets *offs,
|
||||
+ bool is_template,
|
||||
+ struct beacon_data *beacon,
|
||||
+ struct ieee80211_chanctx_conf *chanctx_conf)
|
||||
+{
|
||||
+ struct ieee80211_local *local = hw_to_local(hw);
|
||||
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
+ struct ieee80211_if_ap *ap = &sdata->u.ap;
|
||||
+ struct sk_buff *skb = NULL;
|
||||
+ u16 csa_off_base = 0;
|
||||
+
|
||||
+ if (beacon->cntdwn_counter_offsets[0]) {
|
||||
+ if (!is_template)
|
||||
+ ieee80211_beacon_update_cntdwn(vif);
|
||||
+
|
||||
+ ieee80211_set_beacon_cntdwn(sdata, beacon);
|
||||
+ }
|
||||
+
|
||||
+ /* headroom, head length,
|
||||
+ * tail length and maximum TIM length
|
||||
+ */
|
||||
+ skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
|
||||
+ beacon->tail_len + 256 +
|
||||
+ local->hw.extra_beacon_tailroom);
|
||||
+ if (!skb)
|
||||
+ return NULL;
|
||||
+
|
||||
+ skb_reserve(skb, local->tx_headroom);
|
||||
+ skb_put_data(skb, beacon->head, beacon->head_len);
|
||||
+
|
||||
+ ieee80211_beacon_add_tim(sdata, &ap->ps, skb, is_template);
|
||||
+
|
||||
+ if (offs) {
|
||||
+ offs->tim_offset = beacon->head_len;
|
||||
+ offs->tim_length = skb->len - beacon->head_len;
|
||||
+ offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
|
||||
+
|
||||
+ /* for AP the csa offsets are from tail */
|
||||
+ csa_off_base = skb->len;
|
||||
+ }
|
||||
+
|
||||
+ if (beacon->tail)
|
||||
+ skb_put_data(skb, beacon->tail, beacon->tail_len);
|
||||
+
|
||||
+ if (ieee80211_beacon_protect(skb, local, sdata) < 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, chanctx_conf,
|
||||
+ csa_off_base);
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
static struct sk_buff *
|
||||
__ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
@@ -4996,12 +5105,8 @@ __ieee80211_beacon_get(struct ieee80211_
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct beacon_data *beacon = NULL;
|
||||
struct sk_buff *skb = NULL;
|
||||
- struct ieee80211_tx_info *info;
|
||||
struct ieee80211_sub_if_data *sdata = NULL;
|
||||
- enum nl80211_band band;
|
||||
- struct ieee80211_tx_rate_control txrc;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
- int csa_off_base = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -5018,48 +5123,11 @@ __ieee80211_beacon_get(struct ieee80211_
|
||||
struct ieee80211_if_ap *ap = &sdata->u.ap;
|
||||
|
||||
beacon = rcu_dereference(ap->beacon);
|
||||
- if (beacon) {
|
||||
- if (beacon->cntdwn_counter_offsets[0]) {
|
||||
- if (!is_template)
|
||||
- ieee80211_beacon_update_cntdwn(vif);
|
||||
-
|
||||
- ieee80211_set_beacon_cntdwn(sdata, beacon);
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * headroom, head length,
|
||||
- * tail length and maximum TIM length
|
||||
- */
|
||||
- skb = dev_alloc_skb(local->tx_headroom +
|
||||
- beacon->head_len +
|
||||
- beacon->tail_len + 256 +
|
||||
- local->hw.extra_beacon_tailroom);
|
||||
- if (!skb)
|
||||
- goto out;
|
||||
-
|
||||
- skb_reserve(skb, local->tx_headroom);
|
||||
- skb_put_data(skb, beacon->head, beacon->head_len);
|
||||
-
|
||||
- ieee80211_beacon_add_tim(sdata, &ap->ps, skb,
|
||||
- is_template);
|
||||
-
|
||||
- if (offs) {
|
||||
- offs->tim_offset = beacon->head_len;
|
||||
- offs->tim_length = skb->len - beacon->head_len;
|
||||
- offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
|
||||
-
|
||||
- /* for AP the csa offsets are from tail */
|
||||
- csa_off_base = skb->len;
|
||||
- }
|
||||
-
|
||||
- if (beacon->tail)
|
||||
- skb_put_data(skb, beacon->tail,
|
||||
- beacon->tail_len);
|
||||
-
|
||||
- if (ieee80211_beacon_protect(skb, local, sdata) < 0)
|
||||
- goto out;
|
||||
- } else
|
||||
+ if (!beacon)
|
||||
goto out;
|
||||
+
|
||||
+ skb = ieee80211_beacon_get_ap(hw, vif, offs, is_template,
|
||||
+ beacon, chanctx_conf);
|
||||
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
|
||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
struct ieee80211_hdr *hdr;
|
||||
@@ -5085,6 +5153,9 @@ __ieee80211_beacon_get(struct ieee80211_
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
IEEE80211_STYPE_BEACON);
|
||||
+
|
||||
+ ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb,
|
||||
+ chanctx_conf, 0);
|
||||
} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
|
||||
@@ -5124,51 +5195,13 @@ __ieee80211_beacon_get(struct ieee80211_
|
||||
}
|
||||
|
||||
skb_put_data(skb, beacon->tail, beacon->tail_len);
|
||||
+ ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb,
|
||||
+ chanctx_conf, 0);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
- /* CSA offsets */
|
||||
- if (offs && beacon) {
|
||||
- int i;
|
||||
-
|
||||
- for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) {
|
||||
- u16 csa_off = beacon->cntdwn_counter_offsets[i];
|
||||
-
|
||||
- if (!csa_off)
|
||||
- continue;
|
||||
-
|
||||
- offs->cntdwn_counter_offs[i] = csa_off_base + csa_off;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- band = chanctx_conf->def.chan->band;
|
||||
-
|
||||
- info = IEEE80211_SKB_CB(skb);
|
||||
-
|
||||
- info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||
- info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
- info->band = band;
|
||||
-
|
||||
- memset(&txrc, 0, sizeof(txrc));
|
||||
- txrc.hw = hw;
|
||||
- txrc.sband = local->hw.wiphy->bands[band];
|
||||
- txrc.bss_conf = &sdata->vif.bss_conf;
|
||||
- txrc.skb = skb;
|
||||
- txrc.reported_rate.idx = -1;
|
||||
- if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band])
|
||||
- txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band];
|
||||
- else
|
||||
- txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
|
||||
- txrc.bss = true;
|
||||
- rate_control_get_rate(sdata, NULL, &txrc);
|
||||
-
|
||||
- info->control.vif = vif;
|
||||
-
|
||||
- info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
|
||||
- IEEE80211_TX_CTL_ASSIGN_SEQ |
|
||||
- IEEE80211_TX_CTL_FIRST_FRAGMENT;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return skb;
|
@ -1,493 +0,0 @@
|
||||
From: John Crispin <john@phrozen.org>
|
||||
Date: Wed, 15 Sep 2021 19:54:34 -0700
|
||||
Subject: [PATCH] nl80211: MBSSID and EMA support in AP mode
|
||||
|
||||
Add new attributes to configure support for multiple BSSID
|
||||
and advanced multi-BSSID advertisements (EMA) in AP mode.
|
||||
|
||||
- NL80211_ATTR_MBSSID_CONFIG used for per interface configuration.
|
||||
- NL80211_ATTR_MBSSID_ELEMS used to MBSSID elements for beacons.
|
||||
|
||||
Memory for the elements is allocated dynamically. This change frees
|
||||
the memory in existing functions which call nl80211_parse_beacon(),
|
||||
a comment is added to indicate the new references to do the same.
|
||||
|
||||
Signed-off-by: John Crispin <john@phrozen.org>
|
||||
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
|
||||
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
|
||||
Link: https://lore.kernel.org/r/20210916025437.29138-2-alokad@codeaurora.org
|
||||
[don't leave ERR_PTR hanging around]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -1046,6 +1046,36 @@ struct cfg80211_crypto_settings {
|
||||
};
|
||||
|
||||
/**
|
||||
+ * struct cfg80211_mbssid_config - AP settings for multi bssid
|
||||
+ *
|
||||
+ * @tx_wdev: pointer to the transmitted interface in the MBSSID set
|
||||
+ * @index: index of this AP in the multi bssid group.
|
||||
+ * @ema: set to true if the beacons should be sent out in EMA mode.
|
||||
+ */
|
||||
+struct cfg80211_mbssid_config {
|
||||
+ struct wireless_dev *tx_wdev;
|
||||
+ u8 index;
|
||||
+ bool ema;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct cfg80211_mbssid_elems - Multiple BSSID elements
|
||||
+ *
|
||||
+ * @cnt: Number of elements in array %elems.
|
||||
+ *
|
||||
+ * @elem: Array of multiple BSSID element(s) to be added into Beacon frames.
|
||||
+ * @elem.data: Data for multiple BSSID elements.
|
||||
+ * @elem.len: Length of data.
|
||||
+ */
|
||||
+struct cfg80211_mbssid_elems {
|
||||
+ u8 cnt;
|
||||
+ struct {
|
||||
+ const u8 *data;
|
||||
+ size_t len;
|
||||
+ } elem[];
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
* struct cfg80211_beacon_data - beacon data
|
||||
* @head: head portion of beacon (before TIM IE)
|
||||
* or %NULL if not changed
|
||||
@@ -1063,6 +1093,7 @@ struct cfg80211_crypto_settings {
|
||||
* @assocresp_ies_len: length of assocresp_ies in octets
|
||||
* @probe_resp_len: length of probe response template (@probe_resp)
|
||||
* @probe_resp: probe response template (AP mode only)
|
||||
+ * @mbssid_ies: multiple BSSID elements
|
||||
* @ftm_responder: enable FTM responder functionality; -1 for no change
|
||||
* (which also implies no change in LCI/civic location data)
|
||||
* @lci: Measurement Report element content, starting with Measurement Token
|
||||
@@ -1080,6 +1111,7 @@ struct cfg80211_beacon_data {
|
||||
const u8 *probe_resp;
|
||||
const u8 *lci;
|
||||
const u8 *civicloc;
|
||||
+ struct cfg80211_mbssid_elems *mbssid_ies;
|
||||
s8 ftm_responder;
|
||||
|
||||
size_t head_len, tail_len;
|
||||
@@ -1194,6 +1226,7 @@ enum cfg80211_ap_settings_flags {
|
||||
* @he_oper: HE operation IE (or %NULL if HE isn't enabled)
|
||||
* @fils_discovery: FILS discovery transmission parameters
|
||||
* @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
|
||||
+ * @mbssid_config: AP settings for multiple bssid
|
||||
*/
|
||||
struct cfg80211_ap_settings {
|
||||
struct cfg80211_chan_def chandef;
|
||||
@@ -1226,6 +1259,7 @@ struct cfg80211_ap_settings {
|
||||
struct cfg80211_he_bss_color he_bss_color;
|
||||
struct cfg80211_fils_discovery fils_discovery;
|
||||
struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
|
||||
+ struct cfg80211_mbssid_config mbssid_config;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -4986,6 +5020,13 @@ struct wiphy_iftype_akm_suites {
|
||||
* %NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes
|
||||
* @sar_capa: SAR control capabilities
|
||||
* @rfkill: a pointer to the rfkill structure
|
||||
+ *
|
||||
+ * @mbssid_max_interfaces: maximum number of interfaces supported by the driver
|
||||
+ * in a multiple BSSID set. This field must be set to a non-zero value
|
||||
+ * by the driver to advertise MBSSID support.
|
||||
+ * @mbssid_max_ema_profile_periodicity: maximum profile periodicity supported by
|
||||
+ * the driver. Setting this field to a non-zero value indicates that the
|
||||
+ * driver supports enhanced multi-BSSID advertisements (EMA AP).
|
||||
*/
|
||||
struct wiphy {
|
||||
struct mutex mtx;
|
||||
@@ -5133,6 +5174,9 @@ struct wiphy {
|
||||
|
||||
struct rfkill *rfkill;
|
||||
|
||||
+ u8 mbssid_max_interfaces;
|
||||
+ u8 ema_max_profile_periodicity;
|
||||
+
|
||||
char priv[] __aligned(NETDEV_ALIGN);
|
||||
};
|
||||
|
||||
--- a/include/uapi/linux/nl80211.h
|
||||
+++ b/include/uapi/linux/nl80211.h
|
||||
@@ -337,7 +337,10 @@
|
||||
* @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes
|
||||
* %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from
|
||||
* userspace to request deletion of a virtual interface, then requires
|
||||
- * attribute %NL80211_ATTR_IFINDEX.
|
||||
+ * attribute %NL80211_ATTR_IFINDEX. If multiple BSSID advertisements are
|
||||
+ * enabled using %NL80211_ATTR_MBSSID_CONFIG, %NL80211_ATTR_MBSSID_ELEMS,
|
||||
+ * and if this command is used for the transmitting interface, then all
|
||||
+ * the non-transmitting interfaces are deleted as well.
|
||||
*
|
||||
* @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
|
||||
* by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
|
||||
@@ -2593,6 +2596,18 @@ enum nl80211_commands {
|
||||
* @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
|
||||
* information for the time while performing a color switch.
|
||||
*
|
||||
+ * @NL80211_ATTR_MBSSID_CONFIG: Nested attribute for multiple BSSID
|
||||
+ * advertisements (MBSSID) parameters in AP mode.
|
||||
+ * Kernel uses this attribute to indicate the driver's support for MBSSID
|
||||
+ * and enhanced multi-BSSID advertisements (EMA AP) to the userspace.
|
||||
+ * Userspace should use this attribute to configure per interface MBSSID
|
||||
+ * parameters.
|
||||
+ * See &enum nl80211_mbssid_config_attributes for details.
|
||||
+ *
|
||||
+ * @NL80211_ATTR_MBSSID_ELEMS: Nested parameter to pass multiple BSSID elements.
|
||||
+ * Mandatory parameter for the transmitting interface to enable MBSSID.
|
||||
+ * Optional for the non-transmitting interfaces.
|
||||
+ *
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@@ -3096,6 +3111,9 @@ enum nl80211_attrs {
|
||||
NL80211_ATTR_COLOR_CHANGE_COLOR,
|
||||
NL80211_ATTR_COLOR_CHANGE_ELEMS,
|
||||
|
||||
+ NL80211_ATTR_MBSSID_CONFIG,
|
||||
+ NL80211_ATTR_MBSSID_ELEMS,
|
||||
+
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@@ -7349,4 +7367,60 @@ enum nl80211_sar_specs_attrs {
|
||||
NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1,
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced
|
||||
+ * multi-BSSID advertisements (EMA) in AP mode.
|
||||
+ * Kernel uses some of these attributes to advertise driver's support for
|
||||
+ * MBSSID and EMA.
|
||||
+ * Remaining attributes should be used by the userspace to configure the
|
||||
+ * features.
|
||||
+ *
|
||||
+ * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid
|
||||
+ *
|
||||
+ * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise
|
||||
+ * the maximum number of MBSSID interfaces supported by the driver.
|
||||
+ * Driver should indicate MBSSID support by setting
|
||||
+ * wiphy->mbssid_max_interfaces to a value more than or equal to 2.
|
||||
+ *
|
||||
+ * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel
|
||||
+ * to advertise the maximum profile periodicity supported by the driver
|
||||
+ * if EMA is enabled. Driver should indicate EMA support to the userspace
|
||||
+ * by setting wiphy->mbssid_max_ema_profile_periodicity to
|
||||
+ * a non-zero value.
|
||||
+ *
|
||||
+ * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of
|
||||
+ * this BSS (u8) in the multiple BSSID set.
|
||||
+ * Value must be set to 0 for the transmitting interface and non-zero for
|
||||
+ * all non-transmitting interfaces. The userspace will be responsible
|
||||
+ * for using unique indices for the interfaces.
|
||||
+ * Range: 0 to wiphy->mbssid_max_interfaces-1.
|
||||
+ *
|
||||
+ * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for
|
||||
+ * a non-transmitted profile which provides the interface index (u32) of
|
||||
+ * the transmitted profile. The value must match one of the interface
|
||||
+ * indices advertised by the kernel. Optional if the interface being set up
|
||||
+ * is the transmitting one, however, if provided then the value must match
|
||||
+ * the interface index of the same.
|
||||
+ *
|
||||
+ * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature.
|
||||
+ * Setting this flag is permitted only if the driver advertises EMA support
|
||||
+ * by setting wiphy->mbssid_max_ema_profile_periodicity to non-zero.
|
||||
+ *
|
||||
+ * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal
|
||||
+ * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute
|
||||
+ */
|
||||
+enum nl80211_mbssid_config_attributes {
|
||||
+ __NL80211_MBSSID_CONFIG_ATTR_INVALID,
|
||||
+
|
||||
+ NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
|
||||
+ NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
|
||||
+ NL80211_MBSSID_CONFIG_ATTR_INDEX,
|
||||
+ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
|
||||
+ NL80211_MBSSID_CONFIG_ATTR_EMA,
|
||||
+
|
||||
+ /* keep last */
|
||||
+ __NL80211_MBSSID_CONFIG_ATTR_LAST,
|
||||
+ NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1,
|
||||
+};
|
||||
+
|
||||
#endif /* __LINUX_NL80211_H */
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -442,6 +442,16 @@ sar_policy[NL80211_SAR_ATTR_MAX + 1] = {
|
||||
[NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy),
|
||||
};
|
||||
|
||||
+static const struct nla_policy
|
||||
+nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = {
|
||||
+ [NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES] = NLA_POLICY_MIN(NLA_U8, 2),
|
||||
+ [NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY] =
|
||||
+ NLA_POLICY_MIN(NLA_U8, 1),
|
||||
+ [NL80211_MBSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 },
|
||||
+ [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 },
|
||||
+ [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG },
|
||||
+};
|
||||
+
|
||||
static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||
[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
|
||||
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
|
||||
@@ -788,6 +798,9 @@ static const struct nla_policy nl80211_p
|
||||
[NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
|
||||
+ [NL80211_ATTR_MBSSID_CONFIG] =
|
||||
+ NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
|
||||
+ [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@@ -2236,6 +2249,35 @@ fail:
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
+static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg)
|
||||
+{
|
||||
+ struct nlattr *config;
|
||||
+
|
||||
+ if (!wiphy->mbssid_max_interfaces)
|
||||
+ return 0;
|
||||
+
|
||||
+ config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
|
||||
+ if (!config)
|
||||
+ return -ENOBUFS;
|
||||
+
|
||||
+ if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
|
||||
+ wiphy->mbssid_max_interfaces))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (wiphy->ema_max_profile_periodicity &&
|
||||
+ nla_put_u8(msg,
|
||||
+ NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
|
||||
+ wiphy->ema_max_profile_periodicity))
|
||||
+ goto fail;
|
||||
+
|
||||
+ nla_nest_end(msg, config);
|
||||
+ return 0;
|
||||
+
|
||||
+fail:
|
||||
+ nla_nest_cancel(msg, config);
|
||||
+ return -ENOBUFS;
|
||||
+}
|
||||
+
|
||||
struct nl80211_dump_wiphy_state {
|
||||
s64 filter_wiphy;
|
||||
long start;
|
||||
@@ -2821,6 +2863,9 @@ static int nl80211_send_wiphy(struct cfg
|
||||
if (nl80211_put_sar_specs(rdev, msg))
|
||||
goto nla_put_failure;
|
||||
|
||||
+ if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
break;
|
||||
@@ -5020,6 +5065,96 @@ static int validate_beacon_tx_rate(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int nl80211_parse_mbssid_config(struct wiphy *wiphy,
|
||||
+ struct net_device *dev,
|
||||
+ struct nlattr *attrs,
|
||||
+ struct cfg80211_mbssid_config *config,
|
||||
+ u8 num_elems)
|
||||
+{
|
||||
+ struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
|
||||
+
|
||||
+ if (!wiphy->mbssid_max_interfaces)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL,
|
||||
+ NULL) ||
|
||||
+ !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX])
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]);
|
||||
+ if (config->ema) {
|
||||
+ if (!wiphy->ema_max_profile_periodicity)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (num_elems > wiphy->ema_max_profile_periodicity)
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]);
|
||||
+ if (config->index >= wiphy->mbssid_max_interfaces ||
|
||||
+ (!config->index && !num_elems))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) {
|
||||
+ u32 tx_ifindex =
|
||||
+ nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]);
|
||||
+
|
||||
+ if ((!config->index && tx_ifindex != dev->ifindex) ||
|
||||
+ (config->index && tx_ifindex == dev->ifindex))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (tx_ifindex != dev->ifindex) {
|
||||
+ struct net_device *tx_netdev =
|
||||
+ dev_get_by_index(wiphy_net(wiphy), tx_ifindex);
|
||||
+
|
||||
+ if (!tx_netdev || !tx_netdev->ieee80211_ptr ||
|
||||
+ tx_netdev->ieee80211_ptr->wiphy != wiphy ||
|
||||
+ tx_netdev->ieee80211_ptr->iftype !=
|
||||
+ NL80211_IFTYPE_AP) {
|
||||
+ dev_put(tx_netdev);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ config->tx_wdev = tx_netdev->ieee80211_ptr;
|
||||
+ } else {
|
||||
+ config->tx_wdev = dev->ieee80211_ptr;
|
||||
+ }
|
||||
+ } else if (!config->index) {
|
||||
+ config->tx_wdev = dev->ieee80211_ptr;
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct cfg80211_mbssid_elems *
|
||||
+nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
|
||||
+{
|
||||
+ struct nlattr *nl_elems;
|
||||
+ struct cfg80211_mbssid_elems *elems;
|
||||
+ int rem_elems;
|
||||
+ u8 i = 0, num_elems = 0;
|
||||
+
|
||||
+ if (!wiphy->mbssid_max_interfaces)
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+
|
||||
+ nla_for_each_nested(nl_elems, attrs, rem_elems)
|
||||
+ num_elems++;
|
||||
+
|
||||
+ elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
|
||||
+ if (!elems)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+
|
||||
+ nla_for_each_nested(nl_elems, attrs, rem_elems) {
|
||||
+ elems->elem[i].data = nla_data(nl_elems);
|
||||
+ elems->elem[i].len = nla_len(nl_elems);
|
||||
+ i++;
|
||||
+ }
|
||||
+ elems->cnt = num_elems;
|
||||
+ return elems;
|
||||
+}
|
||||
+
|
||||
static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
|
||||
struct nlattr *attrs[],
|
||||
struct cfg80211_beacon_data *bcn)
|
||||
@@ -5100,6 +5235,17 @@ static int nl80211_parse_beacon(struct c
|
||||
bcn->ftm_responder = -1;
|
||||
}
|
||||
|
||||
+ if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
|
||||
+ struct cfg80211_mbssid_elems *mbssid =
|
||||
+ nl80211_parse_mbssid_elems(&rdev->wiphy,
|
||||
+ attrs[NL80211_ATTR_MBSSID_ELEMS]);
|
||||
+
|
||||
+ if (IS_ERR(mbssid))
|
||||
+ return PTR_ERR(mbssid);
|
||||
+
|
||||
+ bcn->mbssid_ies = mbssid;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5556,6 +5702,17 @@ static int nl80211_start_ap(struct sk_bu
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) {
|
||||
+ err = nl80211_parse_mbssid_config(&rdev->wiphy, dev,
|
||||
+ info->attrs[NL80211_ATTR_MBSSID_CONFIG],
|
||||
+ ¶ms.mbssid_config,
|
||||
+ params.beacon.mbssid_ies ?
|
||||
+ params.beacon.mbssid_ies->cnt :
|
||||
+ 0);
|
||||
+ if (err)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
nl80211_calculate_ap_params(¶ms);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
||||
@@ -5577,6 +5734,11 @@ static int nl80211_start_ap(struct sk_bu
|
||||
|
||||
out:
|
||||
kfree(params.acl);
|
||||
+ kfree(params.beacon.mbssid_ies);
|
||||
+ if (params.mbssid_config.tx_wdev &&
|
||||
+ params.mbssid_config.tx_wdev->netdev &&
|
||||
+ params.mbssid_config.tx_wdev->netdev != dev)
|
||||
+ dev_put(params.mbssid_config.tx_wdev->netdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -5601,12 +5763,14 @@ static int nl80211_set_beacon(struct sk_
|
||||
|
||||
err = nl80211_parse_beacon(rdev, info->attrs, ¶ms);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto out;
|
||||
|
||||
wdev_lock(wdev);
|
||||
err = rdev_change_beacon(rdev, dev, ¶ms);
|
||||
wdev_unlock(wdev);
|
||||
|
||||
+out:
|
||||
+ kfree(params.mbssid_ies);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -9283,12 +9447,14 @@ static int nl80211_channel_switch(struct
|
||||
|
||||
err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon_after);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto free;
|
||||
|
||||
csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs),
|
||||
GFP_KERNEL);
|
||||
- if (!csa_attrs)
|
||||
- return -ENOMEM;
|
||||
+ if (!csa_attrs) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto free;
|
||||
+ }
|
||||
|
||||
err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
|
||||
info->attrs[NL80211_ATTR_CSA_IES],
|
||||
@@ -9407,6 +9573,8 @@ skip_beacons:
|
||||
wdev_unlock(wdev);
|
||||
|
||||
free:
|
||||
+ kfree(params.beacon_after.mbssid_ies);
|
||||
+ kfree(params.beacon_csa.mbssid_ies);
|
||||
kfree(csa_attrs);
|
||||
return err;
|
||||
}
|
||||
@@ -14959,6 +15127,8 @@ static int nl80211_color_change(struct s
|
||||
wdev_unlock(wdev);
|
||||
|
||||
out:
|
||||
+ kfree(params.beacon_next.mbssid_ies);
|
||||
+ kfree(params.beacon_color_change.mbssid_ies);
|
||||
kfree(tb);
|
||||
return err;
|
||||
}
|
@ -1,378 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 23 Oct 2021 11:10:50 +0200
|
||||
Subject: [PATCH] cfg80211: implement APIs for dedicated radar detection HW
|
||||
|
||||
If a dedicated (off-channel) radar detection hardware (chain)
|
||||
is available in the hardware/driver, allow this to be used by
|
||||
calling the NL80211_CMD_RADAR_DETECT command with a new flag
|
||||
attribute requesting off-channel radar detection is used.
|
||||
|
||||
Offchannel CAC (channel availability check) avoids the CAC
|
||||
downtime when switching to a radar channel or when turning on
|
||||
the AP.
|
||||
|
||||
Drivers advertise support for this using the new feature flag
|
||||
NL80211_EXT_FEATURE_RADAR_OFFCHAN.
|
||||
|
||||
Tested-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/7468e291ef5d05d692c1738d25b8f778d8ea5c3f.1634979655.git.lorenzo@kernel.org
|
||||
Link: https://lore.kernel.org/r/1e60e60fef00e14401adae81c3d49f3e5f307537.1634979655.git.lorenzo@kernel.org
|
||||
Link: https://lore.kernel.org/r/85fa50f57fc3adb2934c8d9ca0be30394de6b7e8.1634979655.git.lorenzo@kernel.org
|
||||
Link: https://lore.kernel.org/r/4b6c08671ad59aae0ac46fc94c02f31b1610eb72.1634979655.git.lorenzo@kernel.org
|
||||
Link: https://lore.kernel.org/r/241849ccaf2c228873c6f8495bf87b19159ba458.1634979655.git.lorenzo@kernel.org
|
||||
[remove offchan_mutex, fix cfg80211_stop_offchan_radar_detection(),
|
||||
remove gfp_t argument, fix documentation, fix tracing]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -4057,6 +4057,15 @@ struct mgmt_frame_regs {
|
||||
* @set_sar_specs: Update the SAR (TX power) settings.
|
||||
*
|
||||
* @color_change: Initiate a color change.
|
||||
+ *
|
||||
+ * @set_radar_offchan: Configure dedicated offchannel chain available for
|
||||
+ * radar/CAC detection on some hw. This chain can't be used to transmit
|
||||
+ * or receive frames and it is bounded to a running wdev.
|
||||
+ * Offchannel radar/CAC detection allows to avoid the CAC downtime
|
||||
+ * switching to a different channel during CAC detection on the selected
|
||||
+ * radar channel.
|
||||
+ * The caller is expected to set chandef pointer to NULL in order to
|
||||
+ * disable offchannel CAC/radar detection.
|
||||
*/
|
||||
struct cfg80211_ops {
|
||||
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
||||
@@ -4387,6 +4396,8 @@ struct cfg80211_ops {
|
||||
int (*color_change)(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_color_change_settings *params);
|
||||
+ int (*set_radar_offchan)(struct wiphy *wiphy,
|
||||
+ struct cfg80211_chan_def *chandef);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -7608,6 +7619,20 @@ void cfg80211_cac_event(struct net_devic
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_radar_event event, gfp_t gfp);
|
||||
|
||||
+/**
|
||||
+ * cfg80211_offchan_cac_event - Channel Availability Check (CAC) offchan event
|
||||
+ * @wiphy: the wiphy
|
||||
+ * @chandef: chandef for the current channel
|
||||
+ * @event: type of event
|
||||
+ *
|
||||
+ * This function is called when a Channel Availability Check (CAC) is finished,
|
||||
+ * started or aborted by a offchannel dedicated chain.
|
||||
+ *
|
||||
+ * Note that this acquires the wiphy lock.
|
||||
+ */
|
||||
+void cfg80211_offchan_cac_event(struct wiphy *wiphy,
|
||||
+ const struct cfg80211_chan_def *chandef,
|
||||
+ enum nl80211_radar_event event);
|
||||
|
||||
/**
|
||||
* cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
|
||||
--- a/include/uapi/linux/nl80211.h
|
||||
+++ b/include/uapi/linux/nl80211.h
|
||||
@@ -2608,6 +2608,13 @@ enum nl80211_commands {
|
||||
* Mandatory parameter for the transmitting interface to enable MBSSID.
|
||||
* Optional for the non-transmitting interfaces.
|
||||
*
|
||||
+ * @NL80211_ATTR_RADAR_OFFCHAN: Configure dedicated offchannel chain available for
|
||||
+ * radar/CAC detection on some hw. This chain can't be used to transmit
|
||||
+ * or receive frames and it is bounded to a running wdev.
|
||||
+ * Offchannel radar/CAC detection allows to avoid the CAC downtime
|
||||
+ * switching on a different channel during CAC detection on the selected
|
||||
+ * radar channel.
|
||||
+ *
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@@ -3114,6 +3121,8 @@ enum nl80211_attrs {
|
||||
NL80211_ATTR_MBSSID_CONFIG,
|
||||
NL80211_ATTR_MBSSID_ELEMS,
|
||||
|
||||
+ NL80211_ATTR_RADAR_OFFCHAN,
|
||||
+
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@@ -6013,6 +6022,9 @@ enum nl80211_feature_flags {
|
||||
* @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
|
||||
* detection and change announcemnts.
|
||||
*
|
||||
+ * @NL80211_EXT_FEATURE_RADAR_OFFCHAN: Device supports offchannel radar/CAC
|
||||
+ * detection.
|
||||
+ *
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
@@ -6078,6 +6090,7 @@ enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_SECURE_RTT,
|
||||
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
|
||||
NL80211_EXT_FEATURE_BSS_COLOR,
|
||||
+ NL80211_EXT_FEATURE_RADAR_OFFCHAN,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
--- a/net/wireless/core.c
|
||||
+++ b/net/wireless/core.c
|
||||
@@ -543,6 +543,7 @@ use_default_name:
|
||||
INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work);
|
||||
INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
|
||||
INIT_WORK(&rdev->event_work, cfg80211_event_work);
|
||||
+ INIT_DELAYED_WORK(&rdev->offchan_cac_work, cfg80211_offchan_cac_work);
|
||||
|
||||
init_waitqueue_head(&rdev->dev_wait);
|
||||
|
||||
@@ -1205,6 +1206,8 @@ void __cfg80211_leave(struct cfg80211_re
|
||||
|
||||
cfg80211_pmsr_wdev_down(wdev);
|
||||
|
||||
+ cfg80211_stop_offchan_radar_detection(wdev);
|
||||
+
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
__cfg80211_leave_ibss(rdev, dev, true);
|
||||
--- a/net/wireless/core.h
|
||||
+++ b/net/wireless/core.h
|
||||
@@ -84,6 +84,10 @@ struct cfg80211_registered_device {
|
||||
|
||||
struct delayed_work dfs_update_channels_wk;
|
||||
|
||||
+ struct wireless_dev *offchan_radar_wdev;
|
||||
+ struct cfg80211_chan_def offchan_radar_chandef;
|
||||
+ struct delayed_work offchan_cac_work;
|
||||
+
|
||||
/* netlink port which started critical protocol (0 means not started) */
|
||||
u32 crit_proto_nlportid;
|
||||
|
||||
@@ -491,6 +495,15 @@ cfg80211_chandef_dfs_cac_time(struct wip
|
||||
|
||||
void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev);
|
||||
|
||||
+int
|
||||
+cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev,
|
||||
+ struct wireless_dev *wdev,
|
||||
+ struct cfg80211_chan_def *chandef);
|
||||
+
|
||||
+void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev);
|
||||
+
|
||||
+void cfg80211_offchan_cac_work(struct work_struct *work);
|
||||
+
|
||||
bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *chan);
|
||||
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -970,3 +970,116 @@ void cfg80211_cac_event(struct net_devic
|
||||
nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_cac_event);
|
||||
+
|
||||
+void cfg80211_offchan_cac_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct delayed_work *delayed_work = to_delayed_work(work);
|
||||
+ struct cfg80211_registered_device *rdev;
|
||||
+
|
||||
+ rdev = container_of(delayed_work, struct cfg80211_registered_device,
|
||||
+ offchan_cac_work);
|
||||
+ cfg80211_offchan_cac_event(&rdev->wiphy, &rdev->offchan_radar_chandef,
|
||||
+ NL80211_RADAR_CAC_FINISHED);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+__cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev,
|
||||
+ struct wireless_dev *wdev,
|
||||
+ const struct cfg80211_chan_def *chandef,
|
||||
+ enum nl80211_radar_event event)
|
||||
+{
|
||||
+ struct wiphy *wiphy = &rdev->wiphy;
|
||||
+ struct net_device *netdev;
|
||||
+
|
||||
+ lockdep_assert_wiphy(&rdev->wiphy);
|
||||
+
|
||||
+ if (event != NL80211_RADAR_CAC_STARTED && !rdev->offchan_radar_wdev)
|
||||
+ return;
|
||||
+
|
||||
+ switch (event) {
|
||||
+ case NL80211_RADAR_CAC_FINISHED:
|
||||
+ cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
|
||||
+ memcpy(&rdev->cac_done_chandef, chandef, sizeof(*chandef));
|
||||
+ queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
|
||||
+ cfg80211_sched_dfs_chan_update(rdev);
|
||||
+ wdev = rdev->offchan_radar_wdev;
|
||||
+ rdev->offchan_radar_wdev = NULL;
|
||||
+ break;
|
||||
+ case NL80211_RADAR_CAC_ABORTED:
|
||||
+ cancel_delayed_work(&rdev->offchan_cac_work);
|
||||
+ wdev = rdev->offchan_radar_wdev;
|
||||
+ rdev->offchan_radar_wdev = NULL;
|
||||
+ break;
|
||||
+ case NL80211_RADAR_CAC_STARTED:
|
||||
+ WARN_ON(!wdev);
|
||||
+ rdev->offchan_radar_wdev = wdev;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ netdev = wdev ? wdev->netdev : NULL;
|
||||
+ nl80211_radar_notify(rdev, chandef, event, netdev, GFP_KERNEL);
|
||||
+}
|
||||
+
|
||||
+void cfg80211_offchan_cac_event(struct wiphy *wiphy,
|
||||
+ const struct cfg80211_chan_def *chandef,
|
||||
+ enum nl80211_radar_event event)
|
||||
+{
|
||||
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
+
|
||||
+ wiphy_lock(wiphy);
|
||||
+ __cfg80211_offchan_cac_event(rdev, NULL, chandef, event);
|
||||
+ wiphy_unlock(wiphy);
|
||||
+}
|
||||
+EXPORT_SYMBOL(cfg80211_offchan_cac_event);
|
||||
+
|
||||
+int
|
||||
+cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev,
|
||||
+ struct wireless_dev *wdev,
|
||||
+ struct cfg80211_chan_def *chandef)
|
||||
+{
|
||||
+ unsigned int cac_time_ms;
|
||||
+ int err;
|
||||
+
|
||||
+ lockdep_assert_wiphy(&rdev->wiphy);
|
||||
+
|
||||
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
+ NL80211_EXT_FEATURE_RADAR_OFFCHAN))
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (rdev->offchan_radar_wdev)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ err = rdev_set_radar_offchan(rdev, chandef);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, chandef);
|
||||
+ if (!cac_time_ms)
|
||||
+ cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
|
||||
+
|
||||
+ rdev->offchan_radar_chandef = *chandef;
|
||||
+ __cfg80211_offchan_cac_event(rdev, wdev, chandef,
|
||||
+ NL80211_RADAR_CAC_STARTED);
|
||||
+ queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_work,
|
||||
+ msecs_to_jiffies(cac_time_ms));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev)
|
||||
+{
|
||||
+ struct wiphy *wiphy = wdev->wiphy;
|
||||
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
+
|
||||
+ lockdep_assert_wiphy(wiphy);
|
||||
+
|
||||
+ if (wdev != rdev->offchan_radar_wdev)
|
||||
+ return;
|
||||
+
|
||||
+ rdev_set_radar_offchan(rdev, NULL);
|
||||
+
|
||||
+ __cfg80211_offchan_cac_event(rdev, NULL, NULL,
|
||||
+ NL80211_RADAR_CAC_ABORTED);
|
||||
+}
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -801,6 +801,7 @@ static const struct nla_policy nl80211_p
|
||||
[NL80211_ATTR_MBSSID_CONFIG] =
|
||||
NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
|
||||
[NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
|
||||
+ [NL80211_ATTR_RADAR_OFFCHAN] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@@ -9287,12 +9288,6 @@ static int nl80211_start_radar_detection
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- if (netif_carrier_ok(dev))
|
||||
- return -EBUSY;
|
||||
-
|
||||
- if (wdev->cac_started)
|
||||
- return -EBUSY;
|
||||
-
|
||||
err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@@ -9303,6 +9298,16 @@ static int nl80211_start_radar_detection
|
||||
if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
|
||||
return -EINVAL;
|
||||
|
||||
+ if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_OFFCHAN]))
|
||||
+ return cfg80211_start_offchan_radar_detection(rdev, wdev,
|
||||
+ &chandef);
|
||||
+
|
||||
+ if (netif_carrier_ok(dev))
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ if (wdev->cac_started)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
/* CAC start is offloaded to HW and can't be started manually */
|
||||
if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
|
||||
return -EOPNOTSUPP;
|
||||
--- a/net/wireless/rdev-ops.h
|
||||
+++ b/net/wireless/rdev-ops.h
|
||||
@@ -1381,4 +1381,21 @@ static inline int rdev_color_change(stru
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static inline int
|
||||
+rdev_set_radar_offchan(struct cfg80211_registered_device *rdev,
|
||||
+ struct cfg80211_chan_def *chandef)
|
||||
+{
|
||||
+ struct wiphy *wiphy = &rdev->wiphy;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!rdev->ops->set_radar_offchan)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ trace_rdev_set_radar_offchan(wiphy, chandef);
|
||||
+ ret = rdev->ops->set_radar_offchan(wiphy, chandef);
|
||||
+ trace_rdev_return_int(wiphy, ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
#endif /* __CFG80211_RDEV_OPS */
|
||||
--- a/net/wireless/trace.h
|
||||
+++ b/net/wireless/trace.h
|
||||
@@ -3643,6 +3643,25 @@ TRACE_EVENT(cfg80211_bss_color_notify,
|
||||
__entry->color_bitmap)
|
||||
);
|
||||
|
||||
+TRACE_EVENT(rdev_set_radar_offchan,
|
||||
+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
|
||||
+
|
||||
+ TP_ARGS(wiphy, chandef),
|
||||
+
|
||||
+ TP_STRUCT__entry(
|
||||
+ WIPHY_ENTRY
|
||||
+ CHAN_DEF_ENTRY
|
||||
+ ),
|
||||
+
|
||||
+ TP_fast_assign(
|
||||
+ WIPHY_ASSIGN;
|
||||
+ CHAN_DEF_ASSIGN(chandef)
|
||||
+ ),
|
||||
+
|
||||
+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
|
||||
+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
|
||||
+);
|
||||
+
|
||||
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
@ -1,183 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 27 Oct 2021 11:03:42 +0200
|
||||
Subject: [PATCH] cfg80211: move offchan_cac_event to a dedicated work
|
||||
|
||||
In order to make cfg80211_offchan_cac_abort() (renamed from
|
||||
cfg80211_offchan_cac_event) callable in other contexts and
|
||||
without so much locking restrictions, make it trigger a new
|
||||
work instead of operating directly.
|
||||
|
||||
Do some other renames while at it to clarify.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/6145c3d0f30400a568023f67981981d24c7c6133.1635325205.git.lorenzo@kernel.org
|
||||
[rewrite commit log]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -7620,19 +7620,13 @@ void cfg80211_cac_event(struct net_devic
|
||||
enum nl80211_radar_event event, gfp_t gfp);
|
||||
|
||||
/**
|
||||
- * cfg80211_offchan_cac_event - Channel Availability Check (CAC) offchan event
|
||||
+ * cfg80211_offchan_cac_abort - Channel Availability Check offchan abort event
|
||||
* @wiphy: the wiphy
|
||||
- * @chandef: chandef for the current channel
|
||||
- * @event: type of event
|
||||
*
|
||||
- * This function is called when a Channel Availability Check (CAC) is finished,
|
||||
- * started or aborted by a offchannel dedicated chain.
|
||||
- *
|
||||
- * Note that this acquires the wiphy lock.
|
||||
+ * This function is called by the driver when a Channel Availability Check
|
||||
+ * (CAC) is aborted by a offchannel dedicated chain.
|
||||
*/
|
||||
-void cfg80211_offchan_cac_event(struct wiphy *wiphy,
|
||||
- const struct cfg80211_chan_def *chandef,
|
||||
- enum nl80211_radar_event event);
|
||||
+void cfg80211_offchan_cac_abort(struct wiphy *wiphy);
|
||||
|
||||
/**
|
||||
* cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
|
||||
--- a/net/wireless/core.c
|
||||
+++ b/net/wireless/core.c
|
||||
@@ -543,7 +543,9 @@ use_default_name:
|
||||
INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work);
|
||||
INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
|
||||
INIT_WORK(&rdev->event_work, cfg80211_event_work);
|
||||
- INIT_DELAYED_WORK(&rdev->offchan_cac_work, cfg80211_offchan_cac_work);
|
||||
+ INIT_WORK(&rdev->offchan_cac_abort_wk, cfg80211_offchan_cac_abort_wk);
|
||||
+ INIT_DELAYED_WORK(&rdev->offchan_cac_done_wk,
|
||||
+ cfg80211_offchan_cac_done_wk);
|
||||
|
||||
init_waitqueue_head(&rdev->dev_wait);
|
||||
|
||||
@@ -1053,11 +1055,13 @@ void wiphy_unregister(struct wiphy *wiph
|
||||
cancel_work_sync(&rdev->conn_work);
|
||||
flush_work(&rdev->event_work);
|
||||
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
|
||||
+ cancel_delayed_work_sync(&rdev->offchan_cac_done_wk);
|
||||
flush_work(&rdev->destroy_work);
|
||||
flush_work(&rdev->sched_scan_stop_wk);
|
||||
flush_work(&rdev->propagate_radar_detect_wk);
|
||||
flush_work(&rdev->propagate_cac_done_wk);
|
||||
flush_work(&rdev->mgmt_registrations_update_wk);
|
||||
+ flush_work(&rdev->offchan_cac_abort_wk);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
|
||||
--- a/net/wireless/core.h
|
||||
+++ b/net/wireless/core.h
|
||||
@@ -86,7 +86,8 @@ struct cfg80211_registered_device {
|
||||
|
||||
struct wireless_dev *offchan_radar_wdev;
|
||||
struct cfg80211_chan_def offchan_radar_chandef;
|
||||
- struct delayed_work offchan_cac_work;
|
||||
+ struct delayed_work offchan_cac_done_wk;
|
||||
+ struct work_struct offchan_cac_abort_wk;
|
||||
|
||||
/* netlink port which started critical protocol (0 means not started) */
|
||||
u32 crit_proto_nlportid;
|
||||
@@ -502,7 +503,9 @@ cfg80211_start_offchan_radar_detection(s
|
||||
|
||||
void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev);
|
||||
|
||||
-void cfg80211_offchan_cac_work(struct work_struct *work);
|
||||
+void cfg80211_offchan_cac_done_wk(struct work_struct *work);
|
||||
+
|
||||
+void cfg80211_offchan_cac_abort_wk(struct work_struct *work);
|
||||
|
||||
bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *chan);
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -971,17 +971,6 @@ void cfg80211_cac_event(struct net_devic
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_cac_event);
|
||||
|
||||
-void cfg80211_offchan_cac_work(struct work_struct *work)
|
||||
-{
|
||||
- struct delayed_work *delayed_work = to_delayed_work(work);
|
||||
- struct cfg80211_registered_device *rdev;
|
||||
-
|
||||
- rdev = container_of(delayed_work, struct cfg80211_registered_device,
|
||||
- offchan_cac_work);
|
||||
- cfg80211_offchan_cac_event(&rdev->wiphy, &rdev->offchan_radar_chandef,
|
||||
- NL80211_RADAR_CAC_FINISHED);
|
||||
-}
|
||||
-
|
||||
static void
|
||||
__cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
@@ -1006,7 +995,7 @@ __cfg80211_offchan_cac_event(struct cfg8
|
||||
rdev->offchan_radar_wdev = NULL;
|
||||
break;
|
||||
case NL80211_RADAR_CAC_ABORTED:
|
||||
- cancel_delayed_work(&rdev->offchan_cac_work);
|
||||
+ cancel_delayed_work(&rdev->offchan_cac_done_wk);
|
||||
wdev = rdev->offchan_radar_wdev;
|
||||
rdev->offchan_radar_wdev = NULL;
|
||||
break;
|
||||
@@ -1022,17 +1011,44 @@ __cfg80211_offchan_cac_event(struct cfg8
|
||||
nl80211_radar_notify(rdev, chandef, event, netdev, GFP_KERNEL);
|
||||
}
|
||||
|
||||
-void cfg80211_offchan_cac_event(struct wiphy *wiphy,
|
||||
- const struct cfg80211_chan_def *chandef,
|
||||
- enum nl80211_radar_event event)
|
||||
+static void
|
||||
+cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev,
|
||||
+ const struct cfg80211_chan_def *chandef,
|
||||
+ enum nl80211_radar_event event)
|
||||
+{
|
||||
+ wiphy_lock(&rdev->wiphy);
|
||||
+ __cfg80211_offchan_cac_event(rdev, NULL, chandef, event);
|
||||
+ wiphy_unlock(&rdev->wiphy);
|
||||
+}
|
||||
+
|
||||
+void cfg80211_offchan_cac_done_wk(struct work_struct *work)
|
||||
+{
|
||||
+ struct delayed_work *delayed_work = to_delayed_work(work);
|
||||
+ struct cfg80211_registered_device *rdev;
|
||||
+
|
||||
+ rdev = container_of(delayed_work, struct cfg80211_registered_device,
|
||||
+ offchan_cac_done_wk);
|
||||
+ cfg80211_offchan_cac_event(rdev, &rdev->offchan_radar_chandef,
|
||||
+ NL80211_RADAR_CAC_FINISHED);
|
||||
+}
|
||||
+
|
||||
+void cfg80211_offchan_cac_abort_wk(struct work_struct *work)
|
||||
+{
|
||||
+ struct cfg80211_registered_device *rdev;
|
||||
+
|
||||
+ rdev = container_of(work, struct cfg80211_registered_device,
|
||||
+ offchan_cac_abort_wk);
|
||||
+ cfg80211_offchan_cac_event(rdev, &rdev->offchan_radar_chandef,
|
||||
+ NL80211_RADAR_CAC_ABORTED);
|
||||
+}
|
||||
+
|
||||
+void cfg80211_offchan_cac_abort(struct wiphy *wiphy)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
- wiphy_lock(wiphy);
|
||||
- __cfg80211_offchan_cac_event(rdev, NULL, chandef, event);
|
||||
- wiphy_unlock(wiphy);
|
||||
+ queue_work(cfg80211_wq, &rdev->offchan_cac_abort_wk);
|
||||
}
|
||||
-EXPORT_SYMBOL(cfg80211_offchan_cac_event);
|
||||
+EXPORT_SYMBOL(cfg80211_offchan_cac_abort);
|
||||
|
||||
int
|
||||
cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev,
|
||||
@@ -1062,7 +1078,7 @@ cfg80211_start_offchan_radar_detection(s
|
||||
rdev->offchan_radar_chandef = *chandef;
|
||||
__cfg80211_offchan_cac_event(rdev, wdev, chandef,
|
||||
NL80211_RADAR_CAC_STARTED);
|
||||
- queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_work,
|
||||
+ queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_done_wk,
|
||||
msecs_to_jiffies(cac_time_ms));
|
||||
|
||||
return 0;
|
@ -1,99 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Nov 2021 18:02:35 +0100
|
||||
Subject: [PATCH] cfg80211: fix possible NULL pointer dereference in
|
||||
cfg80211_stop_offchan_radar_detection
|
||||
|
||||
Fix the following NULL pointer dereference in
|
||||
cfg80211_stop_offchan_radar_detection routine that occurs when hostapd
|
||||
is stopped during the CAC on offchannel chain:
|
||||
|
||||
Sat Jan 1 0[ 779.567851] ESR = 0x96000005
|
||||
0:12:50 2000 dae[ 779.572346] EC = 0x25: DABT (current EL), IL = 32 bits
|
||||
mon.debug hostap[ 779.578984] SET = 0, FnV = 0
|
||||
d: hostapd_inter[ 779.583445] EA = 0, S1PTW = 0
|
||||
face_deinit_free[ 779.587936] Data abort info:
|
||||
: num_bss=1 conf[ 779.592224] ISV = 0, ISS = 0x00000005
|
||||
->num_bss=1
|
||||
Sat[ 779.597403] CM = 0, WnR = 0
|
||||
Jan 1 00:12:50[ 779.601749] user pgtable: 4k pages, 39-bit VAs, pgdp=00000000418b2000
|
||||
2000 daemon.deb[ 779.609601] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
|
||||
ug hostapd: host[ 779.619657] Internal error: Oops: 96000005 [#1] SMP
|
||||
[ 779.770810] CPU: 0 PID: 2202 Comm: hostapd Not tainted 5.10.75 #0
|
||||
[ 779.776892] Hardware name: MediaTek MT7622 RFB1 board (DT)
|
||||
[ 779.782370] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO BTYPE=--)
|
||||
[ 779.788384] pc : cfg80211_chandef_valid+0x10/0x490 [cfg80211]
|
||||
[ 779.794128] lr : cfg80211_check_station_change+0x3190/0x3950 [cfg80211]
|
||||
[ 779.800731] sp : ffffffc01204b7e0
|
||||
[ 779.804036] x29: ffffffc01204b7e0 x28: ffffff80039bdc00
|
||||
[ 779.809340] x27: 0000000000000000 x26: ffffffc008cb3050
|
||||
[ 779.814644] x25: 0000000000000000 x24: 0000000000000002
|
||||
[ 779.819948] x23: ffffff8002630000 x22: ffffff8003e748d0
|
||||
[ 779.825252] x21: 0000000000000cc0 x20: ffffff8003da4a00
|
||||
[ 779.830556] x19: 0000000000000000 x18: ffffff8001bf7ce0
|
||||
[ 779.835860] x17: 00000000ffffffff x16: 0000000000000000
|
||||
[ 779.841164] x15: 0000000040d59200 x14: 00000000000019c0
|
||||
[ 779.846467] x13: 00000000000001c8 x12: 000636b9e9dab1c6
|
||||
[ 779.851771] x11: 0000000000000141 x10: 0000000000000820
|
||||
[ 779.857076] x9 : 0000000000000000 x8 : ffffff8003d7d038
|
||||
[ 779.862380] x7 : 0000000000000000 x6 : ffffff8003d7d038
|
||||
[ 779.867683] x5 : 0000000000000e90 x4 : 0000000000000038
|
||||
[ 779.872987] x3 : 0000000000000002 x2 : 0000000000000004
|
||||
[ 779.878291] x1 : 0000000000000000 x0 : 0000000000000000
|
||||
[ 779.883594] Call trace:
|
||||
[ 779.886039] cfg80211_chandef_valid+0x10/0x490 [cfg80211]
|
||||
[ 779.891434] cfg80211_check_station_change+0x3190/0x3950 [cfg80211]
|
||||
[ 779.897697] nl80211_radar_notify+0x138/0x19c [cfg80211]
|
||||
[ 779.903005] cfg80211_stop_offchan_radar_detection+0x7c/0x8c [cfg80211]
|
||||
[ 779.909616] __cfg80211_leave+0x2c/0x190 [cfg80211]
|
||||
[ 779.914490] cfg80211_register_netdevice+0x1c0/0x6d0 [cfg80211]
|
||||
[ 779.920404] raw_notifier_call_chain+0x50/0x70
|
||||
[ 779.924841] call_netdevice_notifiers_info+0x54/0xa0
|
||||
[ 779.929796] __dev_close_many+0x40/0x100
|
||||
[ 779.933712] __dev_change_flags+0x98/0x190
|
||||
[ 779.937800] dev_change_flags+0x20/0x60
|
||||
[ 779.941628] devinet_ioctl+0x534/0x6d0
|
||||
[ 779.945370] inet_ioctl+0x1bc/0x230
|
||||
[ 779.948849] sock_do_ioctl+0x44/0x200
|
||||
[ 779.952502] sock_ioctl+0x268/0x4c0
|
||||
[ 779.955985] __arm64_sys_ioctl+0xac/0xd0
|
||||
[ 779.959900] el0_svc_common.constprop.0+0x60/0x110
|
||||
[ 779.964682] do_el0_svc+0x1c/0x24
|
||||
[ 779.967990] el0_svc+0x10/0x1c
|
||||
[ 779.971036] el0_sync_handler+0x9c/0x120
|
||||
[ 779.974950] el0_sync+0x148/0x180
|
||||
[ 779.978259] Code: a9bc7bfd 910003fd a90153f3 aa0003f3 (f9400000)
|
||||
[ 779.984344] ---[ end trace 0e67b4f5d6cdeec7 ]---
|
||||
[ 779.996400] Kernel panic - not syncing: Oops: Fatal exception
|
||||
[ 780.002139] SMP: stopping secondary CPUs
|
||||
[ 780.006057] Kernel Offset: disabled
|
||||
[ 780.009537] CPU features: 0x0000002,04002004
|
||||
[ 780.013796] Memory Limit: none
|
||||
|
||||
Fixes: b8f5facf286b ("cfg80211: implement APIs for dedicated radar detection HW")
|
||||
Reported-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
|
||||
Tested-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/c2e34c065bf8839c5ffa45498ae154021a72a520.1635958796.git.lorenzo@kernel.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -982,6 +982,9 @@ __cfg80211_offchan_cac_event(struct cfg8
|
||||
|
||||
lockdep_assert_wiphy(&rdev->wiphy);
|
||||
|
||||
+ if (!cfg80211_chandef_valid(chandef))
|
||||
+ return;
|
||||
+
|
||||
if (event != NL80211_RADAR_CAC_STARTED && !rdev->offchan_radar_wdev)
|
||||
return;
|
||||
|
||||
@@ -1096,6 +1099,6 @@ void cfg80211_stop_offchan_radar_detecti
|
||||
|
||||
rdev_set_radar_offchan(rdev, NULL);
|
||||
|
||||
- __cfg80211_offchan_cac_event(rdev, NULL, NULL,
|
||||
+ __cfg80211_offchan_cac_event(rdev, wdev, &rdev->offchan_radar_chandef,
|
||||
NL80211_RADAR_CAC_ABORTED);
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 16 Nov 2021 12:41:52 +0100
|
||||
Subject: [PATCH] cfg80211: schedule offchan_cac_abort_wk in
|
||||
cfg80211_radar_event
|
||||
|
||||
If necessary schedule offchan_cac_abort_wk work in cfg80211_radar_event
|
||||
routine adding offchan parameter to cfg80211_radar_event signature.
|
||||
Rename cfg80211_radar_event in __cfg80211_radar_event and introduce
|
||||
the two following inline helpers:
|
||||
- cfg80211_radar_event
|
||||
- cfg80211_offchan_radar_event
|
||||
Doing so the drv will not need to run cfg80211_offchan_cac_abort() after
|
||||
radar detection on the offchannel chain.
|
||||
|
||||
Tested-by: Owen Peng <owen.peng@mediatek.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/3ff583e021e3343a3ced54a7b09b5e184d1880dc.1637062727.git.lorenzo@kernel.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -7580,15 +7580,33 @@ void cfg80211_cqm_txe_notify(struct net_
|
||||
void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp);
|
||||
|
||||
/**
|
||||
- * cfg80211_radar_event - radar detection event
|
||||
+ * __cfg80211_radar_event - radar detection event
|
||||
* @wiphy: the wiphy
|
||||
* @chandef: chandef for the current channel
|
||||
+ * @offchan: the radar has been detected on the offchannel chain
|
||||
* @gfp: context flags
|
||||
*
|
||||
* This function is called when a radar is detected on the current chanenl.
|
||||
*/
|
||||
-void cfg80211_radar_event(struct wiphy *wiphy,
|
||||
- struct cfg80211_chan_def *chandef, gfp_t gfp);
|
||||
+void __cfg80211_radar_event(struct wiphy *wiphy,
|
||||
+ struct cfg80211_chan_def *chandef,
|
||||
+ bool offchan, gfp_t gfp);
|
||||
+
|
||||
+static inline void
|
||||
+cfg80211_radar_event(struct wiphy *wiphy,
|
||||
+ struct cfg80211_chan_def *chandef,
|
||||
+ gfp_t gfp)
|
||||
+{
|
||||
+ __cfg80211_radar_event(wiphy, chandef, false, gfp);
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+cfg80211_offchan_radar_event(struct wiphy *wiphy,
|
||||
+ struct cfg80211_chan_def *chandef,
|
||||
+ gfp_t gfp)
|
||||
+{
|
||||
+ __cfg80211_radar_event(wiphy, chandef, true, gfp);
|
||||
+}
|
||||
|
||||
/**
|
||||
* cfg80211_sta_opmode_change_notify - STA's ht/vht operation mode change event
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -905,13 +905,13 @@ void cfg80211_dfs_channels_update_work(s
|
||||
}
|
||||
|
||||
|
||||
-void cfg80211_radar_event(struct wiphy *wiphy,
|
||||
- struct cfg80211_chan_def *chandef,
|
||||
- gfp_t gfp)
|
||||
+void __cfg80211_radar_event(struct wiphy *wiphy,
|
||||
+ struct cfg80211_chan_def *chandef,
|
||||
+ bool offchan, gfp_t gfp)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
- trace_cfg80211_radar_event(wiphy, chandef);
|
||||
+ trace_cfg80211_radar_event(wiphy, chandef, offchan);
|
||||
|
||||
/* only set the chandef supplied channel to unavailable, in
|
||||
* case the radar is detected on only one of multiple channels
|
||||
@@ -919,6 +919,9 @@ void cfg80211_radar_event(struct wiphy *
|
||||
*/
|
||||
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
|
||||
|
||||
+ if (offchan)
|
||||
+ queue_work(cfg80211_wq, &rdev->offchan_cac_abort_wk);
|
||||
+
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
|
||||
nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
|
||||
@@ -926,7 +929,7 @@ void cfg80211_radar_event(struct wiphy *
|
||||
memcpy(&rdev->radar_chandef, chandef, sizeof(struct cfg80211_chan_def));
|
||||
queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
|
||||
}
|
||||
-EXPORT_SYMBOL(cfg80211_radar_event);
|
||||
+EXPORT_SYMBOL(__cfg80211_radar_event);
|
||||
|
||||
void cfg80211_cac_event(struct net_device *netdev,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
@@ -998,7 +1001,8 @@ __cfg80211_offchan_cac_event(struct cfg8
|
||||
rdev->offchan_radar_wdev = NULL;
|
||||
break;
|
||||
case NL80211_RADAR_CAC_ABORTED:
|
||||
- cancel_delayed_work(&rdev->offchan_cac_done_wk);
|
||||
+ if (!cancel_delayed_work(&rdev->offchan_cac_done_wk))
|
||||
+ return;
|
||||
wdev = rdev->offchan_radar_wdev;
|
||||
rdev->offchan_radar_wdev = NULL;
|
||||
break;
|
||||
--- a/net/wireless/trace.h
|
||||
+++ b/net/wireless/trace.h
|
||||
@@ -3022,18 +3022,21 @@ TRACE_EVENT(cfg80211_ch_switch_started_n
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_radar_event,
|
||||
- TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
|
||||
- TP_ARGS(wiphy, chandef),
|
||||
+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
|
||||
+ bool offchan),
|
||||
+ TP_ARGS(wiphy, chandef, offchan),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
CHAN_DEF_ENTRY
|
||||
+ __field(bool, offchan)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
CHAN_DEF_ASSIGN(chandef);
|
||||
+ __entry->offchan = offchan;
|
||||
),
|
||||
- TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
|
||||
- WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
|
||||
+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", offchan %d",
|
||||
+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->offchan)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_cac_event,
|
@ -1,220 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 16 Nov 2021 15:03:36 +0100
|
||||
Subject: [PATCH] cfg80211: allow continuous radar monitoring on offchannel
|
||||
chain
|
||||
|
||||
Allow continuous radar detection on the offchannel chain in order
|
||||
to switch to the monitored channel whenever the underlying driver
|
||||
reports a radar pattern on the main channel.
|
||||
|
||||
Tested-by: Owen Peng <owen.peng@mediatek.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/d46217310a49b14ff0e9c002f0a6e0547d70fd2c.1637071350.git.lorenzo@kernel.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/wireless/chan.c
|
||||
+++ b/net/wireless/chan.c
|
||||
@@ -712,6 +712,19 @@ static bool cfg80211_is_wiphy_oper_chan(
|
||||
return false;
|
||||
}
|
||||
|
||||
+static bool
|
||||
+cfg80211_offchan_chain_is_active(struct cfg80211_registered_device *rdev,
|
||||
+ struct ieee80211_channel *channel)
|
||||
+{
|
||||
+ if (!rdev->offchan_radar_wdev)
|
||||
+ return false;
|
||||
+
|
||||
+ if (!cfg80211_chandef_valid(&rdev->offchan_radar_chandef))
|
||||
+ return false;
|
||||
+
|
||||
+ return cfg80211_is_sub_chan(&rdev->offchan_radar_chandef, channel);
|
||||
+}
|
||||
+
|
||||
bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *chan)
|
||||
{
|
||||
@@ -728,6 +741,9 @@ bool cfg80211_any_wiphy_oper_chan(struct
|
||||
|
||||
if (cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan))
|
||||
return true;
|
||||
+
|
||||
+ if (cfg80211_offchan_chain_is_active(rdev, chan))
|
||||
+ return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -988,7 +988,7 @@ __cfg80211_offchan_cac_event(struct cfg8
|
||||
if (!cfg80211_chandef_valid(chandef))
|
||||
return;
|
||||
|
||||
- if (event != NL80211_RADAR_CAC_STARTED && !rdev->offchan_radar_wdev)
|
||||
+ if (!rdev->offchan_radar_wdev)
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
@@ -998,17 +998,13 @@ __cfg80211_offchan_cac_event(struct cfg8
|
||||
queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
wdev = rdev->offchan_radar_wdev;
|
||||
- rdev->offchan_radar_wdev = NULL;
|
||||
break;
|
||||
case NL80211_RADAR_CAC_ABORTED:
|
||||
if (!cancel_delayed_work(&rdev->offchan_cac_done_wk))
|
||||
return;
|
||||
wdev = rdev->offchan_radar_wdev;
|
||||
- rdev->offchan_radar_wdev = NULL;
|
||||
break;
|
||||
case NL80211_RADAR_CAC_STARTED:
|
||||
- WARN_ON(!wdev);
|
||||
- rdev->offchan_radar_wdev = wdev;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -1024,7 +1020,8 @@ cfg80211_offchan_cac_event(struct cfg802
|
||||
enum nl80211_radar_event event)
|
||||
{
|
||||
wiphy_lock(&rdev->wiphy);
|
||||
- __cfg80211_offchan_cac_event(rdev, NULL, chandef, event);
|
||||
+ __cfg80211_offchan_cac_event(rdev, rdev->offchan_radar_wdev,
|
||||
+ chandef, event);
|
||||
wiphy_unlock(&rdev->wiphy);
|
||||
}
|
||||
|
||||
@@ -1071,7 +1068,13 @@ cfg80211_start_offchan_radar_detection(s
|
||||
NL80211_EXT_FEATURE_RADAR_OFFCHAN))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
- if (rdev->offchan_radar_wdev)
|
||||
+ /* Offchannel chain already locked by another wdev */
|
||||
+ if (rdev->offchan_radar_wdev && rdev->offchan_radar_wdev != wdev)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ /* CAC already in progress on the offchannel chain */
|
||||
+ if (rdev->offchan_radar_wdev == wdev &&
|
||||
+ delayed_work_pending(&rdev->offchan_cac_done_wk))
|
||||
return -EBUSY;
|
||||
|
||||
err = rdev_set_radar_offchan(rdev, chandef);
|
||||
@@ -1083,6 +1086,8 @@ cfg80211_start_offchan_radar_detection(s
|
||||
cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
|
||||
|
||||
rdev->offchan_radar_chandef = *chandef;
|
||||
+ rdev->offchan_radar_wdev = wdev; /* Get offchain ownership */
|
||||
+
|
||||
__cfg80211_offchan_cac_event(rdev, wdev, chandef,
|
||||
NL80211_RADAR_CAC_STARTED);
|
||||
queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_done_wk,
|
||||
@@ -1102,6 +1107,7 @@ void cfg80211_stop_offchan_radar_detecti
|
||||
return;
|
||||
|
||||
rdev_set_radar_offchan(rdev, NULL);
|
||||
+ rdev->offchan_radar_wdev = NULL; /* Release offchain ownership */
|
||||
|
||||
__cfg80211_offchan_cac_event(rdev, wdev, &rdev->offchan_radar_chandef,
|
||||
NL80211_RADAR_CAC_ABORTED);
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -9278,42 +9278,60 @@ static int nl80211_start_radar_detection
|
||||
struct cfg80211_chan_def chandef;
|
||||
enum nl80211_dfs_regions dfs_region;
|
||||
unsigned int cac_time_ms;
|
||||
- int err;
|
||||
+ int err = -EINVAL;
|
||||
+
|
||||
+ flush_delayed_work(&rdev->dfs_update_channels_wk);
|
||||
+
|
||||
+ wiphy_lock(wiphy);
|
||||
|
||||
dfs_region = reg_get_dfs_region(wiphy);
|
||||
if (dfs_region == NL80211_DFS_UNSET)
|
||||
- return -EINVAL;
|
||||
+ goto unlock;
|
||||
|
||||
err = nl80211_parse_chandef(rdev, info, &chandef);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto unlock;
|
||||
|
||||
err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
|
||||
if (err < 0)
|
||||
- return err;
|
||||
+ goto unlock;
|
||||
|
||||
- if (err == 0)
|
||||
- return -EINVAL;
|
||||
+ if (err == 0) {
|
||||
+ err = -EINVAL;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
|
||||
- if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
|
||||
- return -EINVAL;
|
||||
+ if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) {
|
||||
+ err = -EINVAL;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
|
||||
- if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_OFFCHAN]))
|
||||
- return cfg80211_start_offchan_radar_detection(rdev, wdev,
|
||||
- &chandef);
|
||||
+ if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_OFFCHAN])) {
|
||||
+ err = cfg80211_start_offchan_radar_detection(rdev, wdev,
|
||||
+ &chandef);
|
||||
+ goto unlock;
|
||||
+ }
|
||||
|
||||
- if (netif_carrier_ok(dev))
|
||||
- return -EBUSY;
|
||||
+ if (netif_carrier_ok(dev)) {
|
||||
+ err = -EBUSY;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
|
||||
- if (wdev->cac_started)
|
||||
- return -EBUSY;
|
||||
+ if (wdev->cac_started) {
|
||||
+ err = -EBUSY;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
|
||||
/* CAC start is offloaded to HW and can't be started manually */
|
||||
- if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
|
||||
- return -EOPNOTSUPP;
|
||||
+ if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) {
|
||||
+ err = -EOPNOTSUPP;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
|
||||
- if (!rdev->ops->start_radar_detection)
|
||||
- return -EOPNOTSUPP;
|
||||
+ if (!rdev->ops->start_radar_detection) {
|
||||
+ err = -EOPNOTSUPP;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
|
||||
cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
|
||||
if (WARN_ON(!cac_time_ms))
|
||||
@@ -9326,6 +9344,9 @@ static int nl80211_start_radar_detection
|
||||
wdev->cac_start_time = jiffies;
|
||||
wdev->cac_time_ms = cac_time_ms;
|
||||
}
|
||||
+unlock:
|
||||
+ wiphy_unlock(wiphy);
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -15961,7 +15982,8 @@ static const struct genl_small_ops nl802
|
||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
.doit = nl80211_start_radar_detection,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
|
||||
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
+ NL80211_FLAG_NO_WIPHY_MTX,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
|
@ -1,67 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 23 Oct 2021 11:10:51 +0200
|
||||
Subject: [PATCH] mac80211: introduce set_radar_offchan callback
|
||||
|
||||
Similar to cfg80211, introduce set_radar_offchan callback in mac80211_ops
|
||||
in order to configure a dedicated offchannel chain available on some hw
|
||||
(e.g. mt7915) to perform offchannel CAC detection and avoid tx/rx downtime.
|
||||
|
||||
Tested-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/201110606d4f3a7dfdf31440e351f2e2c375d4f0.1634979655.git.lorenzo@kernel.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -3937,6 +3937,14 @@ struct ieee80211_prep_tx_info {
|
||||
* twt structure.
|
||||
* @twt_teardown_request: Update the hw with TWT teardown request received
|
||||
* from the peer.
|
||||
+ * @set_radar_offchan: Configure dedicated offchannel chain available for
|
||||
+ * radar/CAC detection on some hw. This chain can't be used to transmit
|
||||
+ * or receive frames and it is bounded to a running wdev.
|
||||
+ * Offchannel radar/CAC detection allows to avoid the CAC downtime
|
||||
+ * switching to a different channel during CAC detection on the selected
|
||||
+ * radar channel.
|
||||
+ * The caller is expected to set chandef pointer to NULL in order to
|
||||
+ * disable offchannel CAC/radar detection.
|
||||
* @net_fill_forward_path: Called from .ndo_fill_forward_path in order to
|
||||
* resolve a path for hardware flow offloading
|
||||
*/
|
||||
@@ -4267,6 +4275,8 @@ struct ieee80211_ops {
|
||||
struct ieee80211_twt_setup *twt);
|
||||
void (*twt_teardown_request)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, u8 flowid);
|
||||
+ int (*set_radar_offchan)(struct ieee80211_hw *hw,
|
||||
+ struct cfg80211_chan_def *chandef);
|
||||
#if LINUX_VERSION_IS_GEQ(5,10,0)
|
||||
int (*net_fill_forward_path)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -4341,6 +4341,18 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
+static int
|
||||
+ieee80211_set_radar_offchan(struct wiphy *wiphy,
|
||||
+ struct cfg80211_chan_def *chandef)
|
||||
+{
|
||||
+ struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
+
|
||||
+ if (!local->ops->set_radar_offchan)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return local->ops->set_radar_offchan(&local->hw, chandef);
|
||||
+}
|
||||
+
|
||||
const struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
@@ -4445,4 +4457,5 @@ const struct cfg80211_ops mac80211_confi
|
||||
.reset_tid_config = ieee80211_reset_tid_config,
|
||||
.set_sar_specs = ieee80211_set_sar_specs,
|
||||
.color_change = ieee80211_color_change,
|
||||
+ .set_radar_offchan = ieee80211_set_radar_offchan,
|
||||
};
|
@ -1,532 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Mon, 29 Nov 2021 14:11:24 +0100
|
||||
Subject: [PATCH] cfg80211: rename offchannel_chain structs to background_chain
|
||||
to avoid confusion with ETSI standard
|
||||
|
||||
ETSI standard defines "Offchannel CAC" as:
|
||||
"Off-Channel CAC is performed by a number of non-continuous checks
|
||||
spread over a period in time. This period, which is required to
|
||||
determine the presence of radar signals, is defined as the Off-Channel
|
||||
CAC Time..
|
||||
Minimum Off-Channel CAC Time 6 minutes and Maximum Off-Channel CAC Time
|
||||
4 hours..".
|
||||
mac80211 implementation refers to a dedicated hw chain used for continuous
|
||||
radar monitoring. Rename offchannel_* references to background_* in
|
||||
order to avoid confusion with ETSI standard.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/4204cc1d648d76b44557981713231e030a3bd991.1638190762.git.lorenzo@kernel.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -4058,14 +4058,14 @@ struct mgmt_frame_regs {
|
||||
*
|
||||
* @color_change: Initiate a color change.
|
||||
*
|
||||
- * @set_radar_offchan: Configure dedicated offchannel chain available for
|
||||
+ * @set_radar_background: Configure dedicated offchannel chain available for
|
||||
* radar/CAC detection on some hw. This chain can't be used to transmit
|
||||
* or receive frames and it is bounded to a running wdev.
|
||||
- * Offchannel radar/CAC detection allows to avoid the CAC downtime
|
||||
+ * Background radar/CAC detection allows to avoid the CAC downtime
|
||||
* switching to a different channel during CAC detection on the selected
|
||||
* radar channel.
|
||||
* The caller is expected to set chandef pointer to NULL in order to
|
||||
- * disable offchannel CAC/radar detection.
|
||||
+ * disable background CAC/radar detection.
|
||||
*/
|
||||
struct cfg80211_ops {
|
||||
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
|
||||
@@ -4396,8 +4396,8 @@ struct cfg80211_ops {
|
||||
int (*color_change)(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_color_change_settings *params);
|
||||
- int (*set_radar_offchan)(struct wiphy *wiphy,
|
||||
- struct cfg80211_chan_def *chandef);
|
||||
+ int (*set_radar_background)(struct wiphy *wiphy,
|
||||
+ struct cfg80211_chan_def *chandef);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -7601,9 +7601,9 @@ cfg80211_radar_event(struct wiphy *wiphy
|
||||
}
|
||||
|
||||
static inline void
|
||||
-cfg80211_offchan_radar_event(struct wiphy *wiphy,
|
||||
- struct cfg80211_chan_def *chandef,
|
||||
- gfp_t gfp)
|
||||
+cfg80211_background_radar_event(struct wiphy *wiphy,
|
||||
+ struct cfg80211_chan_def *chandef,
|
||||
+ gfp_t gfp)
|
||||
{
|
||||
__cfg80211_radar_event(wiphy, chandef, true, gfp);
|
||||
}
|
||||
@@ -7638,13 +7638,13 @@ void cfg80211_cac_event(struct net_devic
|
||||
enum nl80211_radar_event event, gfp_t gfp);
|
||||
|
||||
/**
|
||||
- * cfg80211_offchan_cac_abort - Channel Availability Check offchan abort event
|
||||
+ * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
|
||||
* @wiphy: the wiphy
|
||||
*
|
||||
* This function is called by the driver when a Channel Availability Check
|
||||
* (CAC) is aborted by a offchannel dedicated chain.
|
||||
*/
|
||||
-void cfg80211_offchan_cac_abort(struct wiphy *wiphy);
|
||||
+void cfg80211_background_cac_abort(struct wiphy *wiphy);
|
||||
|
||||
/**
|
||||
* cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -3937,14 +3937,14 @@ struct ieee80211_prep_tx_info {
|
||||
* twt structure.
|
||||
* @twt_teardown_request: Update the hw with TWT teardown request received
|
||||
* from the peer.
|
||||
- * @set_radar_offchan: Configure dedicated offchannel chain available for
|
||||
+ * @set_radar_background: Configure dedicated offchannel chain available for
|
||||
* radar/CAC detection on some hw. This chain can't be used to transmit
|
||||
* or receive frames and it is bounded to a running wdev.
|
||||
- * Offchannel radar/CAC detection allows to avoid the CAC downtime
|
||||
+ * Background radar/CAC detection allows to avoid the CAC downtime
|
||||
* switching to a different channel during CAC detection on the selected
|
||||
* radar channel.
|
||||
* The caller is expected to set chandef pointer to NULL in order to
|
||||
- * disable offchannel CAC/radar detection.
|
||||
+ * disable background CAC/radar detection.
|
||||
* @net_fill_forward_path: Called from .ndo_fill_forward_path in order to
|
||||
* resolve a path for hardware flow offloading
|
||||
*/
|
||||
@@ -4275,8 +4275,8 @@ struct ieee80211_ops {
|
||||
struct ieee80211_twt_setup *twt);
|
||||
void (*twt_teardown_request)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, u8 flowid);
|
||||
- int (*set_radar_offchan)(struct ieee80211_hw *hw,
|
||||
- struct cfg80211_chan_def *chandef);
|
||||
+ int (*set_radar_background)(struct ieee80211_hw *hw,
|
||||
+ struct cfg80211_chan_def *chandef);
|
||||
#if LINUX_VERSION_IS_GEQ(5,10,0)
|
||||
int (*net_fill_forward_path)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
--- a/include/uapi/linux/nl80211.h
|
||||
+++ b/include/uapi/linux/nl80211.h
|
||||
@@ -2608,10 +2608,10 @@ enum nl80211_commands {
|
||||
* Mandatory parameter for the transmitting interface to enable MBSSID.
|
||||
* Optional for the non-transmitting interfaces.
|
||||
*
|
||||
- * @NL80211_ATTR_RADAR_OFFCHAN: Configure dedicated offchannel chain available for
|
||||
- * radar/CAC detection on some hw. This chain can't be used to transmit
|
||||
- * or receive frames and it is bounded to a running wdev.
|
||||
- * Offchannel radar/CAC detection allows to avoid the CAC downtime
|
||||
+ * @NL80211_ATTR_RADAR_BACKGROUND: Configure dedicated offchannel chain
|
||||
+ * available for radar/CAC detection on some hw. This chain can't be used
|
||||
+ * to transmit or receive frames and it is bounded to a running wdev.
|
||||
+ * Background radar/CAC detection allows to avoid the CAC downtime
|
||||
* switching on a different channel during CAC detection on the selected
|
||||
* radar channel.
|
||||
*
|
||||
@@ -3121,7 +3121,7 @@ enum nl80211_attrs {
|
||||
NL80211_ATTR_MBSSID_CONFIG,
|
||||
NL80211_ATTR_MBSSID_ELEMS,
|
||||
|
||||
- NL80211_ATTR_RADAR_OFFCHAN,
|
||||
+ NL80211_ATTR_RADAR_BACKGROUND,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
@@ -6022,7 +6022,7 @@ enum nl80211_feature_flags {
|
||||
* @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
|
||||
* detection and change announcemnts.
|
||||
*
|
||||
- * @NL80211_EXT_FEATURE_RADAR_OFFCHAN: Device supports offchannel radar/CAC
|
||||
+ * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC
|
||||
* detection.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
@@ -6090,7 +6090,7 @@ enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_SECURE_RTT,
|
||||
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
|
||||
NL80211_EXT_FEATURE_BSS_COLOR,
|
||||
- NL80211_EXT_FEATURE_RADAR_OFFCHAN,
|
||||
+ NL80211_EXT_FEATURE_RADAR_BACKGROUND,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -4342,15 +4342,15 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
-ieee80211_set_radar_offchan(struct wiphy *wiphy,
|
||||
- struct cfg80211_chan_def *chandef)
|
||||
+ieee80211_set_radar_background(struct wiphy *wiphy,
|
||||
+ struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
|
||||
- if (!local->ops->set_radar_offchan)
|
||||
+ if (!local->ops->set_radar_background)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
- return local->ops->set_radar_offchan(&local->hw, chandef);
|
||||
+ return local->ops->set_radar_background(&local->hw, chandef);
|
||||
}
|
||||
|
||||
const struct cfg80211_ops mac80211_config_ops = {
|
||||
@@ -4457,5 +4457,5 @@ const struct cfg80211_ops mac80211_confi
|
||||
.reset_tid_config = ieee80211_reset_tid_config,
|
||||
.set_sar_specs = ieee80211_set_sar_specs,
|
||||
.color_change = ieee80211_color_change,
|
||||
- .set_radar_offchan = ieee80211_set_radar_offchan,
|
||||
+ .set_radar_background = ieee80211_set_radar_background,
|
||||
};
|
||||
--- a/net/wireless/chan.c
|
||||
+++ b/net/wireless/chan.c
|
||||
@@ -716,13 +716,13 @@ static bool
|
||||
cfg80211_offchan_chain_is_active(struct cfg80211_registered_device *rdev,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
- if (!rdev->offchan_radar_wdev)
|
||||
+ if (!rdev->background_radar_wdev)
|
||||
return false;
|
||||
|
||||
- if (!cfg80211_chandef_valid(&rdev->offchan_radar_chandef))
|
||||
+ if (!cfg80211_chandef_valid(&rdev->background_radar_chandef))
|
||||
return false;
|
||||
|
||||
- return cfg80211_is_sub_chan(&rdev->offchan_radar_chandef, channel);
|
||||
+ return cfg80211_is_sub_chan(&rdev->background_radar_chandef, channel);
|
||||
}
|
||||
|
||||
bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
|
||||
--- a/net/wireless/core.c
|
||||
+++ b/net/wireless/core.c
|
||||
@@ -543,9 +543,10 @@ use_default_name:
|
||||
INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work);
|
||||
INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
|
||||
INIT_WORK(&rdev->event_work, cfg80211_event_work);
|
||||
- INIT_WORK(&rdev->offchan_cac_abort_wk, cfg80211_offchan_cac_abort_wk);
|
||||
- INIT_DELAYED_WORK(&rdev->offchan_cac_done_wk,
|
||||
- cfg80211_offchan_cac_done_wk);
|
||||
+ INIT_WORK(&rdev->background_cac_abort_wk,
|
||||
+ cfg80211_background_cac_abort_wk);
|
||||
+ INIT_DELAYED_WORK(&rdev->background_cac_done_wk,
|
||||
+ cfg80211_background_cac_done_wk);
|
||||
|
||||
init_waitqueue_head(&rdev->dev_wait);
|
||||
|
||||
@@ -1055,13 +1056,13 @@ void wiphy_unregister(struct wiphy *wiph
|
||||
cancel_work_sync(&rdev->conn_work);
|
||||
flush_work(&rdev->event_work);
|
||||
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
|
||||
- cancel_delayed_work_sync(&rdev->offchan_cac_done_wk);
|
||||
+ cancel_delayed_work_sync(&rdev->background_cac_done_wk);
|
||||
flush_work(&rdev->destroy_work);
|
||||
flush_work(&rdev->sched_scan_stop_wk);
|
||||
flush_work(&rdev->propagate_radar_detect_wk);
|
||||
flush_work(&rdev->propagate_cac_done_wk);
|
||||
flush_work(&rdev->mgmt_registrations_update_wk);
|
||||
- flush_work(&rdev->offchan_cac_abort_wk);
|
||||
+ flush_work(&rdev->background_cac_abort_wk);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
|
||||
@@ -1210,7 +1211,7 @@ void __cfg80211_leave(struct cfg80211_re
|
||||
|
||||
cfg80211_pmsr_wdev_down(wdev);
|
||||
|
||||
- cfg80211_stop_offchan_radar_detection(wdev);
|
||||
+ cfg80211_stop_background_radar_detection(wdev);
|
||||
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
--- a/net/wireless/core.h
|
||||
+++ b/net/wireless/core.h
|
||||
@@ -84,10 +84,10 @@ struct cfg80211_registered_device {
|
||||
|
||||
struct delayed_work dfs_update_channels_wk;
|
||||
|
||||
- struct wireless_dev *offchan_radar_wdev;
|
||||
- struct cfg80211_chan_def offchan_radar_chandef;
|
||||
- struct delayed_work offchan_cac_done_wk;
|
||||
- struct work_struct offchan_cac_abort_wk;
|
||||
+ struct wireless_dev *background_radar_wdev;
|
||||
+ struct cfg80211_chan_def background_radar_chandef;
|
||||
+ struct delayed_work background_cac_done_wk;
|
||||
+ struct work_struct background_cac_abort_wk;
|
||||
|
||||
/* netlink port which started critical protocol (0 means not started) */
|
||||
u32 crit_proto_nlportid;
|
||||
@@ -497,15 +497,15 @@ cfg80211_chandef_dfs_cac_time(struct wip
|
||||
void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev);
|
||||
|
||||
int
|
||||
-cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev,
|
||||
- struct wireless_dev *wdev,
|
||||
- struct cfg80211_chan_def *chandef);
|
||||
+cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rdev,
|
||||
+ struct wireless_dev *wdev,
|
||||
+ struct cfg80211_chan_def *chandef);
|
||||
|
||||
-void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev);
|
||||
+void cfg80211_stop_background_radar_detection(struct wireless_dev *wdev);
|
||||
|
||||
-void cfg80211_offchan_cac_done_wk(struct work_struct *work);
|
||||
+void cfg80211_background_cac_done_wk(struct work_struct *work);
|
||||
|
||||
-void cfg80211_offchan_cac_abort_wk(struct work_struct *work);
|
||||
+void cfg80211_background_cac_abort_wk(struct work_struct *work);
|
||||
|
||||
bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *chan);
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -920,7 +920,7 @@ void __cfg80211_radar_event(struct wiphy
|
||||
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
|
||||
|
||||
if (offchan)
|
||||
- queue_work(cfg80211_wq, &rdev->offchan_cac_abort_wk);
|
||||
+ queue_work(cfg80211_wq, &rdev->background_cac_abort_wk);
|
||||
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
|
||||
@@ -975,10 +975,10 @@ void cfg80211_cac_event(struct net_devic
|
||||
EXPORT_SYMBOL(cfg80211_cac_event);
|
||||
|
||||
static void
|
||||
-__cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev,
|
||||
- struct wireless_dev *wdev,
|
||||
- const struct cfg80211_chan_def *chandef,
|
||||
- enum nl80211_radar_event event)
|
||||
+__cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
|
||||
+ struct wireless_dev *wdev,
|
||||
+ const struct cfg80211_chan_def *chandef,
|
||||
+ enum nl80211_radar_event event)
|
||||
{
|
||||
struct wiphy *wiphy = &rdev->wiphy;
|
||||
struct net_device *netdev;
|
||||
@@ -988,7 +988,7 @@ __cfg80211_offchan_cac_event(struct cfg8
|
||||
if (!cfg80211_chandef_valid(chandef))
|
||||
return;
|
||||
|
||||
- if (!rdev->offchan_radar_wdev)
|
||||
+ if (!rdev->background_radar_wdev)
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
@@ -997,12 +997,12 @@ __cfg80211_offchan_cac_event(struct cfg8
|
||||
memcpy(&rdev->cac_done_chandef, chandef, sizeof(*chandef));
|
||||
queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
- wdev = rdev->offchan_radar_wdev;
|
||||
+ wdev = rdev->background_radar_wdev;
|
||||
break;
|
||||
case NL80211_RADAR_CAC_ABORTED:
|
||||
- if (!cancel_delayed_work(&rdev->offchan_cac_done_wk))
|
||||
+ if (!cancel_delayed_work(&rdev->background_cac_done_wk))
|
||||
return;
|
||||
- wdev = rdev->offchan_radar_wdev;
|
||||
+ wdev = rdev->background_radar_wdev;
|
||||
break;
|
||||
case NL80211_RADAR_CAC_STARTED:
|
||||
break;
|
||||
@@ -1015,49 +1015,49 @@ __cfg80211_offchan_cac_event(struct cfg8
|
||||
}
|
||||
|
||||
static void
|
||||
-cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev,
|
||||
- const struct cfg80211_chan_def *chandef,
|
||||
- enum nl80211_radar_event event)
|
||||
+cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
|
||||
+ const struct cfg80211_chan_def *chandef,
|
||||
+ enum nl80211_radar_event event)
|
||||
{
|
||||
wiphy_lock(&rdev->wiphy);
|
||||
- __cfg80211_offchan_cac_event(rdev, rdev->offchan_radar_wdev,
|
||||
- chandef, event);
|
||||
+ __cfg80211_background_cac_event(rdev, rdev->background_radar_wdev,
|
||||
+ chandef, event);
|
||||
wiphy_unlock(&rdev->wiphy);
|
||||
}
|
||||
|
||||
-void cfg80211_offchan_cac_done_wk(struct work_struct *work)
|
||||
+void cfg80211_background_cac_done_wk(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work = to_delayed_work(work);
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
rdev = container_of(delayed_work, struct cfg80211_registered_device,
|
||||
- offchan_cac_done_wk);
|
||||
- cfg80211_offchan_cac_event(rdev, &rdev->offchan_radar_chandef,
|
||||
- NL80211_RADAR_CAC_FINISHED);
|
||||
+ background_cac_done_wk);
|
||||
+ cfg80211_background_cac_event(rdev, &rdev->background_radar_chandef,
|
||||
+ NL80211_RADAR_CAC_FINISHED);
|
||||
}
|
||||
|
||||
-void cfg80211_offchan_cac_abort_wk(struct work_struct *work)
|
||||
+void cfg80211_background_cac_abort_wk(struct work_struct *work)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
rdev = container_of(work, struct cfg80211_registered_device,
|
||||
- offchan_cac_abort_wk);
|
||||
- cfg80211_offchan_cac_event(rdev, &rdev->offchan_radar_chandef,
|
||||
- NL80211_RADAR_CAC_ABORTED);
|
||||
+ background_cac_abort_wk);
|
||||
+ cfg80211_background_cac_event(rdev, &rdev->background_radar_chandef,
|
||||
+ NL80211_RADAR_CAC_ABORTED);
|
||||
}
|
||||
|
||||
-void cfg80211_offchan_cac_abort(struct wiphy *wiphy)
|
||||
+void cfg80211_background_cac_abort(struct wiphy *wiphy)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
- queue_work(cfg80211_wq, &rdev->offchan_cac_abort_wk);
|
||||
+ queue_work(cfg80211_wq, &rdev->background_cac_abort_wk);
|
||||
}
|
||||
-EXPORT_SYMBOL(cfg80211_offchan_cac_abort);
|
||||
+EXPORT_SYMBOL(cfg80211_background_cac_abort);
|
||||
|
||||
int
|
||||
-cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev,
|
||||
- struct wireless_dev *wdev,
|
||||
- struct cfg80211_chan_def *chandef)
|
||||
+cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rdev,
|
||||
+ struct wireless_dev *wdev,
|
||||
+ struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
unsigned int cac_time_ms;
|
||||
int err;
|
||||
@@ -1065,19 +1065,19 @@ cfg80211_start_offchan_radar_detection(s
|
||||
lockdep_assert_wiphy(&rdev->wiphy);
|
||||
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
- NL80211_EXT_FEATURE_RADAR_OFFCHAN))
|
||||
+ NL80211_EXT_FEATURE_RADAR_BACKGROUND))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Offchannel chain already locked by another wdev */
|
||||
- if (rdev->offchan_radar_wdev && rdev->offchan_radar_wdev != wdev)
|
||||
+ if (rdev->background_radar_wdev && rdev->background_radar_wdev != wdev)
|
||||
return -EBUSY;
|
||||
|
||||
/* CAC already in progress on the offchannel chain */
|
||||
- if (rdev->offchan_radar_wdev == wdev &&
|
||||
- delayed_work_pending(&rdev->offchan_cac_done_wk))
|
||||
+ if (rdev->background_radar_wdev == wdev &&
|
||||
+ delayed_work_pending(&rdev->background_cac_done_wk))
|
||||
return -EBUSY;
|
||||
|
||||
- err = rdev_set_radar_offchan(rdev, chandef);
|
||||
+ err = rdev_set_radar_background(rdev, chandef);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1085,30 +1085,31 @@ cfg80211_start_offchan_radar_detection(s
|
||||
if (!cac_time_ms)
|
||||
cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
|
||||
|
||||
- rdev->offchan_radar_chandef = *chandef;
|
||||
- rdev->offchan_radar_wdev = wdev; /* Get offchain ownership */
|
||||
+ rdev->background_radar_chandef = *chandef;
|
||||
+ rdev->background_radar_wdev = wdev; /* Get offchain ownership */
|
||||
|
||||
- __cfg80211_offchan_cac_event(rdev, wdev, chandef,
|
||||
- NL80211_RADAR_CAC_STARTED);
|
||||
- queue_delayed_work(cfg80211_wq, &rdev->offchan_cac_done_wk,
|
||||
+ __cfg80211_background_cac_event(rdev, wdev, chandef,
|
||||
+ NL80211_RADAR_CAC_STARTED);
|
||||
+ queue_delayed_work(cfg80211_wq, &rdev->background_cac_done_wk,
|
||||
msecs_to_jiffies(cac_time_ms));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-void cfg80211_stop_offchan_radar_detection(struct wireless_dev *wdev)
|
||||
+void cfg80211_stop_background_radar_detection(struct wireless_dev *wdev)
|
||||
{
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
lockdep_assert_wiphy(wiphy);
|
||||
|
||||
- if (wdev != rdev->offchan_radar_wdev)
|
||||
+ if (wdev != rdev->background_radar_wdev)
|
||||
return;
|
||||
|
||||
- rdev_set_radar_offchan(rdev, NULL);
|
||||
- rdev->offchan_radar_wdev = NULL; /* Release offchain ownership */
|
||||
+ rdev_set_radar_background(rdev, NULL);
|
||||
+ rdev->background_radar_wdev = NULL; /* Release offchain ownership */
|
||||
|
||||
- __cfg80211_offchan_cac_event(rdev, wdev, &rdev->offchan_radar_chandef,
|
||||
- NL80211_RADAR_CAC_ABORTED);
|
||||
+ __cfg80211_background_cac_event(rdev, wdev,
|
||||
+ &rdev->background_radar_chandef,
|
||||
+ NL80211_RADAR_CAC_ABORTED);
|
||||
}
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -801,7 +801,7 @@ static const struct nla_policy nl80211_p
|
||||
[NL80211_ATTR_MBSSID_CONFIG] =
|
||||
NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
|
||||
[NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
|
||||
- [NL80211_ATTR_RADAR_OFFCHAN] = { .type = NLA_FLAG },
|
||||
+ [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@@ -9306,9 +9306,9 @@ static int nl80211_start_radar_detection
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
- if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_OFFCHAN])) {
|
||||
- err = cfg80211_start_offchan_radar_detection(rdev, wdev,
|
||||
- &chandef);
|
||||
+ if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) {
|
||||
+ err = cfg80211_start_background_radar_detection(rdev, wdev,
|
||||
+ &chandef);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
--- a/net/wireless/rdev-ops.h
|
||||
+++ b/net/wireless/rdev-ops.h
|
||||
@@ -1382,17 +1382,17 @@ static inline int rdev_color_change(stru
|
||||
}
|
||||
|
||||
static inline int
|
||||
-rdev_set_radar_offchan(struct cfg80211_registered_device *rdev,
|
||||
- struct cfg80211_chan_def *chandef)
|
||||
+rdev_set_radar_background(struct cfg80211_registered_device *rdev,
|
||||
+ struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct wiphy *wiphy = &rdev->wiphy;
|
||||
int ret;
|
||||
|
||||
- if (!rdev->ops->set_radar_offchan)
|
||||
+ if (!rdev->ops->set_radar_background)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
- trace_rdev_set_radar_offchan(wiphy, chandef);
|
||||
- ret = rdev->ops->set_radar_offchan(wiphy, chandef);
|
||||
+ trace_rdev_set_radar_background(wiphy, chandef);
|
||||
+ ret = rdev->ops->set_radar_background(wiphy, chandef);
|
||||
trace_rdev_return_int(wiphy, ret);
|
||||
|
||||
return ret;
|
||||
--- a/net/wireless/trace.h
|
||||
+++ b/net/wireless/trace.h
|
||||
@@ -3646,7 +3646,7 @@ TRACE_EVENT(cfg80211_bss_color_notify,
|
||||
__entry->color_bitmap)
|
||||
);
|
||||
|
||||
-TRACE_EVENT(rdev_set_radar_offchan,
|
||||
+TRACE_EVENT(rdev_set_radar_background,
|
||||
TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
|
||||
|
||||
TP_ARGS(wiphy, chandef),
|
@ -1,144 +0,0 @@
|
||||
From: John Crispin <john@phrozen.org>
|
||||
Date: Wed, 15 Sep 2021 19:54:35 -0700
|
||||
Subject: [PATCH] mac80211: MBSSID support in interface handling
|
||||
|
||||
Configure multiple BSSID and enhanced multi-BSSID advertisement (EMA)
|
||||
parameters in mac80211 for AP mode.
|
||||
|
||||
For each interface, 'mbssid_tx_vif' points to the transmitting interface of
|
||||
the MBSSID set. The pointer is set to NULL if MBSSID is disabled.
|
||||
|
||||
Function ieee80211_stop() is modified to always bring down all the
|
||||
non-transmitting interfaces first and the transmitting interface last.
|
||||
|
||||
Signed-off-by: John Crispin <john@phrozen.org>
|
||||
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
|
||||
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
|
||||
Link: https://lore.kernel.org/r/20210916025437.29138-3-alokad@codeaurora.org
|
||||
[slightly change logic to be more obvious]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -1719,6 +1719,7 @@ enum ieee80211_offload_flags {
|
||||
* write-protected by sdata_lock and local->mtx so holding either is fine
|
||||
* for read access.
|
||||
* @color_change_color: the bss color that will be used after the change.
|
||||
+ * @mbssid_tx_vif: Pointer to the transmitting interface if MBSSID is enabled.
|
||||
*/
|
||||
struct ieee80211_vif {
|
||||
enum nl80211_iftype type;
|
||||
@@ -1750,6 +1751,8 @@ struct ieee80211_vif {
|
||||
bool color_change_active;
|
||||
u8 color_change_color;
|
||||
|
||||
+ struct ieee80211_vif *mbssid_tx_vif;
|
||||
+
|
||||
/* must be last */
|
||||
u8 drv_priv[] __aligned(sizeof(void *));
|
||||
};
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -112,6 +112,36 @@ static int ieee80211_set_mon_options(str
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata,
|
||||
+ struct cfg80211_mbssid_config params)
|
||||
+{
|
||||
+ struct ieee80211_sub_if_data *tx_sdata;
|
||||
+
|
||||
+ sdata->vif.mbssid_tx_vif = NULL;
|
||||
+ sdata->vif.bss_conf.bssid_index = 0;
|
||||
+ sdata->vif.bss_conf.nontransmitted = false;
|
||||
+ sdata->vif.bss_conf.ema_ap = false;
|
||||
+
|
||||
+ if (sdata->vif.type != NL80211_IFTYPE_AP || !params.tx_wdev)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tx_sdata = IEEE80211_WDEV_TO_SUB_IF(params.tx_wdev);
|
||||
+ if (!tx_sdata)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (tx_sdata == sdata) {
|
||||
+ sdata->vif.mbssid_tx_vif = &sdata->vif;
|
||||
+ } else {
|
||||
+ sdata->vif.mbssid_tx_vif = &tx_sdata->vif;
|
||||
+ sdata->vif.bss_conf.nontransmitted = true;
|
||||
+ sdata->vif.bss_conf.bssid_index = params.index;
|
||||
+ }
|
||||
+ if (params.ema)
|
||||
+ sdata->vif.bss_conf.ema_ap = true;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
|
||||
const char *name,
|
||||
unsigned char name_assign_type,
|
||||
@@ -1107,6 +1137,14 @@ static int ieee80211_start_ap(struct wip
|
||||
changed |= BSS_CHANGED_HE_BSS_COLOR;
|
||||
}
|
||||
|
||||
+ if (sdata->vif.type == NL80211_IFTYPE_AP &&
|
||||
+ params->mbssid_config.tx_wdev) {
|
||||
+ err = ieee80211_set_ap_mbssid_options(sdata,
|
||||
+ params->mbssid_config);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
mutex_lock(&local->mtx);
|
||||
err = ieee80211_vif_use_channel(sdata, ¶ms->chandef,
|
||||
IEEE80211_CHANCTX_SHARED);
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -632,17 +632,46 @@ static void ieee80211_do_stop(struct iee
|
||||
ieee80211_add_virtual_monitor(local);
|
||||
}
|
||||
|
||||
+static void ieee80211_stop_mbssid(struct ieee80211_sub_if_data *sdata)
|
||||
+{
|
||||
+ struct ieee80211_sub_if_data *tx_sdata, *non_tx_sdata, *tmp_sdata;
|
||||
+ struct ieee80211_vif *tx_vif = sdata->vif.mbssid_tx_vif;
|
||||
+
|
||||
+ if (!tx_vif)
|
||||
+ return;
|
||||
+
|
||||
+ tx_sdata = vif_to_sdata(tx_vif);
|
||||
+ sdata->vif.mbssid_tx_vif = NULL;
|
||||
+
|
||||
+ list_for_each_entry_safe(non_tx_sdata, tmp_sdata,
|
||||
+ &tx_sdata->local->interfaces, list) {
|
||||
+ if (non_tx_sdata != sdata && non_tx_sdata != tx_sdata &&
|
||||
+ non_tx_sdata->vif.mbssid_tx_vif == tx_vif &&
|
||||
+ ieee80211_sdata_running(non_tx_sdata)) {
|
||||
+ non_tx_sdata->vif.mbssid_tx_vif = NULL;
|
||||
+ dev_close(non_tx_sdata->wdev.netdev);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (sdata != tx_sdata && ieee80211_sdata_running(tx_sdata)) {
|
||||
+ tx_sdata->vif.mbssid_tx_vif = NULL;
|
||||
+ dev_close(tx_sdata->wdev.netdev);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int ieee80211_stop(struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
- /* close all dependent VLAN interfaces before locking wiphy */
|
||||
+ /* close dependent VLAN and MBSSID interfaces before locking wiphy */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||
struct ieee80211_sub_if_data *vlan, *tmpsdata;
|
||||
|
||||
list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
|
||||
u.vlan.list)
|
||||
dev_close(vlan->dev);
|
||||
+
|
||||
+ ieee80211_stop_mbssid(sdata);
|
||||
}
|
||||
|
||||
wiphy_lock(sdata->local->hw.wiphy);
|
@ -1,326 +0,0 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 24 Feb 2022 12:54:58 +0100
|
||||
Subject: [PATCH] mac80211: MBSSID beacon handling in AP mode
|
||||
|
||||
Add new fields in struct beacon_data to store all MBSSID elements.
|
||||
Generate a beacon template which includes all MBSSID elements.
|
||||
Move CSA offset to reflect the MBSSID element length.
|
||||
|
||||
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
|
||||
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
|
||||
Co-developed-by: John Crispin <john@phrozen.org>
|
||||
Signed-off-by: John Crispin <john@phrozen.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Tested-by: Money Wang <money.wang@mediatek.com>
|
||||
Link: https://lore.kernel.org/r/5322db3c303f431adaf191ab31c45e151dde5465.1645702516.git.lorenzo@kernel.org
|
||||
[small cleanups]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -4938,12 +4938,14 @@ void ieee80211_report_low_ack(struct iee
|
||||
* @cntdwn_counter_offs: array of IEEE80211_MAX_CNTDWN_COUNTERS_NUM offsets
|
||||
* to countdown counters. This array can contain zero values which
|
||||
* should be ignored.
|
||||
+ * @mbssid_off: position of the multiple bssid element
|
||||
*/
|
||||
struct ieee80211_mutable_offsets {
|
||||
u16 tim_offset;
|
||||
u16 tim_length;
|
||||
|
||||
u16 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
|
||||
+ u16 mbssid_off;
|
||||
};
|
||||
|
||||
/**
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -989,11 +989,29 @@ static int ieee80211_set_ftm_responder_p
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int
|
||||
+ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst,
|
||||
+ struct cfg80211_mbssid_elems *src)
|
||||
+{
|
||||
+ int i, offset = 0;
|
||||
+
|
||||
+ for (i = 0; i < src->cnt; i++) {
|
||||
+ memcpy(pos + offset, src->elem[i].data, src->elem[i].len);
|
||||
+ dst->elem[i].len = src->elem[i].len;
|
||||
+ dst->elem[i].data = pos + offset;
|
||||
+ offset += dst->elem[i].len;
|
||||
+ }
|
||||
+ dst->cnt = src->cnt;
|
||||
+
|
||||
+ return offset;
|
||||
+}
|
||||
+
|
||||
static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_beacon_data *params,
|
||||
const struct ieee80211_csa_settings *csa,
|
||||
const struct ieee80211_color_change_settings *cca)
|
||||
{
|
||||
+ struct cfg80211_mbssid_elems *mbssid = NULL;
|
||||
struct beacon_data *new, *old;
|
||||
int new_head_len, new_tail_len;
|
||||
int size, err;
|
||||
@@ -1021,6 +1039,17 @@ static int ieee80211_assign_beacon(struc
|
||||
|
||||
size = sizeof(*new) + new_head_len + new_tail_len;
|
||||
|
||||
+ /* new or old multiple BSSID elements? */
|
||||
+ if (params->mbssid_ies) {
|
||||
+ mbssid = params->mbssid_ies;
|
||||
+ size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
|
||||
+ size += ieee80211_get_mbssid_beacon_len(mbssid);
|
||||
+ } else if (old && old->mbssid_ies) {
|
||||
+ mbssid = old->mbssid_ies;
|
||||
+ size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
|
||||
+ size += ieee80211_get_mbssid_beacon_len(mbssid);
|
||||
+ }
|
||||
+
|
||||
new = kzalloc(size, GFP_KERNEL);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
@@ -1029,12 +1058,20 @@ static int ieee80211_assign_beacon(struc
|
||||
|
||||
/*
|
||||
* pointers go into the block we allocated,
|
||||
- * memory is | beacon_data | head | tail |
|
||||
+ * memory is | beacon_data | head | tail | mbssid_ies
|
||||
*/
|
||||
new->head = ((u8 *) new) + sizeof(*new);
|
||||
new->tail = new->head + new_head_len;
|
||||
new->head_len = new_head_len;
|
||||
new->tail_len = new_tail_len;
|
||||
+ /* copy in optional mbssid_ies */
|
||||
+ if (mbssid) {
|
||||
+ u8 *pos = new->tail + new->tail_len;
|
||||
+
|
||||
+ new->mbssid_ies = (void *)pos;
|
||||
+ pos += struct_size(new->mbssid_ies, elem, mbssid->cnt);
|
||||
+ ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid);
|
||||
+ }
|
||||
|
||||
if (csa) {
|
||||
new->cntdwn_current_counter = csa->count;
|
||||
@@ -1332,8 +1369,11 @@ static int ieee80211_stop_ap(struct wiph
|
||||
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
- kfree(sdata->u.ap.next_beacon);
|
||||
- sdata->u.ap.next_beacon = NULL;
|
||||
+ if (sdata->u.ap.next_beacon) {
|
||||
+ kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
+ sdata->u.ap.next_beacon = NULL;
|
||||
+ }
|
||||
|
||||
/* turn off carrier for this interface and dependent VLANs */
|
||||
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
|
||||
@@ -3126,12 +3166,24 @@ cfg80211_beacon_dup(struct cfg80211_beac
|
||||
|
||||
len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len +
|
||||
beacon->proberesp_ies_len + beacon->assocresp_ies_len +
|
||||
- beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len;
|
||||
+ beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len +
|
||||
+ ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
|
||||
|
||||
new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL);
|
||||
if (!new_beacon)
|
||||
return NULL;
|
||||
|
||||
+ if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) {
|
||||
+ new_beacon->mbssid_ies =
|
||||
+ kzalloc(struct_size(new_beacon->mbssid_ies,
|
||||
+ elem, beacon->mbssid_ies->cnt),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!new_beacon->mbssid_ies) {
|
||||
+ kfree(new_beacon);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
pos = (u8 *)(new_beacon + 1);
|
||||
if (beacon->head_len) {
|
||||
new_beacon->head_len = beacon->head_len;
|
||||
@@ -3169,6 +3221,10 @@ cfg80211_beacon_dup(struct cfg80211_beac
|
||||
memcpy(pos, beacon->probe_resp, beacon->probe_resp_len);
|
||||
pos += beacon->probe_resp_len;
|
||||
}
|
||||
+ if (beacon->mbssid_ies && beacon->mbssid_ies->cnt)
|
||||
+ pos += ieee80211_copy_mbssid_beacon(pos,
|
||||
+ new_beacon->mbssid_ies,
|
||||
+ beacon->mbssid_ies);
|
||||
|
||||
/* might copy -1, meaning no changes requested */
|
||||
new_beacon->ftm_responder = beacon->ftm_responder;
|
||||
@@ -3206,8 +3262,11 @@ static int ieee80211_set_after_csa_beaco
|
||||
case NL80211_IFTYPE_AP:
|
||||
err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
||||
NULL, NULL);
|
||||
- kfree(sdata->u.ap.next_beacon);
|
||||
- sdata->u.ap.next_beacon = NULL;
|
||||
+ if (sdata->u.ap.next_beacon) {
|
||||
+ kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
+ sdata->u.ap.next_beacon = NULL;
|
||||
+ }
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
@@ -3362,8 +3421,12 @@ static int ieee80211_set_csa_beacon(stru
|
||||
if ((params->n_counter_offsets_beacon >
|
||||
IEEE80211_MAX_CNTDWN_COUNTERS_NUM) ||
|
||||
(params->n_counter_offsets_presp >
|
||||
- IEEE80211_MAX_CNTDWN_COUNTERS_NUM))
|
||||
+ IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) {
|
||||
+ kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
+ sdata->u.ap.next_beacon = NULL;
|
||||
return -EINVAL;
|
||||
+ }
|
||||
|
||||
csa.counter_offsets_beacon = params->counter_offsets_beacon;
|
||||
csa.counter_offsets_presp = params->counter_offsets_presp;
|
||||
@@ -3373,7 +3436,9 @@ static int ieee80211_set_csa_beacon(stru
|
||||
|
||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL);
|
||||
if (err < 0) {
|
||||
+ kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
+ sdata->u.ap.next_beacon = NULL;
|
||||
return err;
|
||||
}
|
||||
*changed |= err;
|
||||
@@ -3460,8 +3525,11 @@ static int ieee80211_set_csa_beacon(stru
|
||||
static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
sdata->vif.color_change_active = false;
|
||||
- kfree(sdata->u.ap.next_beacon);
|
||||
- sdata->u.ap.next_beacon = NULL;
|
||||
+ if (sdata->u.ap.next_beacon) {
|
||||
+ kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
+ sdata->u.ap.next_beacon = NULL;
|
||||
+ }
|
||||
|
||||
cfg80211_color_change_aborted_notify(sdata->dev);
|
||||
}
|
||||
@@ -4199,8 +4267,11 @@ ieee80211_set_after_color_change_beacon(
|
||||
|
||||
ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
||||
NULL, NULL);
|
||||
- kfree(sdata->u.ap.next_beacon);
|
||||
- sdata->u.ap.next_beacon = NULL;
|
||||
+ if (sdata->u.ap.next_beacon) {
|
||||
+ kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
+ sdata->u.ap.next_beacon = NULL;
|
||||
+ }
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -4243,7 +4314,11 @@ ieee80211_set_color_change_beacon(struct
|
||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change,
|
||||
NULL, &color_change);
|
||||
if (err < 0) {
|
||||
- kfree(sdata->u.ap.next_beacon);
|
||||
+ if (sdata->u.ap.next_beacon) {
|
||||
+ kfree(sdata->u.ap.next_beacon->mbssid_ies);
|
||||
+ kfree(sdata->u.ap.next_beacon);
|
||||
+ sdata->u.ap.next_beacon = NULL;
|
||||
+ }
|
||||
return err;
|
||||
}
|
||||
*changed |= err;
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -261,6 +261,7 @@ struct beacon_data {
|
||||
struct ieee80211_meshconf_ie *meshconf;
|
||||
u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
|
||||
u8 cntdwn_current_counter;
|
||||
+ struct cfg80211_mbssid_elems *mbssid_ies;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
@@ -1082,6 +1083,20 @@ ieee80211_vif_get_shift(struct ieee80211
|
||||
return shift;
|
||||
}
|
||||
|
||||
+static inline int
|
||||
+ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems)
|
||||
+{
|
||||
+ int i, len = 0;
|
||||
+
|
||||
+ if (!elems)
|
||||
+ return 0;
|
||||
+
|
||||
+ for (i = 0; i < elems->cnt; i++)
|
||||
+ len += elems->elem[i].len;
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
enum {
|
||||
IEEE80211_RX_MSG = 1,
|
||||
IEEE80211_TX_STATUS_MSG = 2,
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -5041,6 +5041,19 @@ ieee80211_beacon_get_finish(struct ieee8
|
||||
IEEE80211_TX_CTL_FIRST_FRAGMENT;
|
||||
}
|
||||
|
||||
+static void
|
||||
+ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ if (!beacon->mbssid_ies)
|
||||
+ return;
|
||||
+
|
||||
+ for (i = 0; i < beacon->mbssid_ies->cnt; i++)
|
||||
+ skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
|
||||
+ beacon->mbssid_ies->elem[i].len);
|
||||
+}
|
||||
+
|
||||
static struct sk_buff *
|
||||
ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
@@ -5054,6 +5067,7 @@ ieee80211_beacon_get_ap(struct ieee80211
|
||||
struct ieee80211_if_ap *ap = &sdata->u.ap;
|
||||
struct sk_buff *skb = NULL;
|
||||
u16 csa_off_base = 0;
|
||||
+ int mbssid_len;
|
||||
|
||||
if (beacon->cntdwn_counter_offsets[0]) {
|
||||
if (!is_template)
|
||||
@@ -5063,11 +5077,12 @@ ieee80211_beacon_get_ap(struct ieee80211
|
||||
}
|
||||
|
||||
/* headroom, head length,
|
||||
- * tail length and maximum TIM length
|
||||
+ * tail length, maximum TIM length and multiple BSSID length
|
||||
*/
|
||||
+ mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
|
||||
skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
|
||||
beacon->tail_len + 256 +
|
||||
- local->hw.extra_beacon_tailroom);
|
||||
+ local->hw.extra_beacon_tailroom + mbssid_len);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
@@ -5081,6 +5096,11 @@ ieee80211_beacon_get_ap(struct ieee80211
|
||||
offs->tim_length = skb->len - beacon->head_len;
|
||||
offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
|
||||
|
||||
+ if (mbssid_len) {
|
||||
+ ieee80211_beacon_add_mbssid(skb, beacon);
|
||||
+ offs->mbssid_off = skb->len - mbssid_len;
|
||||
+ }
|
||||
+
|
||||
/* for AP the csa offsets are from tail */
|
||||
csa_off_base = skb->len;
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
From: John Crispin <john@phrozen.org>
|
||||
Date: Thu, 24 Feb 2022 12:54:59 +0100
|
||||
Subject: [PATCH] mac80211: MBSSID channel switch
|
||||
|
||||
Trigger ieee80211_csa_finish() on the non-transmitting interfaces
|
||||
when channel switch concludes on the transmitting interface.
|
||||
|
||||
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
|
||||
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
|
||||
Signed-off-by: John Crispin <john@phrozen.org>
|
||||
Link: https://lore.kernel.org/r/6fde4d7f9fa387494f46a7aa4a584478dcda06f1.1645702516.git.lorenzo@kernel.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -3247,9 +3247,31 @@ cfg80211_beacon_dup(struct cfg80211_beac
|
||||
void ieee80211_csa_finish(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
+ struct ieee80211_local *local = sdata->local;
|
||||
|
||||
- ieee80211_queue_work(&sdata->local->hw,
|
||||
- &sdata->csa_finalize_work);
|
||||
+ rcu_read_lock();
|
||||
+
|
||||
+ if (vif->mbssid_tx_vif == vif) {
|
||||
+ /* Trigger ieee80211_csa_finish() on the non-transmitting
|
||||
+ * interfaces when channel switch is received on
|
||||
+ * transmitting interface
|
||||
+ */
|
||||
+ struct ieee80211_sub_if_data *iter;
|
||||
+
|
||||
+ list_for_each_entry_rcu(iter, &local->interfaces, list) {
|
||||
+ if (!ieee80211_sdata_running(iter))
|
||||
+ continue;
|
||||
+
|
||||
+ if (iter == sdata || iter->vif.mbssid_tx_vif != vif)
|
||||
+ continue;
|
||||
+
|
||||
+ ieee80211_queue_work(&iter->local->hw,
|
||||
+ &iter->csa_finalize_work);
|
||||
+ }
|
||||
+ }
|
||||
+ ieee80211_queue_work(&local->hw, &sdata->csa_finalize_work);
|
||||
+
|
||||
+ rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_finish);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user