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

Commit 0439f536 authored by Ivo van Doorn's avatar Ivo van Doorn Committed by John W. Linville
Browse files

rt2x00: Move TX/RX work into dedicated workqueue



The TX/RX work structures must be able to run independently
of other workqueues. This is because mac80211 might use
the flush() callback function from various context, which depends
on the TX/RX work to complete while the main thread is blocked
(until the the TX queues are empty).

This should reduce the number of  'Queue %d failed to flush' warnings.

Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Acked-by: default avatarGertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e1f4e808
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -860,6 +860,13 @@ struct rt2x00_dev {
	 */
	 */
	struct ieee80211_low_level_stats low_level_stats;
	struct ieee80211_low_level_stats low_level_stats;


	/**
	 * Work queue for all work which should not be placed
	 * on the mac80211 workqueue (because of dependencies
	 * between various work structures).
	 */
	struct workqueue_struct *workqueue;

	/*
	/*
	 * Scheduled work.
	 * Scheduled work.
	 * NOTE: intf_work will use ieee80211_iterate_active_interfaces()
	 * NOTE: intf_work will use ieee80211_iterate_active_interfaces()
+9 −1
Original line number Original line Diff line number Diff line
@@ -997,8 +997,15 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
		    BIT(NL80211_IFTYPE_WDS);
		    BIT(NL80211_IFTYPE_WDS);


	/*
	/*
	 * Initialize configuration work.
	 * Initialize work.
	 */
	 */
	rt2x00dev->workqueue =
	    alloc_ordered_workqueue(wiphy_name(rt2x00dev->hw->wiphy), 0);
	if (!rt2x00dev->workqueue) {
		retval = -ENOMEM;
		goto exit;
	}

	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);


	/*
	/*
@@ -1057,6 +1064,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
	cancel_work_sync(&rt2x00dev->intf_work);
	cancel_work_sync(&rt2x00dev->intf_work);
	cancel_work_sync(&rt2x00dev->rxdone_work);
	cancel_work_sync(&rt2x00dev->rxdone_work);
	cancel_work_sync(&rt2x00dev->txdone_work);
	cancel_work_sync(&rt2x00dev->txdone_work);
	destroy_workqueue(rt2x00dev->workqueue);


	/*
	/*
	 * Free the tx status fifo.
	 * Free the tx status fifo.
+5 −2
Original line number Original line Diff line number Diff line
@@ -417,7 +417,8 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
	    !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
	    !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
		return;
		return;


	schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
	ieee80211_queue_delayed_work(rt2x00dev->hw,
				     &link->watchdog_work, WATCHDOG_INTERVAL);
}
}


void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -441,7 +442,9 @@ static void rt2x00link_watchdog(struct work_struct *work)
	rt2x00dev->ops->lib->watchdog(rt2x00dev);
	rt2x00dev->ops->lib->watchdog(rt2x00dev);


	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
		schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
		ieee80211_queue_delayed_work(rt2x00dev->hw,
					     &link->watchdog_work,
					     WATCHDOG_INTERVAL);
}
}


void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
+4 −4
Original line number Original line Diff line number Diff line
@@ -227,7 +227,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
	 * Schedule the delayed work for reading the TX status
	 * Schedule the delayed work for reading the TX status
	 * from the device.
	 * from the device.
	 */
	 */
	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
	queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
}
}


static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
@@ -320,7 +320,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
	 * Schedule the delayed work for reading the RX status
	 * Schedule the delayed work for reading the RX status
	 * from the device.
	 * from the device.
	 */
	 */
	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
	queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
}
}


static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
@@ -429,7 +429,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue)
		 * Schedule the completion handler manually, when this
		 * Schedule the completion handler manually, when this
		 * worker function runs, it should cleanup the queue.
		 * worker function runs, it should cleanup the queue.
		 */
		 */
		ieee80211_queue_work(queue->rt2x00dev->hw, completion);
		queue_work(queue->rt2x00dev->workqueue, completion);


		/*
		/*
		 * Wait for a little while to give the driver
		 * Wait for a little while to give the driver
@@ -453,7 +453,7 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
	WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
	WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
		" invoke forced tx handler\n", queue->qid);
		" invoke forced tx handler\n", queue->qid);


	ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
	queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);
}
}


void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)