rt2x00: rt2800usb: rework txstatus code

Currently we read tx status register after each urb data transfer. As
callback procedure also trigger reading, that causing we have many
"threads" of reading status. To prevent that introduce TX_STATUS_READING
flags, and check if we are already in process of sequential reading
TX_STA_FIFO, before requesting new reads.

Change timer to hrtimer, that make TX_STA_FIFO overruns less possible.
Use 200 us for initial timeout, and then reschedule in 100 us period,
this values probably have to be tuned.

Make changes on txdone work. Schedule it from
rt2800usb_tx_sta_fifo_read_completed() callback when first valid status
show up. Check in callback if tx status timeout happens, and schedule
work on that condition too. That make possible to remove tx status
timeout from generic watchdog. I moved that to rt2800usb.

Loop in txdone work, that should prevent situation when we queue work,
which is already processed, and after finish work is not rescheduled
again.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 2eea386..66094eb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -526,22 +526,6 @@
 	rt2x00queue_flush_queue(queue, true);
 }
 
-static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
-{
-	WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
-		" invoke forced tx handler\n", queue->qid);
-
-	queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);
-}
-
-static int rt2x00usb_status_timeout(struct data_queue *queue)
-{
-	struct queue_entry *entry;
-
-	entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-	return rt2x00queue_status_timeout(entry);
-}
-
 static int rt2x00usb_dma_timeout(struct data_queue *queue)
 {
 	struct queue_entry *entry;
@@ -558,8 +542,6 @@
 		if (!rt2x00queue_empty(queue)) {
 			if (rt2x00usb_dma_timeout(queue))
 				rt2x00usb_watchdog_tx_dma(queue);
-			if (rt2x00usb_status_timeout(queue))
-				rt2x00usb_watchdog_tx_status(queue);
 		}
 	}
 }
@@ -829,7 +811,8 @@
 
 	INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
 	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
-	init_timer(&rt2x00dev->txstatus_timer);
+	hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
 
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)