The Wi-Fi 7 REO send path submits a hardware command before allocating the software entry used to match its completion. If the atomic allocation then fails, the function returns -ENOMEM even though the command is already in flight. The completion cannot be matched to a callback, and callers may retry an operation whose first command was accepted by hardware. This can skip RX TID cleanup or issue duplicate queue operations under memory pressure. Allocate and initialize the pending-command context before writing the REO ring. Free it when hardware submission fails or returns an invalid command number. Commands without callbacks continue to avoid the allocation. This changes only the Wi-Fi 7 command sender; the Wi-Fi 8 ring path already allocates callback state before submission. Found during code review. Fixes: 52c555680bae ("wifi: ath12k: Move arch specific rx tid and related functions to wifi7 directory") Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k Signed-off-by: Pradeep Kumar Chitrapu --- drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 35 +++++++++++++++++---------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c index a41049e7b425..d3ed2134818a 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c @@ -148,30 +148,39 @@ int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *cmd_ring; int cmd_num; + if (!cb) { + dp_cmd = NULL; + } else { + /* Can this be optimized so that we keep the pending command list only + * for tid delete command to free up the resource on the command status + * indication? + */ + dp_cmd = kzalloc_obj(*dp_cmd, GFP_ATOMIC); + if (!dp_cmd) + return -ENOMEM; + + INIT_LIST_HEAD(&dp_cmd->list); + memcpy(&dp_cmd->data, rx_tid, sizeof(*rx_tid)); + } + cmd_ring = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id]; cmd_num = ath12k_wifi7_hal_reo_cmd_send(ab, cmd_ring, type, cmd); /* cmd_num should start from 1, during failure return the error code */ - if (cmd_num < 0) + if (cmd_num < 0) { + kfree(dp_cmd); return cmd_num; + } /* reo cmd ring descriptors has cmd_num starting from 1 */ - if (cmd_num == 0) + if (cmd_num == 0) { + kfree(dp_cmd); return -EINVAL; - - if (!cb) - return 0; - - /* Can this be optimized so that we keep the pending command list only - * for tid delete command to free up the resource on the command status - * indication? - */ - dp_cmd = kzalloc_obj(*dp_cmd, GFP_ATOMIC); + } if (!dp_cmd) - return -ENOMEM; + return 0; - memcpy(&dp_cmd->data, rx_tid, sizeof(*rx_tid)); dp_cmd->cmd_num = cmd_num; dp_cmd->handler = cb; -- 2.43.0