2023-04-13 18:41:57

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 00/15] wifi: iwlwifi: updates intended for v6.4 2023-04-13 - set 2

From: Gregory Greenman <[email protected]>

Hi,

Here's one more set of iwlwifi patches for v6.4.
It's the ususal developement, small improvements,
cleanups and bugfixes.

Thanks,
Gregory

Alon Giladi (1):
wifi: iwlwifi: acpi: support modules with high antenna gain

Avraham Stern (2):
wifi: iwlwifi: mvm: fix shift-out-of-bounds
wifi: iwlwifi: mvm: make HLTK configuration for PASN station optional

Ayala Beker (2):
wifi: iwlwifi: mvm: don't drop unencrypted MCAST frames
wifi: iwlwifi: mvm: scan legacy bands and UHB channels with same
antenna

Daniel Gabay (3):
wifi: iwlwifi: pcie: fix possible NULL pointer dereference
wifi: iwlwifi: yoyo: skip dump correctly on hw error
wifi: iwlwifi: yoyo: Fix possible division by zero

Haim Dreyfuss (1):
wifi: iwlwifi: mvm: support wowlan info notification version 2

Johannes Berg (3):
wifi: iwlwifi: mvm: request limiting to 8 MSDUs per A-MSDU
wifi: iwlwifi: mvm: add DSM_FUNC_ENABLE_6E value to debugfs
wifi: iwlwifi: pcie: work around ROM bug on AX210 integrated

Miri Korenblit (1):
wifi: iwlwifi: mvm: cleanup beacon_inject_active during hw restart

Mukesh Sisodiya (2):
wifi: iwlwifi: dbg: print pc register data once fw dump occurred
wifi: iwlwifi: Fix the duplicate dump name

drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 41 +++++++----
.../net/wireless/intel/iwlwifi/fw/api/d3.h | 37 +++++++++-
.../net/wireless/intel/iwlwifi/fw/api/scan.h | 3 +
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 6 +-
drivers/net/wireless/intel/iwlwifi/fw/dump.c | 11 +++
drivers/net/wireless/intel/iwlwifi/fw/file.h | 2 +
.../net/wireless/intel/iwlwifi/fw/runtime.h | 1 +
drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 2 +
.../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 6 ++
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 9 +++
.../net/wireless/intel/iwlwifi/iwl-trans.h | 16 +++++
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 35 ++++++++-
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 22 ++++++
.../intel/iwlwifi/mvm/ftm-initiator.c | 25 ++++++-
.../intel/iwlwifi/mvm/ftm-responder.c | 19 +++--
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 +++
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 11 ++-
drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 5 ++
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 4 +-
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 3 +
.../wireless/intel/iwlwifi/pcie/trans-gen2.c | 72 +++++++++++++++++--
22 files changed, 309 insertions(+), 36 deletions(-)

--
2.38.1


2023-04-13 18:42:12

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 05/15] wifi: iwlwifi: mvm: request limiting to 8 MSDUs per A-MSDU

From: Johannes Berg <[email protected]>

Due to hardware limitations when splitting up A-MSDUs, it
cannot handle an arbitrary number of MSDUs per A-MSDU. Set
the bits to ask transmitters to send only 8 MSDUs in one
A-MSDU.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index fc15636beec0..ac5c4799fa7e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -227,14 +227,18 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
static const u8 he_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
- [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF |
+ WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB,
+ [8] = WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB,
};

static const u8 tm_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT |
WLAN_EXT_CAPA3_TIMING_MEASUREMENT_SUPPORT,
- [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF |
+ WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB,
+ [8] = WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB,
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
};

--
2.38.1

2023-04-13 18:42:13

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 04/15] wifi: iwlwifi: mvm: fix shift-out-of-bounds

From: Avraham Stern <[email protected]>

The aux queue is initialized to IWL_MVM_INVALID_QUEUE. This is
later used for a bitmask of the queue, which results in a
shift-out-of-bounds. Fix it.

Fixes: b85f7ebb2497 ("wifi: iwlwifi: mvm: avoid UB shift of snif_queue")
Signed-off-by: Avraham Stern <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 6b2690534f59..3e5bed885bd9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -2231,11 +2231,13 @@ static int iwl_mvm_add_int_sta_with_queue(struct iwl_mvm *mvm, int macidx,
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id)
{
int ret;
+ u32 qmask = mvm->aux_queue == IWL_MVM_INVALID_QUEUE ? 0 :
+ BIT(mvm->aux_queue);

lockdep_assert_held(&mvm->mutex);

/* Allocate aux station and assign to it the aux queue */
- ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
+ ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, qmask,
NL80211_IFTYPE_UNSPECIFIED,
IWL_STA_AUX_ACTIVITY);
if (ret)
--
2.38.1

2023-04-13 18:42:21

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 06/15] wifi: iwlwifi: mvm: make HLTK configuration for PASN station optional

From: Avraham Stern <[email protected]>

When secure LTF is not used, the HLTK is not derived during the PASN
authentication. Make the HLTK optional when adding a PASN station.

Signed-off-by: Avraham Stern <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../intel/iwlwifi/mvm/ftm-initiator.c | 25 ++++++++++++++++---
.../intel/iwlwifi/mvm/ftm-responder.c | 19 +++++++++++---
2 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index 379da4bec5dd..3963a0d4ed04 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -25,6 +25,10 @@ struct iwl_mvm_smooth_entry {
u64 host_time;
};

+enum iwl_mvm_pasn_flags {
+ IWL_MVM_PASN_FLAG_HAS_HLTK = BIT(0),
+};
+
struct iwl_mvm_ftm_pasn_entry {
struct list_head list;
u8 addr[ETH_ALEN];
@@ -33,6 +37,7 @@ struct iwl_mvm_ftm_pasn_entry {
u8 cipher;
u8 tx_pn[IEEE80211_CCMP_PN_LEN];
u8 rx_pn[IEEE80211_CCMP_PN_LEN];
+ u32 flags;
};

int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -79,14 +84,24 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
rcu_read_unlock();
}

- if (tk_len != expected_tk_len || hltk_len != sizeof(pasn->hltk)) {
+ if (tk_len != expected_tk_len ||
+ (hltk_len && hltk_len != sizeof(pasn->hltk))) {
IWL_ERR(mvm, "Invalid key length: tk_len=%u hltk_len=%u\n",
tk_len, hltk_len);
goto out;
}

+ if (!expected_tk_len && !hltk_len) {
+ IWL_ERR(mvm, "TK and HLTK not set\n");
+ goto out;
+ }
+
memcpy(pasn->addr, addr, sizeof(pasn->addr));
- memcpy(pasn->hltk, hltk, sizeof(pasn->hltk));
+
+ if (hltk_len) {
+ memcpy(pasn->hltk, hltk, sizeof(pasn->hltk));
+ pasn->flags |= IWL_MVM_PASN_FLAG_HAS_HLTK;
+ }

if (tk && tk_len)
memcpy(pasn->tk, tk, sizeof(pasn->tk));
@@ -691,7 +706,11 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
continue;

target->cipher = entry->cipher;
- memcpy(target->hltk, entry->hltk, sizeof(target->hltk));
+
+ if (entry->flags & IWL_MVM_PASN_FLAG_HAS_HLTK)
+ memcpy(target->hltk, entry->hltk, sizeof(target->hltk));
+ else
+ memset(target->hltk, 0, sizeof(target->hltk));

if (vif->cfg.assoc &&
!memcmp(vif->bss_conf.bssid, target->bssid,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
index c37d793d6a4a..1b6fb73ddfc7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -317,6 +317,8 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
.addr = addr,
.hltk = hltk,
};
+ struct iwl_mvm_pasn_hltk_data *hltk_data_ptr = NULL;
+
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
WIDE_ID(LOCATION_GROUP, TOF_RESPONDER_DYN_CONFIG_CMD),
2);
@@ -328,12 +330,21 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
return -ENOTSUPP;
}

- hltk_data.cipher = iwl_mvm_cipher_to_location_cipher(cipher);
- if (hltk_data.cipher == IWL_LOCATION_CIPHER_INVALID) {
- IWL_ERR(mvm, "invalid cipher: %u\n", cipher);
+ if ((!hltk || !hltk_len) && (!tk || !tk_len)) {
+ IWL_ERR(mvm, "TK and HLTK not set\n");
return -EINVAL;
}

+ if (hltk && hltk_len) {
+ hltk_data.cipher = iwl_mvm_cipher_to_location_cipher(cipher);
+ if (hltk_data.cipher == IWL_LOCATION_CIPHER_INVALID) {
+ IWL_ERR(mvm, "invalid cipher: %u\n", cipher);
+ return -EINVAL;
+ }
+
+ hltk_data_ptr = &hltk_data;
+ }
+
if (tk && tk_len) {
sta = kzalloc(sizeof(*sta), GFP_KERNEL);
if (!sta)
@@ -350,7 +361,7 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
list_add_tail(&sta->list, &mvm->resp_pasn_list);
}

- ret = iwl_mvm_ftm_responder_dyn_cfg_v3(mvm, vif, NULL, &hltk_data);
+ ret = iwl_mvm_ftm_responder_dyn_cfg_v3(mvm, vif, NULL, hltk_data_ptr);
if (ret && sta)
iwl_mvm_resp_del_pasn_sta(mvm, vif, sta);

--
2.38.1

2023-04-13 18:42:25

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 02/15] wifi: iwlwifi: mvm: don't drop unencrypted MCAST frames

From: Ayala Beker <[email protected]>

MCAST frames are filtered out by the driver if we are not
authorized yet.
Fix it to filter out only protected frames.

Fixes: 147eb05f24e6 ("iwlwifi: mvm: always tell the firmware to accept MCAST frames in BSS")
Signed-off-by: Ayala Beker <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index e08dca8d2baa..b38b24246675 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -383,9 +383,10 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
* Don't even try to decrypt a MCAST frame that was received
* before the managed vif is authorized, we'd fail anyway.
*/
- if (vif->type == NL80211_IFTYPE_STATION &&
+ if (is_multicast_ether_addr(hdr->addr1) &&
+ vif->type == NL80211_IFTYPE_STATION &&
!mvmvif->authorized &&
- is_multicast_ether_addr(hdr->addr1)) {
+ ieee80211_has_protected(hdr->frame_control)) {
IWL_DEBUG_DROP(mvm, "MCAST before the vif is authorized\n");
kfree_skb(skb);
rcu_read_unlock();
--
2.38.1

2023-04-13 18:42:31

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 07/15] wifi: iwlwifi: mvm: support wowlan info notification version 2

From: Haim Dreyfuss <[email protected]>

As part of version 2 we don't need to have wake_packet_bufsize
and wake_packet_length. The first one is already calculated by the driver,
the latter is sent as part of the wake packet notification.

Signed-off-by: Haim Dreyfuss <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/fw/api/d3.h | 37 ++++++++++++++++++-
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 35 +++++++++++++++++-
2 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
index df0833890e55..8a613e150a02 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
@@ -767,7 +767,7 @@ struct iwl_wowlan_status_v12 {
} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_12 */

/**
- * struct iwl_wowlan_info_notif - WoWLAN information notification
+ * struct iwl_wowlan_info_notif_v1 - WoWLAN information notification
* @gtk: GTK data
* @igtk: IGTK data
* @replay_ctr: GTK rekey replay counter
@@ -785,7 +785,7 @@ struct iwl_wowlan_status_v12 {
* @station_id: station id
* @reserved2: reserved
*/
-struct iwl_wowlan_info_notif {
+struct iwl_wowlan_info_notif_v1 {
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
__le64 replay_ctr;
@@ -803,6 +803,39 @@ struct iwl_wowlan_info_notif {
u8 reserved2[2];
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */

+/**
+ * struct iwl_wowlan_info_notif - WoWLAN information notification
+ * @gtk: GTK data
+ * @igtk: IGTK data
+ * @replay_ctr: GTK rekey replay counter
+ * @pattern_number: number of the matched patterns
+ * @reserved1: reserved
+ * @qos_seq_ctr: QoS sequence counters to use next
+ * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
+ * @num_of_gtk_rekeys: number of GTK rekeys
+ * @transmitted_ndps: number of transmitted neighbor discovery packets
+ * @received_beacons: number of received beacons
+ * @tid_tear_down: bit mask of tids whose BA sessions were closed
+ * in suspend state
+ * @station_id: station id
+ * @reserved2: reserved
+ */
+struct iwl_wowlan_info_notif {
+ struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
+ __le64 replay_ctr;
+ __le16 pattern_number;
+ __le16 reserved1;
+ __le16 qos_seq_ctr[8];
+ __le32 wakeup_reasons;
+ __le32 num_of_gtk_rekeys;
+ __le32 transmitted_ndps;
+ __le32 received_beacons;
+ u8 tid_tear_down;
+ u8 station_id;
+ u8 reserved2[2];
+} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_2 */
+
/**
* struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification
* @wake_packet_length: wakeup packet length
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 40adf789c8fc..bf80b1d093a2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -2017,6 +2017,12 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
{
u32 i;

+ if (!data) {
+ IWL_ERR(mvm, "iwl_wowlan_info_notif data is NULL\n");
+ status = NULL;
+ return;
+ }
+
if (len < sizeof(*data)) {
IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
status = NULL;
@@ -2705,10 +2711,33 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
struct iwl_d3_data *d3_data = data;
u32 len;
int ret;
+ int wowlan_info_ver = iwl_fw_lookup_notif_ver(mvm->fw,
+ PROT_OFFLOAD_GROUP,
+ WOWLAN_INFO_NOTIFICATION,
+ IWL_FW_CMD_VER_UNKNOWN);
+

switch (WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)) {
case WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_INFO_NOTIFICATION): {
- struct iwl_wowlan_info_notif *notif = (void *)pkt->data;
+ struct iwl_wowlan_info_notif *notif;
+
+ if (wowlan_info_ver < 2) {
+ struct iwl_wowlan_info_notif_v1 *notif_v1 = (void *)pkt->data;
+
+ notif = kmemdup(notif_v1,
+ offsetofend(struct iwl_wowlan_info_notif,
+ received_beacons),
+ GFP_ATOMIC);
+
+ if (!notif)
+ return false;
+
+ notif->tid_tear_down = notif_v1->tid_tear_down;
+ notif->station_id = notif_v1->station_id;
+
+ } else {
+ notif = (void *)pkt->data;
+ }

if (d3_data->notif_received & IWL_D3_NOTIF_WOWLAN_INFO) {
/* We might get two notifications due to dual bss */
@@ -2721,6 +2750,10 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
len = iwl_rx_packet_payload_len(pkt);
iwl_mvm_parse_wowlan_info_notif(mvm, notif, d3_data->status,
len);
+
+ if (wowlan_info_ver < 2)
+ kfree(notif);
+
if (d3_data->status &&
d3_data->status->wakeup_reasons & IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT)
/* We are supposed to get also wake packet notif */
--
2.38.1

2023-04-13 18:42:34

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 08/15] wifi: iwlwifi: mvm: cleanup beacon_inject_active during hw restart

From: Miri Korenblit <[email protected]>

beacon_inject_active turns true and false via debugfs when we inject a
beacon. During the time of the beacon injection we can't configure the
FW with a beacon cmd. If we have a hw restart during the beacon injection
then in the recovery flow we will not be able to configure the beacon
cmd to the FW. Fix this by cleaning up this variable after an hw restart.

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index ac5c4799fa7e..d6f29aa2a66f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1065,6 +1065,9 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->rx_ba_sessions = 0;
mvm->fwrt.dump.conf = FW_DBG_INVALID;
mvm->monitor_on = false;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ mvm->beacon_inject_active = false;
+#endif

/* keep statistics ticking */
iwl_mvm_accu_radio_stats(mvm);
--
2.38.1

2023-04-13 18:42:37

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 09/15] wifi: iwlwifi: mvm: add DSM_FUNC_ENABLE_6E value to debugfs

From: Johannes Berg <[email protected]>

In order to simplify checking that this value was set up
correctly, add it to debugfs.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 527daaf46f96..affaed4d13fa 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -340,6 +340,26 @@ static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,

return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
+
+static ssize_t iwl_dbgfs_wifi_6e_enable_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+ int err, pos;
+ char buf[12];
+ u32 value;
+
+ err = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
+ DSM_FUNC_ENABLE_6E,
+ &iwl_guid, &value);
+ if (err)
+ return err;
+
+ pos = sprintf(buf, "0x%08x\n", value);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
#endif

static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
@@ -1898,6 +1918,7 @@ MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);

#ifdef CONFIG_ACPI
MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
+MVM_DEBUGFS_READ_FILE_OPS(wifi_6e_enable);
#endif

MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
@@ -2092,6 +2113,7 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
MVM_DEBUGFS_ADD_FILE(tas_get_status, mvm->debugfs_dir, 0400);
#ifdef CONFIG_ACPI
MVM_DEBUGFS_ADD_FILE(sar_geo_profile, mvm->debugfs_dir, 0400);
+ MVM_DEBUGFS_ADD_FILE(wifi_6e_enable, mvm->debugfs_dir, 0400);
#endif
MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);

--
2.38.1

2023-04-13 18:42:56

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 11/15] wifi: iwlwifi: Fix the duplicate dump name

From: Mukesh Sisodiya <[email protected]>

Driver is using the dump name generated first time in all
generated dump in case of NMI.
The validity of dump name should be with each dump created
and need to reset after each use.

Fixes: 834f920ef34b ("wifi: iwlwifi: yoyo: Add driver defined dump file name")
Signed-off-by: Mukesh Sisodiya <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index ca97f2fcb693..51cdbc13fbcd 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -2345,6 +2345,8 @@ static u32 iwl_dump_ini_file_name_info(struct iwl_fw_runtime *fwrt,
/* add the dump file name extension tlv to the list */
list_add_tail(&entry->list, list);

+ fwrt->trans->dbg.dump_file_name_ext_valid = false;
+
return entry->size;
}

--
2.38.1

2023-04-13 18:43:13

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 12/15] wifi: iwlwifi: pcie: fix possible NULL pointer dereference

From: Daniel Gabay <[email protected]>

It is possible that iwl_pci_probe() will fail and free the trans,
then afterwards iwl_pci_remove() will be called and crash by trying
to access trans which is already freed, fix it.

iwlwifi 0000:01:00.0: Detected crf-id 0xa5a5a5a2, cnv-id 0xa5a5a5a2
wfpm id 0xa5a5a5a2
iwlwifi 0000:01:00.0: Can't find a correct rfid for crf id 0x5a2
...
BUG: kernel NULL pointer dereference, address: 0000000000000028
...
RIP: 0010:iwl_pci_remove+0x12/0x30 [iwlwifi]
pci_device_remove+0x3e/0xb0
device_release_driver_internal+0x103/0x1f0
driver_detach+0x4c/0x90
bus_remove_driver+0x5c/0xd0
driver_unregister+0x31/0x50
pci_unregister_driver+0x40/0x90
iwl_pci_unregister_driver+0x15/0x20 [iwlwifi]
__exit_compat+0x9/0x98 [iwlwifi]
__x64_sys_delete_module+0x147/0x260

Signed-off-by: Daniel Gabay <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 70f6c59eec5d..a60329079167 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1733,6 +1733,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
{
struct iwl_trans *trans = pci_get_drvdata(pdev);

+ if (!trans)
+ return;
+
iwl_drv_stop(trans->drv);

iwl_trans_pcie_free(trans);
--
2.38.1

2023-04-13 18:43:17

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 13/15] wifi: iwlwifi: yoyo: skip dump correctly on hw error

From: Daniel Gabay <[email protected]>

When NIC is in a bad state, reading data will return 28 bits as
0xa5a5a5a and the lowest 4 bits are not fixed value.

Mask these bits in a few places to skip the dump correctly.

Fixes: 89639e06d0f3 ("iwlwifi: yoyo: support for new DBGI_SRAM region")
Signed-off-by: Daniel Gabay <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 51cdbc13fbcd..d5b51496bd0b 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1038,7 +1038,7 @@ iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
range->range_data_size = reg->dev_addr.size;
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
prph_val = iwl_read_prph(fwrt->trans, addr + i);
- if (prph_val == 0x5a5a5a5a)
+ if ((prph_val & ~0xf) == 0xa5a5a5a0)
return -EBUSY;
*val++ = cpu_to_le32(prph_val);
}
@@ -1562,7 +1562,7 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
prph_data = iwl_read_prph_no_grab(fwrt->trans, (i % 2) ?
DBGI_SRAM_TARGET_ACCESS_RDATA_MSB :
DBGI_SRAM_TARGET_ACCESS_RDATA_LSB);
- if (prph_data == 0x5a5a5a5a) {
+ if ((prph_data & ~0xf) == 0xa5a5a5a0) {
iwl_trans_release_nic_access(fwrt->trans);
return -EBUSY;
}
--
2.38.1

2023-04-13 18:43:21

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 15/15] wifi: iwlwifi: mvm: scan legacy bands and UHB channels with same antenna

From: Ayala Beker <[email protected]>

In case of UHB scan that follows a scan on legacy bands,
consider both scan commands as part of the same scan cycle,
and thus configure them to use the same antenna configuration.

Signed-off-by: Ayala Beker <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/fw/api/scan.h | 3 +++
drivers/net/wireless/intel/iwlwifi/fw/file.h | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 5 +++++
3 files changed, 9 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
index 7ba0e3409199..ec96ba053a5c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
@@ -709,10 +709,13 @@ enum iwl_umac_scan_general_flags_v2 {
* should be aware of a P2P GO operation on the 2GHz band.
* @IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB: scan event scheduling
* should be aware of a P2P GO operation on the 5GHz or 6GHz band.
+ * @IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_DONT_TOGGLE_ANT: don't toggle between
+ * valid antennas, and use the same antenna as in previous scan
*/
enum iwl_umac_scan_general_params_flags2 {
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_LB = BIT(0),
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB = BIT(1),
+ IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_DONT_TOGGLE_ANT = BIT(2),
};

/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index a0260a1fa099..34ef106a2274 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -459,6 +459,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_SYNCED_TIME = (__force iwl_ucode_tlv_capa_t)106,
IWL_UCODE_TLV_CAPA_TIME_SYNC_BOTH_FTM_TM = (__force iwl_ucode_tlv_capa_t)108,
IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT = (__force iwl_ucode_tlv_capa_t)109,
+ IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT = (__force iwl_ucode_tlv_capa_t)111,

#ifdef __CHECKER__
/* sparse says it cannot increment the previous enum member */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 07045092c717..7749f15b7f14 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -2081,6 +2081,11 @@ static u8 iwl_mvm_scan_umac_flags2(struct iwl_mvm *mvm,
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB;
}

+ if (params->scan_6ghz &&
+ fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT))
+ flags |= IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_DONT_TOGGLE_ANT;
+
return flags;
}

--
2.38.1

2023-04-13 18:43:22

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 14/15] wifi: iwlwifi: yoyo: Fix possible division by zero

From: Daniel Gabay <[email protected]>

Don't allow buffer allocation TLV with zero req_size since it
leads later to division by zero in iwl_dbg_tlv_alloc_fragments().
Also, NPK/SRAM locations are allowed to have zero buffer req_size,
don't discard them.

Fixes: a9248de42464 ("iwlwifi: dbg_ini: add TLV allocation new API support")
Signed-off-by: Daniel Gabay <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
index 87366b70b17f..546737320a57 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
@@ -138,6 +138,12 @@ static int iwl_dbg_tlv_alloc_buf_alloc(struct iwl_trans *trans,
alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1)
goto err;

+ if (buf_location == IWL_FW_INI_LOCATION_DRAM_PATH &&
+ alloc->req_size == 0) {
+ IWL_ERR(trans, "WRT: Invalid DRAM buffer allocation requested size (0)\n");
+ return -EINVAL;
+ }
+
trans->dbg.fw_mon_cfg[alloc_id] = *alloc;

return 0;
--
2.38.1

2023-04-13 18:43:30

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 01/15] wifi: iwlwifi: dbg: print pc register data once fw dump occurred

From: Mukesh Sisodiya <[email protected]>

Add debug print for different FW program counter details of
different CPU. Program counter pc details will be read from
TLV during init.

Signed-off-by: Mukesh Sisodiya <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/fw/dump.c | 11 +++++++++++
drivers/net/wireless/intel/iwlwifi/fw/file.h | 1 +
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 9 +++++++++
drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 16 ++++++++++++++++
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 ++++++++++
5 files changed, 47 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
index 59ed321bcc27..f86f7b4baa18 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
@@ -484,6 +484,9 @@ static void iwl_fwrt_dump_fseq_regs(struct iwl_fw_runtime *fwrt)

void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
{
+ struct iwl_pc_data *pc_data;
+ u8 count;
+
if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) {
IWL_ERR(fwrt,
"DEVICE_ENABLED bit is not set. Aborting dump.\n");
@@ -502,6 +505,14 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
iwl_fwrt_dump_rcm_error_log(fwrt, 1);
iwl_fwrt_dump_iml_error_log(fwrt);
iwl_fwrt_dump_fseq_regs(fwrt);
+ if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ pc_data = fwrt->trans->dbg.pc_data;
+ for (count = 0; count < fwrt->trans->dbg.num_pc;
+ count++, pc_data++)
+ IWL_ERR(fwrt, "%s: 0x%x\n",
+ pc_data->pc_name,
+ pc_data->pc_address);
+ }

if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
u32 scratch = iwl_read32(fwrt->trans, CSR_FUNC_SCRATCH);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index f2eefca6e260..a0260a1fa099 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -101,6 +101,7 @@ enum iwl_ucode_tlv_type {

IWL_UCODE_TLV_SEC_TABLE_ADDR = 66,
IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,
+ IWL_UCODE_TLV_CURRENT_PC = 68,

IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0,

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 4c977ba9cd85..4959977a92a1 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -127,6 +127,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
kfree(drv->fw.iml);
kfree(drv->fw.ucode_capa.cmd_versions);
kfree(drv->fw.phy_integration_ver);
+ kfree(drv->trans->dbg.pc_data);

for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
iwl_free_fw_img(drv, drv->fw.img + i);
@@ -1232,6 +1233,14 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
iwl_drv_set_dump_exclude(drv, tlv_type,
tlv_data, tlv_len);
break;
+ case IWL_UCODE_TLV_CURRENT_PC:
+ if (tlv_len < sizeof(struct iwl_pc_data))
+ goto invalid_tlv_len;
+ drv->trans->dbg.num_pc =
+ tlv_len / sizeof(struct iwl_pc_data);
+ drv->trans->dbg.pc_data =
+ kmemdup(tlv_data, tlv_len, GFP_KERNEL);
+ break;
default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index dd277a4fa8dd..74ff4788dc83 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -748,6 +748,18 @@ struct iwl_imr_data {
__le64 imr_base_addr;
};

+#define IWL_TRANS_CURRENT_PC_NAME_MAX_BYTES 32
+
+/**
+ * struct iwl_pc_data - program counter details
+ * @pc_name: cpu name
+ * @pc_address: cpu program counter
+ */
+struct iwl_pc_data {
+ u8 pc_name[IWL_TRANS_CURRENT_PC_NAME_MAX_BYTES];
+ u32 pc_address;
+};
+
/**
* struct iwl_trans_debug - transport debug related data
*
@@ -777,6 +789,8 @@ struct iwl_imr_data {
* @ucode_preset: preset based on ucode
* @dump_file_name_ext: dump file name extension
* @dump_file_name_ext_valid: dump file name extension if valid or not
+ * @num_pc: number of program counter for cpu
+ * @pc_data: details of the program counter
*/
struct iwl_trans_debug {
u8 n_dest_reg;
@@ -817,6 +831,8 @@ struct iwl_trans_debug {
struct iwl_imr_data imr_data;
u8 dump_file_name_ext[IWL_FW_INI_MAX_NAME];
bool dump_file_name_ext_valid;
+ u32 num_pc;
+ struct iwl_pc_data *pc_data;
};

struct iwl_dma_ptr {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 521eded39028..3f5cc6bf3f1c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -321,6 +321,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
static const u16 alive_cmd[] = { UCODE_ALIVE_NTFY };
bool run_in_rfkill =
ucode_type == IWL_UCODE_INIT || iwl_mvm_has_unified_ucode(mvm);
+ u8 count;
+ struct iwl_pc_data *pc_data;

if (ucode_type == IWL_UCODE_REGULAR &&
iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
@@ -393,6 +395,14 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,

/* LMAC/UMAC PC info */
if (trans->trans_cfg->device_family >=
+ IWL_DEVICE_FAMILY_22000) {
+ pc_data = trans->dbg.pc_data;
+ for (count = 0; count < trans->dbg.num_pc;
+ count++, pc_data++)
+ IWL_ERR(mvm, "%s: 0x%x\n",
+ pc_data->pc_name,
+ pc_data->pc_address);
+ } else if (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_9000) {
IWL_ERR(mvm, "UMAC PC: 0x%x\n",
iwl_read_umac_prph(trans,
--
2.38.1

2023-04-13 18:43:57

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 10/15] wifi: iwlwifi: pcie: work around ROM bug on AX210 integrated

From: Johannes Berg <[email protected]>

On 22000 and AX210 devices, there's a ROM bug that causes it to
set invalid LTR settings. On 22000 and AX210 non-integrated we
can fix up these settings from the driver (as done in the code
here), but on AX210 integrated these registers are not available
to the driver.

Attempt to work around the issue by spinning while the IML is
being loaded, the IML will then reprogram the LTR values itself
after it's loaded, so only the brief IML load (which the ROM is
doing) is affected.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 2 +
.../wireless/intel/iwlwifi/pcie/trans-gen2.c | 72 +++++++++++++++++--
2 files changed, 69 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
index bece76b1a514..52479516c76b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
@@ -102,6 +102,8 @@
#define CSR_LTR_LONG_VAL_AD_SNOOP_VAL 0x000003ff
#define CSR_LTR_LONG_VAL_AD_SCALE_USEC 2

+#define CSR_LTR_LAST_MSG (CSR_BASE + 0x0DC)
+
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index 1e263154e9eb..45b63e3f5df3 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -350,7 +350,7 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr)
mutex_unlock(&trans_pcie->mutex);
}

-static void iwl_pcie_set_ltr(struct iwl_trans *trans)
+static bool iwl_pcie_set_ltr(struct iwl_trans *trans)
{
u32 ltr_val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ |
u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC,
@@ -371,18 +371,77 @@ static void iwl_pcie_set_ltr(struct iwl_trans *trans)
trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) &&
!trans->trans_cfg->integrated) {
iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val);
- } else if (trans->trans_cfg->integrated &&
- trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) {
+ return true;
+ }
+
+ if (trans->trans_cfg->integrated &&
+ trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) {
iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL);
iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val);
+ return true;
+ }
+
+ if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
+ /* First clear the interrupt, just in case */
+ iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD,
+ MSIX_HW_INT_CAUSES_REG_IML);
+ /* In this case, unfortunately the same ROM bug exists in the
+ * device (not setting LTR correctly), but we don't have control
+ * over the settings from the host due to some hardware security
+ * features. The only workaround we've been able to come up with
+ * so far is to try to keep the CPU and device busy by polling
+ * it and the IML (image loader) completed interrupt.
+ */
+ return false;
+ }
+
+ /* nothing needs to be done on other devices */
+ return true;
+}
+
+static void iwl_pcie_spin_for_iml(struct iwl_trans *trans)
+{
+/* in practice, this seems to complete in around 20-30ms at most, wait 100 */
+#define IML_WAIT_TIMEOUT (HZ / 10)
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ unsigned long end_time = jiffies + IML_WAIT_TIMEOUT;
+ u32 value, loops = 0;
+ bool irq = false;
+
+ if (WARN_ON(!trans_pcie->iml))
+ return;
+
+ value = iwl_read32(trans, CSR_LTR_LAST_MSG);
+ IWL_DEBUG_INFO(trans, "Polling for IML load - CSR_LTR_LAST_MSG=0x%x\n",
+ value);
+
+ while (time_before(jiffies, end_time)) {
+ if (iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD) &
+ MSIX_HW_INT_CAUSES_REG_IML) {
+ irq = true;
+ break;
+ }
+ /* Keep the CPU and device busy. */
+ value = iwl_read32(trans, CSR_LTR_LAST_MSG);
+ loops++;
}
+
+ IWL_DEBUG_INFO(trans,
+ "Polled for IML load: irq=%d, loops=%d, CSR_LTR_LAST_MSG=0x%x\n",
+ irq, loops, value);
+
+ /* We don't fail here even if we timed out - maybe we get lucky and the
+ * interrupt comes in later (and we get alive from firmware) and then
+ * we're all happy - but if not we'll fail on alive timeout or get some
+ * other error out.
+ */
}

int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
const struct fw_img *fw, bool run_in_rfkill)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- bool hw_rfkill;
+ bool hw_rfkill, keep_ram_busy;
int ret;

/* This may fail if AMT took ownership of the device */
@@ -443,7 +502,7 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
if (ret)
goto out;

- iwl_pcie_set_ltr(trans);
+ keep_ram_busy = !iwl_pcie_set_ltr(trans);

if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
iwl_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE);
@@ -455,6 +514,9 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1);
}

+ if (keep_ram_busy)
+ iwl_pcie_spin_for_iml(trans);
+
/* re-check RF-Kill state since we may have missed the interrupt */
hw_rfkill = iwl_pcie_check_hw_rf_kill(trans);
if (hw_rfkill && !run_in_rfkill)
--
2.38.1

2023-04-13 18:43:58

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 03/15] wifi: iwlwifi: acpi: support modules with high antenna gain

From: Alon Giladi <[email protected]>

Starting from version 4 of ANT_GAIN_CMD verification of ppag table
values is done by the FW. Driver has to send the complete table as
it appears in the BIOS. Make this change.

Signed-off-by: Alon Giladi <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 41 ++++++++++++-------
.../net/wireless/intel/iwlwifi/fw/runtime.h | 1 +
2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index a02e5a67b706..5f4a51310add 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -1006,8 +1006,10 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
union acpi_object *wifi_pkg, *data, *flags;
int i, j, ret, tbl_rev, num_sub_bands = 0;
int idx = 2;
+ u8 cmd_ver;

fwrt->ppag_flags = 0;
+ fwrt->ppag_table_valid = false;

data = iwl_acpi_get_object(fwrt->dev, ACPI_PPAG_METHOD);
if (IS_ERR(data))
@@ -1054,8 +1056,15 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
}

fwrt->ppag_flags = flags->integer.value & ACPI_PPAG_MASK;
-
- if (!fwrt->ppag_flags) {
+ cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
+ WIDE_ID(PHY_OPS_GROUP,
+ PER_PLATFORM_ANT_GAIN_CMD),
+ IWL_FW_CMD_VER_UNKNOWN);
+ if (cmd_ver == IWL_FW_CMD_VER_UNKNOWN) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+ if (!fwrt->ppag_flags && cmd_ver <= 3) {
ret = 0;
goto out_free;
}
@@ -1076,21 +1085,22 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
}

fwrt->ppag_chains[i].subbands[j] = ent->integer.value;
-
+ /* from ver 4 the fw deals with out of range values */
+ if (cmd_ver >= 4)
+ continue;
if ((j == 0 &&
(fwrt->ppag_chains[i].subbands[j] > ACPI_PPAG_MAX_LB ||
fwrt->ppag_chains[i].subbands[j] < ACPI_PPAG_MIN_LB)) ||
(j != 0 &&
(fwrt->ppag_chains[i].subbands[j] > ACPI_PPAG_MAX_HB ||
fwrt->ppag_chains[i].subbands[j] < ACPI_PPAG_MIN_HB))) {
- fwrt->ppag_flags = 0;
ret = -EINVAL;
goto out_free;
}
}
}

-
+ fwrt->ppag_table_valid = true;
ret = 0;

out_free:
@@ -1115,19 +1125,22 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c
IWL_DEBUG_RADIO(fwrt,
"PPAG capability not supported by FW, command not sent.\n");
return -EINVAL;
- }
- if (!fwrt->ppag_flags) {
- IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
- return -EINVAL;
- }
+ }
+
+ cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
+ WIDE_ID(PHY_OPS_GROUP,
+ PER_PLATFORM_ANT_GAIN_CMD),
+ IWL_FW_CMD_VER_UNKNOWN);
+ if (!fwrt->ppag_table_valid || (cmd_ver <= 3 && !fwrt->ppag_flags)) {
+ IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
+ return -EINVAL;
+ }

/* The 'flags' field is the same in v1 and in v2 so we can just
* use v1 to access it.
*/
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
- cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
- WIDE_ID(PHY_OPS_GROUP, PER_PLATFORM_ANT_GAIN_CMD),
- IWL_FW_CMD_VER_UNKNOWN);
+
if (cmd_ver == 1) {
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = cmd->v1.gain[0];
@@ -1138,7 +1151,7 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c
fwrt->ppag_ver);
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
}
- } else if (cmd_ver == 2 || cmd_ver == 3) {
+ } else if (cmd_ver >= 2 && cmd_ver <= 4) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = cmd->v2.gain[0];
*cmd_size = sizeof(cmd->v2);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index a59cf4d9567c..df689a9b7e2c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -165,6 +165,7 @@ struct iwl_fw_runtime {
struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
u32 ppag_flags;
u32 ppag_ver;
+ bool ppag_table_valid;
struct iwl_sar_offset_mapping_cmd sgom_table;
bool sgom_enabled;
u8 reduced_power_flags;
--
2.38.1