From 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 22 Oct 2024 10:36:11 +0000
Subject: [PATCH] 修改4g拨号为QMI,需要在系统里后台执行quectel-CM
---
kernel/drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 264 +++++++++++++++++++++++++++++++---------------------
1 files changed, 158 insertions(+), 106 deletions(-)
diff --git a/kernel/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/kernel/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index bdb87d8..0059c83 100644
--- a/kernel/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/kernel/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -17,11 +18,6 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
@@ -34,6 +30,8 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -228,7 +226,7 @@
!(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK))
return 0;
*crypt_len = IEEE80211_TKIP_IV_LEN;
- /* fall through if TTAK OK */
+ /* fall through */
case RX_MPDU_RES_STATUS_SEC_WEP_ENC:
if (!(rx_pkt_status & RX_MPDU_RES_STATUS_ICV_OK))
@@ -355,7 +353,6 @@
u32 rate_n_flags;
u32 rx_pkt_status;
u8 crypt_len = 0;
- bool take_ref;
phy_info = &mvm->last_phy_info;
rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data;
@@ -423,7 +420,7 @@
id >>= RX_MDPU_RES_STATUS_STA_ID_SHIFT;
- if (!WARN_ON_ONCE(id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))) {
+ if (!WARN_ON_ONCE(id >= mvm->fw->ucode_capa.num_stations)) {
sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);
if (IS_ERR(sta))
sta = NULL;
@@ -439,13 +436,14 @@
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct ieee80211_vif *tx_blocked_vif =
rcu_dereference(mvm->csa_tx_blocked_vif);
+ struct iwl_fw_dbg_trigger_tlv *trig;
+ struct ieee80211_vif *vif = mvmsta->vif;
/* We have tx blocked stations (with CS bit). If we heard
* frames from a blocked station on a new channel we can
* TX to it again.
*/
- if (unlikely(tx_blocked_vif) &&
- mvmsta->vif == tx_blocked_vif) {
+ if (unlikely(tx_blocked_vif) && vif == tx_blocked_vif) {
struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(tx_blocked_vif);
@@ -456,23 +454,18 @@
rs_update_last_rssi(mvm, mvmsta, rx_status);
- if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) &&
- ieee80211_is_beacon(hdr->frame_control)) {
- struct iwl_fw_dbg_trigger_tlv *trig;
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt,
+ ieee80211_vif_to_wdev(vif),
+ FW_DBG_TRIGGER_RSSI);
+
+ if (trig && ieee80211_is_beacon(hdr->frame_control)) {
struct iwl_fw_dbg_trigger_low_rssi *rssi_trig;
- bool trig_check;
s32 rssi;
- trig = iwl_fw_dbg_get_trigger(mvm->fw,
- FW_DBG_TRIGGER_RSSI);
rssi_trig = (void *)trig->data;
rssi = le32_to_cpu(rssi_trig->rssi);
- trig_check =
- iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
- ieee80211_vif_to_wdev(mvmsta->vif),
- trig);
- if (trig_check && rx_status->signal < rssi)
+ if (rx_status->signal < rssi)
iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,
NULL);
}
@@ -565,24 +558,10 @@
if (unlikely(ieee80211_is_beacon(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control)))
- rx_status->boottime_ns = ktime_get_boot_ns();
-
- /* Take a reference briefly to kick off a d0i3 entry delay so
- * we can handle bursts of RX packets without toggling the
- * state too often. But don't do this for beacons if we are
- * going to idle because the beacon filtering changes we make
- * cause the firmware to send us collateral beacons. */
- take_ref = !(test_bit(STATUS_TRANS_GOING_IDLE, &mvm->trans->status) &&
- ieee80211_is_beacon(hdr->frame_control));
-
- if (take_ref)
- iwl_mvm_ref(mvm, IWL_MVM_REF_RX);
+ rx_status->boottime_ns = ktime_get_boottime_ns();
iwl_mvm_pass_packet_to_mac80211(mvm, sta, napi, skb, hdr, len,
crypt_len, rxb);
-
- if (take_ref)
- iwl_mvm_unref(mvm, IWL_MVM_REF_RX);
}
struct iwl_mvm_stat_data {
@@ -590,7 +569,8 @@
__le32 flags;
__le32 mac_id;
u8 beacon_filter_average_energy;
- void *general;
+ __le32 *beacon_counter;
+ u8 *beacon_average_energy;
};
static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
@@ -604,32 +584,16 @@
int hyst = vif->bss_conf.cqm_rssi_hyst;
u16 id = le32_to_cpu(data->mac_id);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ u16 vif_id = mvmvif->id;
/* This doesn't need the MAC ID check since it's not taking the
* data copied into the "data" struct, but rather the data from
* the notification directly.
*/
- if (data->general) {
- u16 vif_id = mvmvif->id;
-
- if (iwl_mvm_is_cdb_supported(mvm)) {
- struct mvm_statistics_general_cdb *general =
- data->general;
-
- mvmvif->beacon_stats.num_beacons =
- le32_to_cpu(general->beacon_counter[vif_id]);
- mvmvif->beacon_stats.avg_signal =
- -general->beacon_average_energy[vif_id];
- } else {
- struct mvm_statistics_general_v8 *general =
- data->general;
-
- mvmvif->beacon_stats.num_beacons =
- le32_to_cpu(general->beacon_counter[vif_id]);
- mvmvif->beacon_stats.avg_signal =
- -general->beacon_average_energy[vif_id];
- }
- }
+ mvmvif->beacon_stats.num_beacons =
+ le32_to_cpu(data->beacon_counter[vif_id]);
+ mvmvif->beacon_stats.avg_signal =
+ -data->beacon_average_energy[vif_id];
/* make sure that beacon statistics don't go backwards with TCM
* request to clear statistics
@@ -707,14 +671,11 @@
struct iwl_fw_dbg_trigger_stats *trig_stats;
u32 trig_offset, trig_thold;
- if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_STATS))
+ trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL, FW_DBG_TRIGGER_STATS);
+ if (!trig)
return;
- trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_STATS);
trig_stats = (void *)trig->data;
-
- if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig))
- return;
trig_offset = le32_to_cpu(trig_stats->stop_offset);
trig_thold = le32_to_cpu(trig_stats->stop_threshold);
@@ -728,18 +689,136 @@
iwl_fw_dbg_collect_trig(&mvm->fwrt, trig, NULL);
}
+static void iwl_mvm_update_avg_energy(struct iwl_mvm *mvm,
+ u8 energy[IWL_MVM_STATION_COUNT_MAX])
+{
+ int i;
+
+ if (WARN_ONCE(mvm->fw->ucode_capa.num_stations >
+ IWL_MVM_STATION_COUNT_MAX,
+ "Driver and FW station count mismatch %d\n",
+ mvm->fw->ucode_capa.num_stations))
+ return;
+
+ rcu_read_lock();
+ for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
+ struct iwl_mvm_sta *sta;
+
+ if (!energy[i])
+ continue;
+
+ sta = iwl_mvm_sta_from_staid_rcu(mvm, i);
+ if (!sta)
+ continue;
+ sta->avg_energy = energy[i];
+ }
+ rcu_read_unlock();
+}
+
+static void
+iwl_mvm_update_tcm_from_stats(struct iwl_mvm *mvm, __le32 *air_time_le,
+ __le32 *rx_bytes_le)
+{
+ int i;
+
+ spin_lock(&mvm->tcm.lock);
+ for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
+ struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[i];
+ u32 rx_bytes = le32_to_cpu(rx_bytes_le[i]);
+ u32 airtime = le32_to_cpu(air_time_le[i]);
+
+ mdata->rx.airtime += airtime;
+ mdata->uapsd_nonagg_detect.rx_bytes += rx_bytes;
+ if (airtime) {
+ /* re-init every time to store rate from FW */
+ ewma_rate_init(&mdata->uapsd_nonagg_detect.rate);
+ ewma_rate_add(&mdata->uapsd_nonagg_detect.rate,
+ rx_bytes * 8 / airtime);
+ }
+ }
+ spin_unlock(&mvm->tcm.lock);
+}
+
+static void
+iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
+ struct iwl_rx_packet *pkt)
+{
+ struct iwl_mvm_stat_data data = {
+ .mvm = mvm,
+ };
+ u8 beacon_average_energy[MAC_INDEX_AUX];
+ u8 average_energy[IWL_MVM_STATION_COUNT_MAX];
+ struct iwl_statistics_operational_ntfy *stats;
+ int expected_size;
+ __le32 flags;
+ int i;
+
+ expected_size = sizeof(*stats);
+ if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) < expected_size,
+ "received invalid statistics size (%d)!, expected_size: %d\n",
+ iwl_rx_packet_payload_len(pkt), expected_size))
+ return;
+
+ stats = (void *)&pkt->data;
+
+ if (WARN_ONCE(stats->hdr.type != FW_STATISTICS_OPERATIONAL ||
+ stats->hdr.version != 1,
+ "received unsupported hdr type %d, version %d\n",
+ stats->hdr.type, stats->hdr.version))
+ return;
+
+ flags = stats->flags;
+ mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
+ mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
+ mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
+ mvm->radio_stats.on_time_scan = le64_to_cpu(stats->on_time_scan);
+
+ iwl_mvm_rx_stats_check_trigger(mvm, pkt);
+
+ data.mac_id = stats->mac_id;
+ data.beacon_filter_average_energy =
+ le32_to_cpu(stats->beacon_filter_average_energy);
+ data.flags = flags;
+ data.beacon_counter = stats->beacon_counter;
+ for (i = 0; i < ARRAY_SIZE(beacon_average_energy); i++)
+ beacon_average_energy[i] =
+ le32_to_cpu(stats->beacon_average_energy[i]);
+
+ data.beacon_average_energy = beacon_average_energy;
+
+ ieee80211_iterate_active_interfaces(mvm->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_stat_iterator,
+ &data);
+
+ for (i = 0; i < ARRAY_SIZE(average_energy); i++)
+ average_energy[i] = le32_to_cpu(stats->average_energy[i]);
+ iwl_mvm_update_avg_energy(mvm, average_energy);
+
+ /*
+ * Don't update in case the statistics are not cleared, since
+ * we will end up counting twice the same airtime, once in TCM
+ * request and once in statistics notification.
+ */
+ if (le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
+ iwl_mvm_update_tcm_from_stats(mvm, stats->air_time,
+ stats->rx_bytes);
+}
+
void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt)
{
struct iwl_mvm_stat_data data = {
.mvm = mvm,
};
+ __le32 *bytes, *air_time, flags;
int expected_size;
- int i;
u8 *energy;
- __le32 *bytes;
- __le32 *air_time;
- __le32 flags;
+
+ /* From ver 14 and up we use TLV statistics format */
+ if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,
+ STATISTICS_CMD, 0) >= 14)
+ return iwl_mvm_handle_rx_statistics_tlv(mvm, pkt);
if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
if (iwl_mvm_has_new_rx_api(mvm))
@@ -747,7 +826,7 @@
else
expected_size = sizeof(struct iwl_notif_statistics_v10);
} else {
- expected_size = sizeof(struct iwl_notif_statistics_cdb);
+ expected_size = sizeof(struct iwl_notif_statistics);
}
if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) != expected_size,
@@ -773,11 +852,12 @@
mvm->radio_stats.on_time_scan =
le64_to_cpu(stats->general.common.on_time_scan);
- data.general = &stats->general;
-
+ data.beacon_counter = stats->general.beacon_counter;
+ data.beacon_average_energy =
+ stats->general.beacon_average_energy;
flags = stats->flag;
} else {
- struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data;
+ struct iwl_notif_statistics *stats = (void *)&pkt->data;
data.mac_id = stats->rx.general.mac_id;
data.beacon_filter_average_energy =
@@ -794,8 +874,9 @@
mvm->radio_stats.on_time_scan =
le64_to_cpu(stats->general.common.on_time_scan);
- data.general = &stats->general;
-
+ data.beacon_counter = stats->general.beacon_counter;
+ data.beacon_average_energy =
+ stats->general.beacon_average_energy;
flags = stats->flag;
}
data.flags = flags;
@@ -817,52 +898,23 @@
bytes = (void *)&v11->load_stats.byte_count;
air_time = (void *)&v11->load_stats.air_time;
} else {
- struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data;
+ struct iwl_notif_statistics *stats = (void *)&pkt->data;
energy = (void *)&stats->load_stats.avg_energy;
bytes = (void *)&stats->load_stats.byte_count;
air_time = (void *)&stats->load_stats.air_time;
}
- rcu_read_lock();
- for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
- struct iwl_mvm_sta *sta;
-
- if (!energy[i])
- continue;
-
- sta = iwl_mvm_sta_from_staid_rcu(mvm, i);
- if (!sta)
- continue;
- sta->avg_energy = energy[i];
- }
- rcu_read_unlock();
+ iwl_mvm_update_avg_energy(mvm, energy);
/*
* Don't update in case the statistics are not cleared, since
* we will end up counting twice the same airtime, once in TCM
* request and once in statistics notification.
*/
- if (!(le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR))
- return;
+ if (le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
+ iwl_mvm_update_tcm_from_stats(mvm, air_time, bytes);
- spin_lock(&mvm->tcm.lock);
- for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
- struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[i];
- u32 airtime = le32_to_cpu(air_time[i]);
- u32 rx_bytes = le32_to_cpu(bytes[i]);
-
- mdata->uapsd_nonagg_detect.rx_bytes += rx_bytes;
- if (airtime) {
- /* re-init every time to store rate from FW */
- ewma_rate_init(&mdata->uapsd_nonagg_detect.rate);
- ewma_rate_add(&mdata->uapsd_nonagg_detect.rate,
- rx_bytes * 8 / airtime);
- }
-
- mdata->rx.airtime += airtime;
- }
- spin_unlock(&mvm->tcm.lock);
}
void iwl_mvm_rx_statistics(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
--
Gitblit v1.6.2