* @IWL_MLD_EMLSR_EXIT_FAIL_ENTRY: FW failed to enter EMLSR
* @IWL_MLD_EMLSR_EXIT_CSA: EMLSR prevented due to channel switch on link
* @IWL_MLD_EMLSR_EXIT_EQUAL_BAND: EMLSR prevented as both links share the band
- * @IWL_MLD_EMLSR_EXIT_BANDWIDTH: Bandwidths of primary and secondary links are
- * not equal
* @IWL_MLD_EMLSR_EXIT_LOW_RSSI: Link RSSI is unsuitable for EMLSR
* @IWL_MLD_EMLSR_EXIT_LINK_USAGE: Exit EMLSR due to low TPT on secondary link
* @IWL_MLD_EMLSR_EXIT_BT_COEX: Exit EMLSR due to BT coexistence
IWL_MLD_EMLSR_EXIT_FAIL_ENTRY = 0x4,
IWL_MLD_EMLSR_EXIT_CSA = 0x8,
IWL_MLD_EMLSR_EXIT_EQUAL_BAND = 0x10,
- IWL_MLD_EMLSR_EXIT_BANDWIDTH = 0x20,
- IWL_MLD_EMLSR_EXIT_LOW_RSSI = 0x40,
- IWL_MLD_EMLSR_EXIT_LINK_USAGE = 0x80,
- IWL_MLD_EMLSR_EXIT_BT_COEX = 0x100,
- IWL_MLD_EMLSR_EXIT_CHAN_LOAD = 0x200,
- IWL_MLD_EMLSR_EXIT_RFI = 0x400,
- IWL_MLD_EMLSR_EXIT_FW_REQUEST = 0x800,
+ IWL_MLD_EMLSR_EXIT_LOW_RSSI = 0x20,
+ IWL_MLD_EMLSR_EXIT_LINK_USAGE = 0x40,
+ IWL_MLD_EMLSR_EXIT_BT_COEX = 0x80,
+ IWL_MLD_EMLSR_EXIT_CHAN_LOAD = 0x100,
+ IWL_MLD_EMLSR_EXIT_RFI = 0x200,
+ IWL_MLD_EMLSR_EXIT_FW_REQUEST = 0x400,
};
/**
bw = ieee80211_chan_width_to_rx_bw(link_conf->chanreq.oper.width);
iwl_mld_omi_ap_changed_bw(mld, link_conf, bw);
- }
- if (changes & BSS_CHANGED_BANDWIDTH) {
- if (iwl_mld_emlsr_active(vif))
- iwl_mld_emlsr_check_equal_bw(mld, vif, link_conf);
- else
- /* Channel load threshold may have changed */
- iwl_mld_retry_emlsr(mld, vif);
}
+
+ if (changes & BSS_CHANGED_BANDWIDTH)
+ iwl_mld_retry_emlsr(mld, vif);
}
static int iwl_mld_update_mu_groups(struct iwl_mld *mld,
HOW(FAIL_ENTRY) \
HOW(CSA) \
HOW(EQUAL_BAND) \
- HOW(BANDWIDTH) \
HOW(LOW_RSSI) \
HOW(LINK_USAGE) \
HOW(BT_COEX) \
struct iwl_mld_link *link_a =
iwl_mld_link_dereference_check(mld_vif, a->link_id);
struct ieee80211_chanctx_conf *chanctx_a = NULL;
+ u32 bw_a, bw_b, ratio;
u32 primary_load_perc;
if (!link_a || !link_a->active) {
IWL_DEBUG_EHT(mld, "Average channel load not by us: %u\n", primary_load_perc);
- return primary_load_perc > iwl_mld_get_min_chan_load_thresh(chanctx_a);
+ if (primary_load_perc < iwl_mld_get_min_chan_load_thresh(chanctx_a)) {
+ IWL_DEBUG_EHT(mld, "Channel load is below the minimum threshold\n");
+ return false;
+ }
+
+ if (iwl_mld_vif_low_latency(mld_vif)) {
+ IWL_DEBUG_EHT(mld, "Low latency vif, EMLSR is allowed\n");
+ return true;
+ }
+
+ if (a->chandef->width <= b->chandef->width)
+ return true;
+
+ bw_a = nl80211_chan_width_to_mhz(a->chandef->width);
+ bw_b = nl80211_chan_width_to_mhz(b->chandef->width);
+ ratio = bw_a / bw_b;
+
+ switch (ratio) {
+ case 2:
+ return primary_load_perc > 25;
+ case 4:
+ return primary_load_perc > 40;
+ case 8:
+ case 16:
+ return primary_load_perc > 50;
+ }
+
+ return false;
}
static bool
if (a->chandef->chan->band == b->chandef->chan->band)
reason_mask |= IWL_MLD_EMLSR_EXIT_EQUAL_BAND;
- if (a->chandef->width != b->chandef->width) {
- /* TODO: task=EMLSR task=statistics
- * replace BANDWIDTH exit reason with channel load criteria
- */
- reason_mask |= IWL_MLD_EMLSR_EXIT_BANDWIDTH;
- }
if (!iwl_mld_channel_load_allows_emlsr(mld, vif, a, b))
reason_mask |= IWL_MLD_EMLSR_EXIT_CHAN_LOAD;
NULL);
}
-void iwl_mld_emlsr_check_equal_bw(struct iwl_mld *mld,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *link)
-{
- u8 other_link_id = iwl_mld_get_other_link(vif, link->link_id);
- struct ieee80211_bss_conf *other_link =
- link_conf_dereference_check(vif, other_link_id);
-
- if (!ieee80211_vif_link_active(vif, link->link_id) ||
- WARN_ON(link->link_id == other_link_id || !other_link))
- return;
-
- if (link->chanreq.oper.width != other_link->chanreq.oper.width)
- iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BANDWIDTH,
- iwl_mld_get_primary_link(vif));
-}
-
static void iwl_mld_emlsr_check_bt_iter(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
} else {
u32 old_chan_load = data->prev_chan_load_not_by_us;
u32 new_chan_load = phy->avg_channel_load_not_by_us;
- u32 thresh = iwl_mld_get_min_chan_load_thresh(chanctx);
+ u32 min_thresh = iwl_mld_get_min_chan_load_thresh(chanctx);
+
+#define THRESHOLD_CROSSED(threshold) \
+ (old_chan_load <= (threshold) && new_chan_load > (threshold))
- if (old_chan_load <= thresh && new_chan_load > thresh)
+ if (THRESHOLD_CROSSED(min_thresh) || THRESHOLD_CROSSED(25) ||
+ THRESHOLD_CROSSED(40) || THRESHOLD_CROSSED(50))
iwl_mld_retry_emlsr(mld, vif);
+#undef THRESHOLD_CROSSED
}
}