mirror of https://gitee.com/openkylin/linux.git
iwlwifi: mvm: add an option to dereference vif by id
Currently whenever we get firmware notification with mac id, we iterate over all the interfaces to find the ID. This is a bit cumbersome. Instead, adding an array of RCU pointers, like we have for station IDs. This is not expensive space wise since we have only up to 4 active MACs, and not complicated code wise, since we have a clear point to init and de-init it. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
fefbf85305
commit
698478c492
|
@ -1382,35 +1382,47 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
|
|||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_missed_beacons_notif *missed_beacons = _data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_missed_beacons_notif *mb = (void *)pkt->data;
|
||||
struct iwl_fw_dbg_trigger_missed_bcon *bcon_trig;
|
||||
struct iwl_fw_dbg_trigger_tlv *trigger;
|
||||
u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx;
|
||||
u32 rx_missed_bcon, rx_missed_bcon_since_rx;
|
||||
struct ieee80211_vif *vif;
|
||||
u32 id = le32_to_cpu(mb->mac_id);
|
||||
|
||||
if (mvmvif->id != (u16)le32_to_cpu(missed_beacons->mac_id))
|
||||
return;
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
|
||||
le32_to_cpu(mb->mac_id),
|
||||
le32_to_cpu(mb->consec_missed_beacons),
|
||||
le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
|
||||
le32_to_cpu(mb->num_recvd_beacons),
|
||||
le32_to_cpu(mb->num_expected_beacons));
|
||||
|
||||
rx_missed_bcon = le32_to_cpu(missed_beacons->consec_missed_beacons);
|
||||
rcu_read_lock();
|
||||
|
||||
vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
|
||||
if (!vif)
|
||||
goto out;
|
||||
|
||||
rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons);
|
||||
rx_missed_bcon_since_rx =
|
||||
le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx);
|
||||
le32_to_cpu(mb->consec_missed_beacons_since_last_rx);
|
||||
/*
|
||||
* TODO: the threshold should be adjusted based on latency conditions,
|
||||
* and/or in case of a CS flow on one of the other AP vifs.
|
||||
*/
|
||||
if (le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx) >
|
||||
if (le32_to_cpu(mb->consec_missed_beacons_since_last_rx) >
|
||||
IWL_MVM_MISSED_BEACONS_THRESHOLD)
|
||||
ieee80211_beacon_loss(vif);
|
||||
|
||||
trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
|
||||
FW_DBG_TRIGGER_MISSED_BEACONS);
|
||||
if (!trigger)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
bcon_trig = (void *)trigger->data;
|
||||
stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon);
|
||||
|
@ -1422,28 +1434,11 @@ static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
|
|||
if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx ||
|
||||
rx_missed_bcon >= stop_trig_missed_bcon)
|
||||
iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_missed_beacons_notif *mb = (void *)pkt->data;
|
||||
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
|
||||
le32_to_cpu(mb->mac_id),
|
||||
le32_to_cpu(mb->consec_missed_beacons),
|
||||
le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
|
||||
le32_to_cpu(mb->num_recvd_beacons),
|
||||
le32_to_cpu(mb->num_expected_beacons));
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_beacon_loss_iterator,
|
||||
mb);
|
||||
|
||||
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_MISSED_BEACONS);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
|
||||
|
@ -1485,16 +1480,29 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
|
|||
ieee80211_rx_napi(mvm->hw, NULL, skb, NULL);
|
||||
}
|
||||
|
||||
static void iwl_mvm_probe_resp_data_iter(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_probe_resp_data_notif *notif = _data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_probe_resp_data_notif *notif = (void *)pkt->data;
|
||||
struct iwl_probe_resp_data *old_data, *new_data;
|
||||
int len = iwl_rx_packet_payload_len(pkt);
|
||||
u32 id = le32_to_cpu(notif->mac_id);
|
||||
struct ieee80211_vif *vif;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
|
||||
if (mvmvif->id != (u16)le32_to_cpu(notif->mac_id))
|
||||
if (WARN_ON_ONCE(len < sizeof(*notif)))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n",
|
||||
notif->noa_active, notif->csa_counter);
|
||||
|
||||
vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
|
||||
if (!vif)
|
||||
return;
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
|
||||
if (!new_data)
|
||||
return;
|
||||
|
@ -1525,25 +1533,6 @@ static void iwl_mvm_probe_resp_data_iter(void *_data, u8 *mac,
|
|||
ieee80211_csa_set_counter(vif, notif->csa_counter);
|
||||
}
|
||||
|
||||
void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_probe_resp_data_notif *notif = (void *)pkt->data;
|
||||
int len = iwl_rx_packet_payload_len(pkt);
|
||||
|
||||
if (WARN_ON_ONCE(len < sizeof(*notif)))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n",
|
||||
notif->noa_active, notif->csa_counter);
|
||||
|
||||
ieee80211_iterate_active_interfaces(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_ACTIVE,
|
||||
iwl_mvm_probe_resp_data_iter,
|
||||
notif);
|
||||
}
|
||||
|
||||
void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
|
|
|
@ -1471,6 +1471,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
|
||||
|
||||
/* Counting number of interfaces is needed for legacy PM */
|
||||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
|
||||
mvm->vif_count++;
|
||||
|
@ -1662,6 +1664,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
iwl_mvm_power_update_mac(mvm);
|
||||
iwl_mvm_mac_ctxt_remove(mvm, vif);
|
||||
|
||||
RCU_INIT_POINTER(mvm->vif_id_to_mac[mvmvif->id], NULL);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_MONITOR)
|
||||
mvm->monitor_on = false;
|
||||
|
||||
|
|
|
@ -989,6 +989,7 @@ struct iwl_mvm {
|
|||
u8 refs[IWL_MVM_REF_COUNT];
|
||||
|
||||
u8 vif_count;
|
||||
struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
|
||||
|
||||
/* -1 for always, 0 for never, >0 for that many times */
|
||||
s8 fw_restart;
|
||||
|
@ -1241,6 +1242,19 @@ iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id)
|
|||
return iwl_mvm_sta_from_mac80211(sta);
|
||||
}
|
||||
|
||||
static inline struct ieee80211_vif *
|
||||
iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu)
|
||||
{
|
||||
if (WARN_ON(vif_id >= ARRAY_SIZE(mvm->vif_id_to_mac)))
|
||||
return NULL;
|
||||
|
||||
if (rcu)
|
||||
return rcu_dereference(mvm->vif_id_to_mac[vif_id]);
|
||||
|
||||
return rcu_dereference_protected(mvm->vif_id_to_mac[vif_id],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
return !iwlwifi_mod_params.d0i3_disable &&
|
||||
|
|
|
@ -1136,19 +1136,14 @@ static void iwl_mvm_tcm_uapsd_nonagg_detected_wk(struct work_struct *wk)
|
|||
"AP isn't using AMPDU with uAPSD enabled");
|
||||
}
|
||||
|
||||
static void iwl_mvm_uapsd_agg_disconnect_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
static void iwl_mvm_uapsd_agg_disconnect(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
int *mac_id = data;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
if (mvmvif->id != *mac_id)
|
||||
return;
|
||||
|
||||
if (!vif->bss_conf.assoc)
|
||||
return;
|
||||
|
||||
|
@ -1158,10 +1153,10 @@ static void iwl_mvm_uapsd_agg_disconnect_iter(void *data, u8 *mac,
|
|||
!mvmvif->queue_params[IEEE80211_AC_BK].uapsd)
|
||||
return;
|
||||
|
||||
if (mvm->tcm.data[*mac_id].uapsd_nonagg_detect.detected)
|
||||
if (mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected)
|
||||
return;
|
||||
|
||||
mvm->tcm.data[*mac_id].uapsd_nonagg_detect.detected = true;
|
||||
mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected = true;
|
||||
IWL_INFO(mvm,
|
||||
"detected AP should do aggregation but isn't, likely due to U-APSD\n");
|
||||
schedule_delayed_work(&mvmvif->uapsd_nonagg_detected_wk, 15 * HZ);
|
||||
|
@ -1174,6 +1169,7 @@ static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm,
|
|||
u64 bytes = mvm->tcm.data[mac].uapsd_nonagg_detect.rx_bytes;
|
||||
u64 tpt;
|
||||
unsigned long rate;
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
rate = ewma_rate_read(&mvm->tcm.data[mac].uapsd_nonagg_detect.rate);
|
||||
|
||||
|
@ -1202,9 +1198,11 @@ static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm,
|
|||
return;
|
||||
}
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_uapsd_agg_disconnect_iter, &mac);
|
||||
rcu_read_lock();
|
||||
vif = rcu_dereference(mvm->vif_id_to_mac[mac]);
|
||||
if (vif)
|
||||
iwl_mvm_uapsd_agg_disconnect(mvm, vif);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void iwl_mvm_tcm_iterator(void *_data, u8 *mac,
|
||||
|
|
Loading…
Reference in New Issue