Unverified Commit a01c02df authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!14055 wifi: mac80211: use two-phase skb reclamation in ieee80211_do_stop()

parents dbdf30d2 4165a108
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -370,6 +370,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
{
	struct ieee80211_local *local = sdata->local;
	unsigned long flags;
	struct sk_buff_head freeq;
	struct sk_buff *skb, *tmp;
	u32 hw_reconf_flags = 0;
	int i, flushed;
@@ -565,18 +566,32 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
		skb_queue_purge(&sdata->skb_queue);
	}

	/*
	 * Since ieee80211_free_txskb() may issue __dev_queue_xmit()
	 * which should be called with interrupts enabled, reclamation
	 * is done in two phases:
	 */
	__skb_queue_head_init(&freeq);

	/* unlink from local queues... */
	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
		skb_queue_walk_safe(&local->pending[i], skb, tmp) {
			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
			if (info->control.vif == &sdata->vif) {
				__skb_unlink(skb, &local->pending[i]);
				ieee80211_free_txskb(&local->hw, skb);
				__skb_queue_tail(&freeq, skb);
			}
		}
	}
	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);

	/* ... and perform actual reclamation with interrupts enabled. */
	skb_queue_walk_safe(&freeq, skb, tmp) {
		__skb_unlink(skb, &freeq);
		ieee80211_free_txskb(&local->hw, skb);
	}

	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
		ieee80211_txq_remove_vlan(local, sdata);