From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55850C5AE4B for ; Wed, 15 Nov 2023 20:57:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344695AbjKOU5n (ORCPT ); Wed, 15 Nov 2023 15:57:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34446 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344585AbjKOU53 (ORCPT ); Wed, 15 Nov 2023 15:57:29 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 766A9D5C for ; Wed, 15 Nov 2023 12:57:22 -0800 (PST) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3B532C433BF; Wed, 15 Nov 2023 20:47:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1700081259; bh=7wCiLi4PKoFnQZI9JnO05FZtnnXkk3FLYHb+j5H3XCc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c94ntgtML5gz9RH2h62ZxkP4Nqdzjwi6AGNs8eaEAo8jqb8ZVsGvt221iA6dKycJ4 Syt6h+DDb615SCp6Meifqzaj/pX+Yn/+sbLZq0+nhRKF4UuCtXh10VQvZ8pO0ojElR +Stv11JtriHKfodG+5Qsjs6jzCQCywUkqL5joR+4= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Miri Korenblit , Gregory Greenman , Johannes Berg , Sasha Levin Subject: [PATCH 5.15 046/244] wifi: iwlwifi: empty overflow queue during flush Date: Wed, 15 Nov 2023 15:33:58 -0500 Message-ID: <20231115203551.129959401@linuxfoundation.org> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20231115203548.387164783@linuxfoundation.org> References: <20231115203548.387164783@linuxfoundation.org> User-Agent: quilt/0.67 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org 5.15-stable review patch. If anyone has any objections, please let me know. ------------------ From: Miri Korenblit [ Upstream commit 658939fc68d3241f9a0019e224cd7154438c23f2 ] If a TX queue has no space for new TX frames, the driver will keep these frames in the overflow queue, and during reclaim flow it will retry to send the frames from that queue. But if the reclaim flow was invoked from TX queue flush, we will also TX these frames, which is wrong as we don't want to TX anything after flush. This might also cause assert 0x125F when removing the queue, saying that the driver removes a non-empty queue Fix this by TXing the overflow queue's frames only if we are not in flush queue flow. Fixes: a44509805895 ("iwlwifi: move reclaim flows to the queue file") Signed-off-by: Miri Korenblit Signed-off-by: Gregory Greenman Link: https://lore.kernel.org/r/20231022173519.caf06c8709d9.Ibf664ccb3f952e836f8fa461ea58fc08e5c46e88@changeid Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 5 +++-- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 7 ++++--- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 4 ++-- drivers/net/wireless/intel/iwlwifi/queue/tx.c | 9 +++++---- drivers/net/wireless/intel/iwlwifi/queue/tx.h | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) --- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c @@ -3,6 +3,7 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2019 Intel Corporation + * Copyright (C) 2023 Intel Corporation * * Contact Information: * Intel Linux Wireless @@ -1174,7 +1175,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv iwlagn_check_ratid_empty(priv, sta_id, tid); } - iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); + iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs, false); freed = 0; @@ -1320,7 +1321,7 @@ void iwlagn_rx_reply_compressed_ba(struc * block-ack window (we assume that they've been successfully * transmitted ... if not, it's too late anyway). */ iwl_trans_reclaim(priv->trans, scd_flow, ba_resp_scd_ssn, - &reclaimed_skbs); + &reclaimed_skbs, false); IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " "sta_id = %d\n", --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -539,7 +539,7 @@ struct iwl_trans_ops { int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_device_tx_cmd *dev_cmd, int queue); void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, - struct sk_buff_head *skbs); + struct sk_buff_head *skbs, bool is_flush); void (*set_q_ptrs)(struct iwl_trans *trans, int queue, int ptr); @@ -1122,14 +1122,15 @@ static inline int iwl_trans_tx(struct iw } static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, - int ssn, struct sk_buff_head *skbs) + int ssn, struct sk_buff_head *skbs, + bool is_flush) { if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) { IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); return; } - trans->ops->reclaim(trans, queue, ssn, skbs); + trans->ops->reclaim(trans, queue, ssn, skbs, is_flush); } static inline void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue, --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1436,7 +1436,7 @@ static void iwl_mvm_rx_tx_cmd_single(str seq_ctl = le16_to_cpu(tx_resp->seq_ctl); /* we can free until ssn % q.n_bd not inclusive */ - iwl_trans_reclaim(mvm->trans, txq_id, ssn, &skbs); + iwl_trans_reclaim(mvm->trans, txq_id, ssn, &skbs, false); while (!skb_queue_empty(&skbs)) { struct sk_buff *skb = __skb_dequeue(&skbs); @@ -1781,7 +1781,7 @@ static void iwl_mvm_tx_reclaim(struct iw * block-ack window (we assume that they've been successfully * transmitted ... if not, it's too late anyway). */ - iwl_trans_reclaim(mvm->trans, txq, index, &reclaimed_skbs); + iwl_trans_reclaim(mvm->trans, txq, index, &reclaimed_skbs, is_flush); skb_queue_walk(&reclaimed_skbs, skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c @@ -1520,7 +1520,7 @@ void iwl_txq_progress(struct iwl_txq *tx /* Frees buffers until index _not_ inclusive */ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn, - struct sk_buff_head *skbs) + struct sk_buff_head *skbs, bool is_flush) { struct iwl_txq *txq = trans->txqs.txq[txq_id]; int tfd_num = iwl_txq_get_cmd_index(txq, ssn); @@ -1591,9 +1591,11 @@ void iwl_txq_reclaim(struct iwl_trans *t if (iwl_txq_space(trans, txq) > txq->low_mark && test_bit(txq_id, trans->txqs.queue_stopped)) { struct sk_buff_head overflow_skbs; + struct sk_buff *skb; __skb_queue_head_init(&overflow_skbs); - skb_queue_splice_init(&txq->overflow_q, &overflow_skbs); + skb_queue_splice_init(&txq->overflow_q, + is_flush ? skbs : &overflow_skbs); /* * We are going to transmit from the overflow queue. @@ -1613,8 +1615,7 @@ void iwl_txq_reclaim(struct iwl_trans *t */ spin_unlock_bh(&txq->lock); - while (!skb_queue_empty(&overflow_skbs)) { - struct sk_buff *skb = __skb_dequeue(&overflow_skbs); + while ((skb = __skb_dequeue(&overflow_skbs))) { struct iwl_device_tx_cmd *dev_cmd_ptr; dev_cmd_ptr = *(void **)((u8 *)skb->cb + --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h @@ -174,7 +174,7 @@ void iwl_txq_gen1_update_byte_cnt_tbl(st struct iwl_txq *txq, u16 byte_cnt, int num_tbs); void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn, - struct sk_buff_head *skbs); + struct sk_buff_head *skbs, bool is_flush); void iwl_txq_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr); void iwl_trans_txq_freeze_timer(struct iwl_trans *trans, unsigned long txqs, bool freeze);