Commit 80ab5445 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'wireless-next-2024-07-11' of...

Merge tag 'wireless-next-2024-07-11' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next

Kalle Valo says:

====================
wireless-next patches for v6.11

Most likely the last "new features" pull request for v6.11 with
changes both in stack and in drivers. The big thing is the multiple
radios for wiphy feature which makes it possible to better advertise
radio capabilities to user space. mt76 enabled MLO and iwlwifi
re-enabled MLO, ath12k and rtw89 Wi-Fi 6 devices got WoWLAN support.

Major changes:

cfg80211/mac80211
 * remove DEAUTH_NEED_MGD_TX_PREP flag
 * multiple radios per wiphy support

mac80211_hwsim
 * multi-radio wiphy support

ath12k
 * DebugFS support for datapath statistics
 * WCN7850: support for WoW (Wake on WLAN)
 * WCN7850: device-tree bindings

ath11k
 * QCA6390: device-tree bindings

iwlwifi
 * mvm: re-enable Multi-Link Operation (MLO)
 * aggregation (A-MSDU) optimisations

rtw89
 * preparation for RTL8852BE-VT support
 * WoWLAN support for WiFi 6 chips
 * 36-bit PCI DMA support

mt76
 * mt7925 Multi-Link Operation (MLO) support

* tag 'wireless-next-2024-07-11' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (204 commits)
  wifi: mac80211: fix AP chandef capturing in CSA
  wifi: iwlwifi: correctly reference TSO page information
  wifi: mt76: mt792x: fix scheduler interference in drv own process
  wifi: mt76: mt7925: enabling MLO when the firmware supports it
  wifi: mt76: mt7925: remove the unused mt7925_mcu_set_chan_info
  wifi: mt76: mt7925: update mt7925_mac_link_bss_add for MLO
  wifi: mt76: mt7925: update mt7925_mcu_bss_basic_tlv for MLO
  wifi: mt76: mt7925: update mt7925_mcu_set_timing for MLO
  wifi: mt76: mt7925: update mt7925_mcu_sta_phy_tlv for MLO
  wifi: mt76: mt7925: update mt7925_mcu_sta_rate_ctrl_tlv for MLO
  wifi: mt76: mt7925: add mt7925_mcu_sta_eht_mld_tlv for MLO
  wifi: mt76: mt7925: update mt7925_mcu_sta_update for MLO
  wifi: mt76: mt7925: update mt7925_mcu_add_bss_info for MLO
  wifi: mt76: mt7925: update mt7925_mcu_bss_mld_tlv for MLO
  wifi: mt76: mt7925: update mt7925_mcu_sta_mld_tlv for MLO
  wifi: mt76: mt7925: add mt7925_[assign,unassign]_vif_chanctx
  wifi: mt76: add def_wcid to struct mt76_wcid
  wifi: mt76: mt7925: report link information in rx status
  wifi: mt76: mt7925: update rate index according to link id
  wifi: mt76: mt7925: add link handling in the mt7925_ipv6_addr_change
  ...
====================

Link: https://patch.msgid.link/20240711102353.0C849C116B1@smtp.kernel.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents cef4902b dabcfd5e
......@@ -17,6 +17,7 @@ description: |
properties:
compatible:
enum:
- pci17cb,1101 # QCA6390
- pci17cb,1103 # WCN6855
reg:
......@@ -28,10 +29,55 @@ properties:
string to uniquely identify variant of the calibration data for designs
with colliding bus and device ids
vddrfacmn-supply:
description: VDD_RFA_CMN supply regulator handle
vddaon-supply:
description: VDD_AON supply regulator handle
vddwlcx-supply:
description: VDD_WL_CX supply regulator handle
vddwlmx-supply:
description: VDD_WL_MX supply regulator handle
vddrfa0p8-supply:
description: VDD_RFA_0P8 supply regulator handle
vddrfa1p2-supply:
description: VDD_RFA_1P2 supply regulator handle
vddrfa1p7-supply:
description: VDD_RFA_1P7 supply regulator handle
vddpcie0p9-supply:
description: VDD_PCIE_0P9 supply regulator handle
vddpcie1p8-supply:
description: VDD_PCIE_1P8 supply regulator handle
required:
- compatible
- reg
allOf:
- if:
properties:
compatible:
contains:
const: pci17cb,1101
then:
required:
- vddrfacmn-supply
- vddaon-supply
- vddwlcx-supply
- vddwlmx-supply
- vddrfa0p8-supply
- vddrfa1p2-supply
- vddrfa1p7-supply
- vddpcie0p9-supply
- vddpcie1p8-supply
additionalProperties: false
examples:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2024 Linaro Limited
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/wireless/qcom,ath12k.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies ath12k wireless devices (PCIe)
maintainers:
- Jeff Johnson <quic_jjohnson@quicinc.com>
- Kalle Valo <kvalo@kernel.org>
description:
Qualcomm Technologies IEEE 802.11be PCIe devices.
properties:
compatible:
enum:
- pci17cb,1107 # WCN7850
reg:
maxItems: 1
vddaon-supply:
description: VDD_AON supply regulator handle
vddwlcx-supply:
description: VDD_WLCX supply regulator handle
vddwlmx-supply:
description: VDD_WLMX supply regulator handle
vddrfacmn-supply:
description: VDD_RFA_CMN supply regulator handle
vddrfa0p8-supply:
description: VDD_RFA_0P8 supply regulator handle
vddrfa1p2-supply:
description: VDD_RFA_1P2 supply regulator handle
vddrfa1p8-supply:
description: VDD_RFA_1P8 supply regulator handle
vddpcie0p9-supply:
description: VDD_PCIE_0P9 supply regulator handle
vddpcie1p8-supply:
description: VDD_PCIE_1P8 supply regulator handle
required:
- compatible
- reg
- vddaon-supply
- vddwlcx-supply
- vddwlmx-supply
- vddrfacmn-supply
- vddrfa0p8-supply
- vddrfa1p2-supply
- vddrfa1p8-supply
- vddpcie0p9-supply
- vddpcie1p8-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/gpio/gpio.h>
pcie {
#address-cells = <3>;
#size-cells = <2>;
pcie@0 {
device_type = "pci";
reg = <0x0 0x0 0x0 0x0 0x0>;
#address-cells = <3>;
#size-cells = <2>;
ranges;
bus-range = <0x01 0xff>;
wifi@0 {
compatible = "pci17cb,1107";
reg = <0x10000 0x0 0x0 0x0 0x0>;
vddaon-supply = <&vreg_pmu_aon_0p59>;
vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>;
vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
};
};
};
......@@ -1877,8 +1877,7 @@ static void ath11k_dp_rx_h_csum_offload(struct ath11k *ar, struct sk_buff *msdu)
CHECKSUM_NONE : CHECKSUM_UNNECESSARY;
}
static int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar,
enum hal_encrypt_type enctype)
int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, enum hal_encrypt_type enctype)
{
switch (enctype) {
case HAL_ENCRYPT_TYPE_OPEN:
......
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_DP_RX_H
#define ATH11K_DP_RX_H
......@@ -95,4 +96,6 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id
int ath11k_dp_rx_pktlog_start(struct ath11k_base *ab);
int ath11k_dp_rx_pktlog_stop(struct ath11k_base *ab, bool stop_timer);
int ath11k_dp_rx_crypto_mic_len(struct ath11k *ar, enum hal_encrypt_type enctype);
#endif /* ATH11K_DP_RX_H */
......@@ -353,8 +353,12 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
if (ts->acked) {
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR +
ts->ack_rssi;
info->status.ack_signal = ts->ack_rssi;
if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
ab->wmi_ab.svc_map))
info->status.ack_signal += ATH11K_DEFAULT_NOISE_FLOOR;
info->status.flags |=
IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
} else {
......@@ -584,8 +588,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
if (ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED &&
!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR +
ts->ack_rssi;
info->status.ack_signal = ts->ack_rssi;
if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
ab->wmi_ab.svc_map))
info->status.ack_signal += ATH11K_DEFAULT_NOISE_FLOOR;
info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
}
......
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021, 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_DP_TX_H
......@@ -13,7 +13,7 @@
struct ath11k_dp_htt_wbm_tx_status {
u32 msdu_id;
bool acked;
int ack_rssi;
s8 ack_rssi;
u16 peer_id;
};
......
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_HAL_TX_H
......@@ -54,7 +54,7 @@ struct hal_tx_info {
struct hal_tx_status {
enum hal_wbm_rel_src_module buf_rel_source;
enum hal_wbm_tqm_rel_reason status;
u8 ack_rssi;
s8 ack_rssi;
u32 flags; /* %HAL_TX_STATUS_FLAGS_ */
u32 ppdu_id;
u8 try_cnt;
......
......@@ -4229,6 +4229,7 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
arg.key_cipher = WMI_CIPHER_AES_CCM;
/* TODO: Re-check if flag is valid */
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
......@@ -4238,12 +4239,10 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
arg.key_txmic_len = 8;
arg.key_rxmic_len = 8;
break;
case WLAN_CIPHER_SUITE_CCMP_256:
arg.key_cipher = WMI_CIPHER_AES_CCM;
break;
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
arg.key_cipher = WMI_CIPHER_AES_GCM;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
break;
default:
ath11k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
......@@ -5903,7 +5902,10 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
{
struct ath11k_base *ab = ar->ab;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
struct ieee80211_tx_info *info;
enum hal_encrypt_type enctype;
unsigned int mic_len;
dma_addr_t paddr;
int buf_id;
int ret;
......@@ -5927,7 +5929,12 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
ieee80211_is_deauth(hdr->frame_control) ||
ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control)) {
skb_put(skb, IEEE80211_CCMP_MIC_LEN);
if (!(skb_cb->flags & ATH11K_SKB_CIPHER_SET))
ath11k_warn(ab, "WMI management tx frame without ATH11K_SKB_CIPHER_SET");
enctype = ath11k_dp_tx_get_encrypt_type(skb_cb->cipher);
mic_len = ath11k_dp_rx_crypto_mic_len(ar, enctype);
skb_put(skb, mic_len);
}
}
......@@ -8977,8 +8984,11 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
}
sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) +
ATH11K_DEFAULT_NOISE_FLOOR;
sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi);
if (!db2dbm)
sinfo->signal_avg += ATH11K_DEFAULT_NOISE_FLOOR;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
}
......@@ -9020,7 +9030,12 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
offload = &arvif->arp_ns_offload;
count = 0;
/* Note: read_lock_bh() calls rcu_read_lock() */
/* The _ipv6_changed() is called with RCU lock already held in
* atomic_notifier_call_chain(), so we don't need to call
* rcu_read_lock() again here. But note that with CONFIG_PREEMPT_RT
* enabled, read_lock_bh() also calls rcu_read_lock(). This is OK
* because RCU read critical section is allowed to get nested.
*/
read_lock_bh(&idev->lock);
memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr));
......
......@@ -2859,7 +2859,7 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab,
int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
{
int timeout;
long time_left;
if (!ath11k_core_coldboot_cal_support(ab) ||
ab->hw_params.cbcal_restart_fw == 0)
......@@ -2867,11 +2867,11 @@ int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
ath11k_dbg(ab, ATH11K_DBG_QMI, "wait for cold boot done\n");
timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
(ab->qmi.cal_done == 1),
ATH11K_COLD_BOOT_FW_RESET_DELAY);
time_left = wait_event_timeout(ab->qmi.cold_boot_waitq,
(ab->qmi.cal_done == 1),
ATH11K_COLD_BOOT_FW_RESET_DELAY);
if (timeout <= 0) {
if (time_left <= 0) {
ath11k_warn(ab, "Coldboot Calibration timed out\n");
return -ETIMEDOUT;
}
......@@ -2886,7 +2886,7 @@ EXPORT_SYMBOL(ath11k_qmi_fwreset_from_cold_boot);
static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab)
{
int timeout;
long time_left;
int ret;
ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_COLD_BOOT);
......@@ -2897,10 +2897,10 @@ static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab)
ath11k_dbg(ab, ATH11K_DBG_QMI, "Coldboot calibration wait started\n");
timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
(ab->qmi.cal_done == 1),
ATH11K_COLD_BOOT_FW_RESET_DELAY);
if (timeout <= 0) {
time_left = wait_event_timeout(ab->qmi.cold_boot_waitq,
(ab->qmi.cal_done == 1),
ATH11K_COLD_BOOT_FW_RESET_DELAY);
if (time_left <= 0) {
ath11k_warn(ab, "coldboot calibration timed out\n");
return 0;
}
......
......@@ -23,9 +23,10 @@ ath12k-y += core.o \
fw.o \
p2p.o
ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o
ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o
ath12k-$(CONFIG_ACPI) += acpi.o
ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
ath12k-$(CONFIG_PM) += wow.o
# for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src)
......@@ -391,4 +391,6 @@ void ath12k_acpi_stop(struct ath12k_base *ab)
acpi_remove_notify_handler(ACPI_HANDLE(ab->dev),
ACPI_DEVICE_NOTIFY,
ath12k_acpi_dsm_notify);
memset(&ab->acpi, 0, sizeof(ab->acpi));
}
......@@ -16,6 +16,7 @@
#include "hif.h"
#include "fw.h"
#include "debugfs.h"
#include "wow.h"
unsigned int ath12k_debug_mask;
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
......@@ -42,14 +43,38 @@ static int ath12k_core_rfkill_config(struct ath12k_base *ab)
return ret;
}
int ath12k_core_suspend(struct ath12k_base *ab)
/* Check if we need to continue with suspend/resume operation.
* Return:
* a negative value: error happens and don't continue.
* 0: no error but don't continue.
* positive value: no error and do continue.
*/
static int ath12k_core_continue_suspend_resume(struct ath12k_base *ab)
{
struct ath12k *ar;
int ret, i;
if (!ab->hw_params->supports_suspend)
return -EOPNOTSUPP;
/* so far single_pdev_only chips have supports_suspend as true
* so pass 0 as a dummy pdev_id here.
*/
ar = ab->pdevs[0].ar;
if (!ar || !ar->ah || ar->ah->state != ATH12K_HW_STATE_OFF)
return 0;
return 1;
}
int ath12k_core_suspend(struct ath12k_base *ab)
{
struct ath12k *ar;
int ret, i;
ret = ath12k_core_continue_suspend_resume(ab);
if (ret <= 0)
return ret;
for (i = 0; i < ab->num_radios; i++) {
ar = ab->pdevs[i].ar;
if (!ar)
......@@ -80,8 +105,13 @@ EXPORT_SYMBOL(ath12k_core_suspend);
int ath12k_core_suspend_late(struct ath12k_base *ab)
{
if (!ab->hw_params->supports_suspend)
return -EOPNOTSUPP;
int ret;
ret = ath12k_core_continue_suspend_resume(ab);
if (ret <= 0)
return ret;
ath12k_acpi_stop(ab);
ath12k_hif_irq_disable(ab);
ath12k_hif_ce_irq_disable(ab);
......@@ -96,8 +126,9 @@ int ath12k_core_resume_early(struct ath12k_base *ab)
{
int ret;
if (!ab->hw_params->supports_suspend)
return -EOPNOTSUPP;
ret = ath12k_core_continue_suspend_resume(ab);
if (ret <= 0)
return ret;
reinit_completion(&ab->restart_completed);
ret = ath12k_hif_power_up(ab);
......@@ -111,9 +142,11 @@ EXPORT_SYMBOL(ath12k_core_resume_early);
int ath12k_core_resume(struct ath12k_base *ab)
{
long time_left;
int ret;
if (!ab->hw_params->supports_suspend)
return -EOPNOTSUPP;
ret = ath12k_core_continue_suspend_resume(ab);
if (ret <= 0)
return ret;
time_left = wait_for_completion_timeout(&ab->restart_completed,
ATH12K_RESET_TIMEOUT_HZ);
......@@ -1059,8 +1092,6 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
mutex_unlock(&ar->conf_mutex);
}
/* Restart after all the link/radio halt */
ieee80211_restart_hw(ah->hw);
break;
case ATH12K_HW_STATE_OFF:
ath12k_warn(ab,
......@@ -1087,7 +1118,8 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
static void ath12k_core_restart(struct work_struct *work)
{
struct ath12k_base *ab = container_of(work, struct ath12k_base, restart_work);
int ret;
struct ath12k_hw *ah;
int ret, i;
ret = ath12k_core_reconfigure_on_crash(ab);
if (ret) {
......@@ -1095,8 +1127,12 @@ static void ath12k_core_restart(struct work_struct *work)
return;
}
if (ab->is_reset)
complete_all(&ab->reconfigure_complete);
if (ab->is_reset) {
for (i = 0; i < ab->num_hw; i++) {
ah = ab->ah[i];
ieee80211_restart_hw(ah->hw);
}
}
complete(&ab->restart_completed);
}
......@@ -1150,20 +1186,14 @@ static void ath12k_core_reset(struct work_struct *work)
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset starting\n");
ab->is_reset = true;
atomic_set(&ab->recovery_start_count, 0);
reinit_completion(&ab->recovery_start);
atomic_set(&ab->recovery_count, 0);
ath12k_core_pre_reconfigure_recovery(ab);
reinit_completion(&ab->reconfigure_complete);
ath12k_core_post_reconfigure_recovery(ab);
ath12k_dbg(ab, ATH12K_DBG_BOOT, "waiting recovery start...\n");
time_left = wait_for_completion_timeout(&ab->recovery_start,
ATH12K_RECOVER_START_TIMEOUT_HZ);
ath12k_hif_irq_disable(ab);
ath12k_hif_ce_irq_disable(ab);
......@@ -1275,8 +1305,6 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
mutex_init(&ab->core_lock);
spin_lock_init(&ab->base_lock);
init_completion(&ab->reset_complete);
init_completion(&ab->reconfigure_complete);
init_completion(&ab->recovery_start);
INIT_LIST_HEAD(&ab->peers);
init_waitqueue_head(&ab->peer_mapping_wq);
......@@ -1288,6 +1316,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0);
init_completion(&ab->htc_suspend);
init_completion(&ab->restart_completed);
init_completion(&ab->wow.wakeup_completed);
ab->dev = dev;
ab->hif.bus = bus;
......
......@@ -28,6 +28,8 @@
#include "dbring.h"
#include "fw.h"
#include "acpi.h"
#include "wow.h"
#include "debugfs_htt_stats.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
......@@ -229,6 +231,13 @@ struct ath12k_vif_cache {
u32 bss_conf_changed;
};
struct ath12k_rekey_data {
u8 kck[NL80211_KCK_LEN];
u8 kek[NL80211_KCK_LEN];
u64 replay_ctr;
bool enable_offload;
};
struct ath12k_vif {
u32 vdev_id;
enum wmi_vdev_type vdev_type;
......@@ -285,6 +294,7 @@ struct ath12k_vif {
u32 punct_bitmap;
bool ps;
struct ath12k_vif_cache *cache;
struct ath12k_rekey_data rekey_data;
};
struct ath12k_vif_iter {
......@@ -472,8 +482,17 @@ struct ath12k_fw_stats {
struct list_head bcn;
};
struct ath12k_dbg_htt_stats {
enum ath12k_dbg_htt_ext_stats_type type;
u32 cfg_param[4];
u8 reset;
struct debug_htt_stats_req *stats_req;
};
struct ath12k_debug {
struct dentry *debugfs_pdev;
struct dentry *debugfs_pdev_symlink;
struct ath12k_dbg_htt_stats htt_stats;
};
struct ath12k_per_peer_tx_stats {
......@@ -606,6 +625,9 @@ struct ath12k {
struct work_struct wmi_mgmt_tx_work;
struct sk_buff_head wmi_mgmt_tx_queue;
struct ath12k_wow wow;
struct completion target_suspend;
bool target_suspend_ack;
struct ath12k_per_peer_tx_stats peer_tx_stats;
struct list_head ppdu_stats_info;
u32 ppdu_stat_list_depth;
......@@ -625,12 +647,12 @@ struct ath12k {
u32 freq_low;
u32 freq_high;
bool nlo_enabled;
};
struct ath12k_hw {
struct ieee80211_hw *hw;
struct ath12k_base *ab;
/* Protect the write operation of the hardware state ath12k_hw::state
* between hardware start<=>reconfigure<=>stop transitions.
*/
......@@ -766,6 +788,11 @@ struct ath12k_base {
const struct ath12k_hif_ops *ops;
} hif;
struct {
struct completion wakeup_completed;
u32 wmi_conf_rx_decap_mode;
} wow;
struct ath12k_ce ce;
struct timer_list rx_replenish_retry;
struct ath12k_hal hal;
......@@ -848,11 +875,8 @@ struct ath12k_base {
struct work_struct reset_work;
atomic_t reset_count;
atomic_t recovery_count;
atomic_t recovery_start_count;
bool is_reset;
struct completion reset_complete;
struct completion reconfigure_complete;
struct completion recovery_start;
/* continuous recovery fail count */
atomic_t fail_cont_count;
unsigned long reset_fail_timeout;
......
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _ATH12K_DEBUG_H_
......@@ -25,6 +25,7 @@ enum ath12k_debug_mask {
ATH12K_DBG_PCI = 0x00001000,
ATH12K_DBG_DP_TX = 0x00002000,
ATH12K_DBG_DP_RX = 0x00004000,
ATH12K_DBG_WOW = 0x00008000,
ATH12K_DBG_ANY = 0xffffffff,
};
......
......@@ -6,6 +6,7 @@
#include "core.h"
#include "debugfs.h"
#include "debugfs_htt_stats.h"
static ssize_t ath12k_write_simulate_radar(struct file *file,
const char __user *user_buf,
......@@ -80,11 +81,27 @@ void ath12k_debugfs_register(struct ath12k *ar)
/* Create a symlink under ieee80211/phy* */
scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
debugfs_create_symlink("ath12k", hw->wiphy->debugfsdir, buf);
ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
hw->wiphy->debugfsdir,
buf);
if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
debugfs_create_file("dfs_simulate_radar", 0200,
ar->debug.debugfs_pdev, ar,
&fops_simulate_radar);
}
ath12k_debugfs_htt_stats_register(ar);
}
void ath12k_debugfs_unregister(struct ath12k *ar)
{
if (!ar->debug.debugfs_pdev)
return;
/* Remove symlink under ieee80211/phy* */
debugfs_remove(ar->debug.debugfs_pdev_symlink);
debugfs_remove_recursive(ar->debug.debugfs_pdev);
ar->debug.debugfs_pdev_symlink = NULL;
ar->debug.debugfs_pdev = NULL;
}
......@@ -11,7 +11,7 @@
void ath12k_debugfs_soc_create(struct ath12k_base *ab);
void ath12k_debugfs_soc_destroy(struct ath12k_base *ab);
void ath12k_debugfs_register(struct ath12k *ar);
void ath12k_debugfs_unregister(struct ath12k *ar);
#else
static inline void ath12k_debugfs_soc_create(struct ath12k_base *ab)
{
......@@ -25,6 +25,10 @@ static inline void ath12k_debugfs_register(struct ath12k *ar)
{
}
static inline void ath12k_debugfs_unregister(struct ath12k *ar)
{
}
#endif /* CONFIG_ATH12K_DEBUGFS */
#endif /* _ATH12K_DEBUGFS_H_ */
This diff is collapsed.
This diff is collapsed.
......@@ -333,6 +333,7 @@ struct ath12k_dp {
struct dp_srng reo_except_ring;
struct dp_srng reo_cmd_ring;
struct dp_srng reo_status_ring;
enum ath12k_peer_metadata_version peer_metadata_ver;
struct dp_srng reo_dst_ring[DP_REO_DST_RING_MAX];
struct dp_tx_ring tx_ring[DP_TCL_NUM_RING_MAX];
struct hal_wbm_idle_scatter_list scatter_list[DP_IDLE_SCATTER_BUFS_MAX];
......
......@@ -17,6 +17,7 @@
#include "dp_tx.h"
#include "peer.h"
#include "dp_mon.h"
#include "debugfs_htt_stats.h"
#define ATH12K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ)
......@@ -1268,10 +1269,10 @@ static int ath12k_htt_tlv_ppdu_stats_parse(struct ath12k_base *ab,
return 0;
}
static int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
const void *ptr, void *data),
void *data)
int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
const void *ptr, void *data),
void *data)
{
const struct htt_tlv *tlv;
const void *begin = ptr;
......@@ -1741,6 +1742,7 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
ath12k_htt_pull_ppdu_stats(ab, skb);
break;
case HTT_T2H_MSG_TYPE_EXT_STATS_CONF:
ath12k_debugfs_htt_ext_stats_handler(ab, skb);
break;
case HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND:
ath12k_htt_mlo_offset_event_handler(ab, skb);
......@@ -2583,6 +2585,29 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
rcu_read_unlock();
}
static u16 ath12k_dp_rx_get_peer_id(struct ath12k_base *ab,
enum ath12k_peer_metadata_version ver,
__le32 peer_metadata)
{
switch (ver) {
default:
ath12k_warn(ab, "Unknown peer metadata version: %d", ver);
fallthrough;
case ATH12K_PEER_METADATA_V0:
return le32_get_bits(peer_metadata,
RX_MPDU_DESC_META_DATA_V0_PEER_ID);
case ATH12K_PEER_METADATA_V1:
return le32_get_bits(peer_metadata,
RX_MPDU_DESC_META_DATA_V1_PEER_ID);
case ATH12K_PEER_METADATA_V1A:
return le32_get_bits(peer_metadata,
RX_MPDU_DESC_META_DATA_V1A_PEER_ID);
case ATH12K_PEER_METADATA_V1B:
return le32_get_bits(peer_metadata,
RX_MPDU_DESC_META_DATA_V1B_PEER_ID);
}
}
int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
struct napi_struct *napi, int budget)
{
......@@ -2611,6 +2636,8 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
ath12k_hal_srng_access_begin(ab, srng);
while ((desc = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
struct rx_mpdu_desc *mpdu_info;
struct rx_msdu_desc *msdu_info;
enum hal_reo_dest_ring_push_reason push_reason;
u32 cookie;
......@@ -2658,16 +2685,19 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
continue;
}
rxcb->is_first_msdu = !!(le32_to_cpu(desc->rx_msdu_info.info0) &
msdu_info = &desc->rx_msdu_info;
mpdu_info = &desc->rx_mpdu_info;
rxcb->is_first_msdu = !!(le32_to_cpu(msdu_info->info0) &
RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU);
rxcb->is_last_msdu = !!(le32_to_cpu(desc->rx_msdu_info.info0) &
rxcb->is_last_msdu = !!(le32_to_cpu(msdu_info->info0) &
RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU);
rxcb->is_continuation = !!(le32_to_cpu(desc->rx_msdu_info.info0) &
rxcb->is_continuation = !!(le32_to_cpu(msdu_info->info0) &
RX_MSDU_DESC_INFO0_MSDU_CONTINUATION);
rxcb->mac_id = mac_id;
rxcb->peer_id = le32_get_bits(desc->rx_mpdu_info.peer_meta_data,
RX_MPDU_DESC_META_DATA_PEER_ID);
rxcb->tid = le32_get_bits(desc->rx_mpdu_info.info0,
rxcb->peer_id = ath12k_dp_rx_get_peer_id(ab, dp->peer_metadata_ver,
mpdu_info->peer_meta_data);
rxcb->tid = le32_get_bits(mpdu_info->info0,
RX_MPDU_DESC_INFO0_TID);
__skb_queue_tail(&msdu_list, msdu);
......@@ -3402,7 +3432,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
struct ath12k *ar;
dma_addr_t paddr;
bool is_frag;
bool drop = false;
bool drop;
int pdev_id;
tot_n_bufs_reaped = 0;
......@@ -3420,7 +3450,9 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
while (budget &&
(reo_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
drop = false;
ab->soc_stats.err_ring_pkts++;
ret = ath12k_hal_desc_reo_parse_err(ab, reo_desc, &paddr,
&desc_bank);
if (ret) {
......
......@@ -139,4 +139,8 @@ ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu);
int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab);
int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab);
int ath12k_dp_htt_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
int (*iter)(struct ath12k_base *ar, u16 tag, u16 len,
const void *ptr, void *data),
void *data);
#endif /* ATH12K_DP_RX_H */
......@@ -1086,6 +1086,7 @@ ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
struct htt_ext_stats_cfg_cmd *cmd;
int len = sizeof(*cmd);
int ret;
u32 pdev_id;
skb = ath12k_htc_alloc_skb(ab, len);
if (!skb)
......@@ -1097,7 +1098,8 @@ ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,
memset(cmd, 0, sizeof(*cmd));
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG;
cmd->hdr.pdev_mask = 1 << ar->pdev->pdev_id;
pdev_id = ath12k_mac_get_target_pdev_id(ar);
cmd->hdr.pdev_mask = 1 << pdev_id;
cmd->hdr.stats_type = type;
cmd->cfg_param0 = cpu_to_le32(cfg_params->cfg0);
......
......@@ -597,8 +597,30 @@ struct hal_tlv_64_hdr {
#define RX_MPDU_DESC_INFO0_MPDU_QOS_CTRL_VALID BIT(27)
#define RX_MPDU_DESC_INFO0_TID GENMASK(31, 28)
/* TODO revisit after meta data is concluded */
#define RX_MPDU_DESC_META_DATA_PEER_ID GENMASK(15, 0)
/* Peer Metadata classification */
/* Version 0 */
#define RX_MPDU_DESC_META_DATA_V0_PEER_ID GENMASK(15, 0)
#define RX_MPDU_DESC_META_DATA_V0_VDEV_ID GENMASK(23, 16)
/* Version 1 */
#define RX_MPDU_DESC_META_DATA_V1_PEER_ID GENMASK(13, 0)
#define RX_MPDU_DESC_META_DATA_V1_LOGICAL_LINK_ID GENMASK(15, 14)
#define RX_MPDU_DESC_META_DATA_V1_VDEV_ID GENMASK(23, 16)
#define RX_MPDU_DESC_META_DATA_V1_LMAC_ID GENMASK(25, 24)
#define RX_MPDU_DESC_META_DATA_V1_DEVICE_ID GENMASK(28, 26)
/* Version 1A */
#define RX_MPDU_DESC_META_DATA_V1A_PEER_ID GENMASK(13, 0)
#define RX_MPDU_DESC_META_DATA_V1A_VDEV_ID GENMASK(21, 14)
#define RX_MPDU_DESC_META_DATA_V1A_LOGICAL_LINK_ID GENMASK(25, 22)
#define RX_MPDU_DESC_META_DATA_V1A_DEVICE_ID GENMASK(28, 26)
/* Version 1B */
#define RX_MPDU_DESC_META_DATA_V1B_PEER_ID GENMASK(13, 0)
#define RX_MPDU_DESC_META_DATA_V1B_VDEV_ID GENMASK(21, 14)
#define RX_MPDU_DESC_META_DATA_V1B_HW_LINK_ID GENMASK(25, 22)
#define RX_MPDU_DESC_META_DATA_V1B_DEVICE_ID GENMASK(28, 26)
struct rx_mpdu_desc {
__le32 info0; /* %RX_MPDU_DESC_INFO */
......
......@@ -244,6 +244,11 @@ static void ath12k_htc_suspend_complete(struct ath12k_base *ab, bool ack)
complete(&ab->htc_suspend);
}
static void ath12k_htc_wakeup_from_suspend(struct ath12k_base *ab)
{
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot wakeup from suspend is received\n");
}
void ath12k_htc_rx_completion_handler(struct ath12k_base *ab,
struct sk_buff *skb)
{
......@@ -349,6 +354,7 @@ void ath12k_htc_rx_completion_handler(struct ath12k_base *ab,
ath12k_htc_suspend_complete(ab, false);
break;
case ATH12K_HTC_MSG_WAKEUP_FROM_SUSPEND_ID:
ath12k_htc_wakeup_from_suspend(ab);
break;
default:
ath12k_warn(ab, "ignoring unsolicited htc ep0 event %u\n",
......
......@@ -78,8 +78,6 @@
#define TARGET_NUM_WDS_ENTRIES 32
#define TARGET_DMA_BURST_SIZE 1
#define TARGET_RX_BATCHMODE 1
#define TARGET_RX_PEER_METADATA_VER_V1A 2
#define TARGET_RX_PEER_METADATA_VER_V1B 3
#define TARGET_EMA_MAX_PROFILE_PERIOD 8
#define ATH12K_HW_DEFAULT_QUEUE 0
......
This diff is collapsed.
......@@ -9,6 +9,7 @@
#include <net/mac80211.h>
#include <net/cfg80211.h>
#include "wmi.h"
struct ath12k;
struct ath12k_base;
......@@ -81,5 +82,9 @@ int ath12k_mac_rfkill_config(struct ath12k *ar);
int ath12k_mac_wait_tx_complete(struct ath12k *ar);
void ath12k_mac_handle_beacon(struct ath12k *ar, struct sk_buff *skb);
void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id);
int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif,
enum wmi_sta_keepalive_method method,
u32 interval);
u8 ath12k_mac_get_target_pdev_id(struct ath12k *ar);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH12K_WOW_H
#define ATH12K_WOW_H
#define ATH12K_WOW_RETRY_NUM 10
#define ATH12K_WOW_RETRY_WAIT_MS 200
#define ATH12K_WOW_PATTERNS 22
struct ath12k_wow {
u32 max_num_patterns;
struct completion wakeup_completed;
struct wiphy_wowlan_support wowlan_support;
};
struct ath12k_pkt_pattern {
u8 pattern[WOW_MAX_PATTERN_SIZE];
u8 bytemask[WOW_MAX_PATTERN_SIZE];
int pattern_len;
int pkt_offset;
};
struct rfc1042_hdr {
u8 llc_dsap;
u8 llc_ssap;
u8 llc_ctrl;
u8 snap_oui[3];
__be16 eth_type;
} __packed;
#ifdef CONFIG_PM
int ath12k_wow_init(struct ath12k *ar);
int ath12k_wow_op_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan);
int ath12k_wow_op_resume(struct ieee80211_hw *hw);
void ath12k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled);
int ath12k_wow_enable(struct ath12k *ar);
int ath12k_wow_wakeup(struct ath12k *ar);
#else
static inline int ath12k_wow_init(struct ath12k *ar)
{
return 0;
}
static inline int ath12k_wow_enable(struct ath12k *ar)
{
return 0;
}
static inline int ath12k_wow_wakeup(struct ath12k *ar)
{
return 0;
}
#endif /* CONFIG_PM */
#endif /* ATH12K_WOW_H */
......@@ -180,11 +180,10 @@ static struct libipw_txb *libipw_alloc_txb(int nr_frags, int txb_size,
struct libipw_txb *txb;
int i;
txb = kmalloc(struct_size(txb, fragments, nr_frags), gfp_mask);
txb = kzalloc(struct_size(txb, fragments, nr_frags), gfp_mask);
if (!txb)
return NULL;
memset(txb, 0, sizeof(struct libipw_txb));
txb->nr_frags = nr_frags;
txb->frag_size = txb_size;
......
......@@ -147,32 +147,34 @@ struct iwl_fw_ini_region_internal_buffer {
* Configures parameters for region data collection
*
* @hdr: debug header
* @id: region id. Max id is &IWL_FW_INI_MAX_REGION_ID
* @id: region id. Max id is %IWL_FW_INI_MAX_REGION_ID
* @type: region type. One of &enum iwl_fw_ini_region_type
* @sub_type: region sub type
* @sub_type_ver: region sub type version
* @reserved: not in use
* @name: region name
* @dev_addr: device address configuration. Used by
* &IWL_FW_INI_REGION_DEVICE_MEMORY, &IWL_FW_INI_REGION_PERIPHERY_MAC,
* &IWL_FW_INI_REGION_PERIPHERY_PHY, &IWL_FW_INI_REGION_PERIPHERY_AUX,
* &IWL_FW_INI_REGION_PAGING, &IWL_FW_INI_REGION_CSR,
* &IWL_FW_INI_REGION_DRAM_IMR and &IWL_FW_INI_REGION_PCI_IOSF_CONFIG
* &IWL_FW_INI_REGION_DBGI_SRAM, &FW_TLV_DEBUG_REGION_TYPE_DBGI_SRAM,
* &IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP,
* %IWL_FW_INI_REGION_DEVICE_MEMORY, %IWL_FW_INI_REGION_PERIPHERY_MAC,
* %IWL_FW_INI_REGION_PERIPHERY_PHY, %IWL_FW_INI_REGION_PERIPHERY_AUX,
* %IWL_FW_INI_REGION_PAGING, %IWL_FW_INI_REGION_CSR,
* %IWL_FW_INI_REGION_DRAM_IMR and %IWL_FW_INI_REGION_PCI_IOSF_CONFIG
* %IWL_FW_INI_REGION_DBGI_SRAM, %FW_TLV_DEBUG_REGION_TYPE_DBGI_SRAM,
* %IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP,
* @dev_addr_range: device address range configuration. Used by
* &IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE and
* &IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE
* @fifos: fifos configuration. Used by &IWL_FW_INI_REGION_TXF and
* &IWL_FW_INI_REGION_RXF
* %IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE and
* %IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE
* @fifos: fifos configuration. Used by %IWL_FW_INI_REGION_TXF and
* %IWL_FW_INI_REGION_RXF
* @err_table: error table configuration. Used by
* IWL_FW_INI_REGION_LMAC_ERROR_TABLE and
* IWL_FW_INI_REGION_UMAC_ERROR_TABLE
* %IWL_FW_INI_REGION_LMAC_ERROR_TABLE and
* %IWL_FW_INI_REGION_UMAC_ERROR_TABLE
* @internal_buffer: internal monitor buffer configuration. Used by
* &IWL_FW_INI_REGION_INTERNAL_BUFFER
* %IWL_FW_INI_REGION_INTERNAL_BUFFER
* @special_mem: special device memory region, used by
* %IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY
* @dram_alloc_id: dram allocation id. One of &enum iwl_fw_ini_allocation_id.
* Used by &IWL_FW_INI_REGION_DRAM_BUFFER
* @tlv_mask: tlv collection mask. Used by &IWL_FW_INI_REGION_TLV
* Used by %IWL_FW_INI_REGION_DRAM_BUFFER
* @tlv_mask: tlv collection mask. Used by %IWL_FW_INI_REGION_TLV
* @addrs: array of addresses attached to the end of the region tlv
*/
struct iwl_fw_ini_region_tlv {
......
......@@ -144,6 +144,7 @@ struct iwl_phy_context_cmd_v1 {
* @rxchain_info: ???
* @sbb_bandwidth: 0 disabled, 1 - 40Mhz ... 4 - 320MHz
* @sbb_ctrl_channel_loc: location of the control channel
* @puncture_mask: bitmap of punctured subchannels
* @dsp_cfg_flags: set to 0
* @reserved: reserved to align to 64 bit
*/
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment