Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8e79ddd authored by Tomas Winkler's avatar Tomas Winkler Committed by John W. Linville
Browse files

mac80211: fix fragmentation kludge



This patch make mac80211 transmit correctly fragmented packet after
queue was stopped

Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent dc1968e7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -586,6 +586,7 @@ struct ieee80211_local {
	struct timer_list sta_cleanup;

	unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)];
	unsigned long queues_pending_run[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)];
	struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES];
	struct tasklet_struct tx_pending_tasklet;

+12 −5
Original line number Diff line number Diff line
@@ -1060,13 +1060,14 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
			  struct ieee80211_tx_data *tx)
{
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_tx_info *info;
	int ret, i;

	if (skb) {
		if (netif_subqueue_stopped(local->mdev, skb))
			return IEEE80211_TX_AGAIN;
		info =  IEEE80211_SKB_CB(skb);

	if (skb) {
		ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
				     "TX to low-level driver", skb);
		ret = local->ops->tx(local_to_hw(local), skb);
@@ -1215,6 +1216,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)

		if (ret == IEEE80211_TX_FRAG_AGAIN)
			skb = NULL;

		set_bit(queue, local->queues_pending);
		smp_mb();
		/*
@@ -1708,14 +1710,19 @@ void ieee80211_tx_pending(unsigned long data)
	netif_tx_lock_bh(dev);
	for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) {
		/* Check that this queue is ok */
		if (__netif_subqueue_stopped(local->mdev, i))
		if (__netif_subqueue_stopped(local->mdev, i) &&
		    !test_bit(i, local->queues_pending_run))
			continue;

		if (!test_bit(i, local->queues_pending)) {
			clear_bit(i, local->queues_pending_run);
			ieee80211_wake_queue(&local->hw, i);
			continue;
		}

		clear_bit(i, local->queues_pending_run);
		netif_start_subqueue(local->mdev, i);

		store = &local->pending_packet[i];
		tx.extra_frag = store->extra_frag;
		tx.num_extra_frag = store->num_extra_frag;
+1 −0
Original line number Diff line number Diff line
@@ -361,6 +361,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
	struct ieee80211_local *local = hw_to_local(hw);

	if (test_bit(queue, local->queues_pending)) {
		set_bit(queue, local->queues_pending_run);
		tasklet_schedule(&local->tx_pending_tasklet);
	} else {
		netif_wake_subqueue(local->mdev, queue);