wifi: ath12k: Decrease ath12k_mac_station_assoc() stack usage
authorJeff Johnson <quic_jjohnson@quicinc.com>
Tue, 17 Dec 2024 20:26:18 +0000 (22:26 +0200)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Thu, 19 Dec 2024 17:41:04 +0000 (09:41 -0800)
Building the ath12k driver with llvm-18.1.7-x86_64 produces the warning:

drivers/net/wireless/ath/ath12k/mac.c:5606:12: warning: stack frame size (1176) exceeds limit (1024) in 'ath12k_mac_op_sta_state' [-Wframe-larger-than]

ath12k_mac_op_sta_state() itself does not consume much stack, but it
calls ath12k_mac_handle_link_sta_state() which in turn calls
ath12k_mac_station_add(). Since those are both static functions with
only one caller, it is suspected that these both get inlined, and
their stack usage is reported for ath12k_mac_op_sta_state().

A major contributor to the ath12k_mac_station_assoc() stack usage is:

struct ath12k_wmi_peer_assoc_arg peer_arg;

Avoid the excess stack usage by dynamically allocating peer_arg
instead of declaring it on the stack.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://patch.msgid.link/20241217202618.1329312-5-kvalo@kernel.org
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/mac.c

index 10293e9c1d4904ec70302388f846b760a9e49d72..6f10813d937820476afe8084ec4030b8eb9548a0 100644 (file)
@@ -4834,7 +4834,6 @@ static int ath12k_mac_station_assoc(struct ath12k *ar,
 {
        struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
        struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
-       struct ath12k_wmi_peer_assoc_arg peer_arg;
        struct ieee80211_link_sta *link_sta;
        int ret;
        struct cfg80211_chan_def def;
@@ -4854,14 +4853,19 @@ static int ath12k_mac_station_assoc(struct ath12k *ar,
        band = def.chan->band;
        mask = &arvif->bitrate_mask;
 
-       ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, reassoc);
+       struct ath12k_wmi_peer_assoc_arg *peer_arg __free(kfree) =
+               kzalloc(sizeof(*peer_arg), GFP_KERNEL);
+       if (!peer_arg)
+               return -ENOMEM;
 
-       if (peer_arg.peer_nss < 1) {
+       ath12k_peer_assoc_prepare(ar, arvif, arsta, peer_arg, reassoc);
+
+       if (peer_arg->peer_nss < 1) {
                ath12k_warn(ar->ab,
-                           "invalid peer NSS %d\n", peer_arg.peer_nss);
+                           "invalid peer NSS %d\n", peer_arg->peer_nss);
                return -EINVAL;
        }
-       ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
+       ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
        if (ret) {
                ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
                            arsta->addr, arvif->vdev_id, ret);