Skip to content

Commit 9a353a4

Browse files
Baochen Qiangjeff-t-johnson
authored andcommitted
wifi: ath12k: avoid burning CPU while waiting for firmware stats
ath12k_mac_get_fw_stats() is busy polling fw_stats_done flag while waiting firmware finishing sending all events. This is not good as CPU is monopolized and kept burning during the wait. Change to the completion mechanism to fix it. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00284.1-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Tested-on: QCN9274 hw2.0 WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1 Fixes: e367c92 ("wifi: ath12k: Request vdev stats from firmware") Reported-by: Grégoire Stein <[email protected]> Closes: https://lore.kernel.org/ath12k/AS8P190MB120575BBB25FCE697CD7D4988763A@AS8P190MB1205.EURP190.PROD.OUTLOOK.COM/ Signed-off-by: Baochen Qiang <[email protected]> Tested-by: Grégoire Stein <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jeff Johnson <[email protected]>
1 parent a48a931 commit 9a353a4

File tree

4 files changed

+14
-24
lines changed

4 files changed

+14
-24
lines changed

drivers/net/wireless/ath/ath12k/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,7 @@ void ath12k_fw_stats_init(struct ath12k *ar)
12161216
INIT_LIST_HEAD(&ar->fw_stats.pdevs);
12171217
INIT_LIST_HEAD(&ar->fw_stats.bcn);
12181218
init_completion(&ar->fw_stats_complete);
1219+
init_completion(&ar->fw_stats_done);
12191220
}
12201221

12211222
void ath12k_fw_stats_free(struct ath12k_fw_stats *stats)
@@ -1228,7 +1229,6 @@ void ath12k_fw_stats_free(struct ath12k_fw_stats *stats)
12281229
void ath12k_fw_stats_reset(struct ath12k *ar)
12291230
{
12301231
spin_lock_bh(&ar->data_lock);
1231-
ar->fw_stats.fw_stats_done = false;
12321232
ath12k_fw_stats_free(&ar->fw_stats);
12331233
spin_unlock_bh(&ar->data_lock);
12341234
}

drivers/net/wireless/ath/ath12k/core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,6 @@ struct ath12k_fw_stats {
632632
struct list_head pdevs;
633633
struct list_head vdevs;
634634
struct list_head bcn;
635-
bool fw_stats_done;
636635
};
637636

638637
struct ath12k_dbg_htt_stats {
@@ -812,6 +811,7 @@ struct ath12k {
812811
bool regdom_set_by_user;
813812

814813
struct completion fw_stats_complete;
814+
struct completion fw_stats_done;
815815

816816
struct completion mlo_setup_done;
817817
u32 mlo_setup_status;

drivers/net/wireless/ath/ath12k/mac.c

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4360,27 +4360,21 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar,
43604360
{
43614361
struct ath12k_base *ab = ar->ab;
43624362
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
4363-
unsigned long timeout, time_left;
4363+
unsigned long time_left;
43644364
int ret;
43654365

43664366
guard(mutex)(&ah->hw_mutex);
43674367

43684368
if (ah->state != ATH12K_HW_STATE_ON)
43694369
return -ENETDOWN;
43704370

4371-
/* FW stats can get split when exceeding the stats data buffer limit.
4372-
* In that case, since there is no end marking for the back-to-back
4373-
* received 'update stats' event, we keep a 3 seconds timeout in case,
4374-
* fw_stats_done is not marked yet
4375-
*/
4376-
timeout = jiffies + msecs_to_jiffies(3 * 1000);
43774371
ath12k_fw_stats_reset(ar);
43784372

43794373
reinit_completion(&ar->fw_stats_complete);
4374+
reinit_completion(&ar->fw_stats_done);
43804375

43814376
ret = ath12k_wmi_send_stats_request_cmd(ar, param->stats_id,
43824377
param->vdev_id, param->pdev_id);
4383-
43844378
if (ret) {
43854379
ath12k_warn(ab, "failed to request fw stats: %d\n", ret);
43864380
return ret;
@@ -4391,7 +4385,6 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar,
43914385
param->pdev_id, param->vdev_id, param->stats_id);
43924386

43934387
time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
4394-
43954388
if (!time_left) {
43964389
ath12k_warn(ab, "time out while waiting for get fw stats\n");
43974390
return -ETIMEDOUT;
@@ -4400,19 +4393,15 @@ int ath12k_mac_get_fw_stats(struct ath12k *ar,
44004393
/* Firmware sends WMI_UPDATE_STATS_EVENTID back-to-back
44014394
* when stats data buffer limit is reached. fw_stats_complete
44024395
* is completed once host receives first event from firmware, but
4403-
* still there could be more events following. Below loop is to wait
4396+
* still there could be more events following. Below is to wait
44044397
* until firmware completes sending all the events.
44054398
*/
4406-
for (;;) {
4407-
if (time_after(jiffies, timeout))
4408-
break;
4409-
spin_lock_bh(&ar->data_lock);
4410-
if (ar->fw_stats.fw_stats_done) {
4411-
spin_unlock_bh(&ar->data_lock);
4412-
break;
4413-
}
4414-
spin_unlock_bh(&ar->data_lock);
4399+
time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ);
4400+
if (!time_left) {
4401+
ath12k_warn(ab, "time out while waiting for fw stats done\n");
4402+
return -ETIMEDOUT;
44154403
}
4404+
44164405
return 0;
44174406
}
44184407

drivers/net/wireless/ath/ath12k/wmi.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8192,11 +8192,12 @@ static void ath12k_wmi_fw_stats_process(struct ath12k *ar,
81928192
&ar->fw_stats.vdevs);
81938193

81948194
if (is_end) {
8195-
ar->fw_stats.fw_stats_done = true;
8195+
complete(&ar->fw_stats_done);
81968196
num_vdev = 0;
81978197
}
81988198
return;
81998199
}
8200+
82008201
if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
82018202
if (list_empty(&stats->bcn)) {
82028203
ath12k_warn(ab, "empty beacon stats");
@@ -8211,7 +8212,7 @@ static void ath12k_wmi_fw_stats_process(struct ath12k *ar,
82118212
&ar->fw_stats.bcn);
82128213

82138214
if (is_end) {
8214-
ar->fw_stats.fw_stats_done = true;
8215+
complete(&ar->fw_stats_done);
82158216
num_bcn = 0;
82168217
}
82178218
}
@@ -8249,7 +8250,7 @@ static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *sk
82498250
/* Handle WMI_REQUEST_PDEV_STAT status update */
82508251
if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
82518252
list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs);
8252-
ar->fw_stats.fw_stats_done = true;
8253+
complete(&ar->fw_stats_done);
82538254
goto complete;
82548255
}
82558256

0 commit comments

Comments
 (0)