aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h7
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h26
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c38
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c50
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h10
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c2
11 files changed, 159 insertions, 3 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 0b7888d43f37..009323e6c20f 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1736,6 +1736,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
1736 __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); 1736 __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
1737 __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); 1737 __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
1738 } 1738 }
1739 __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
1739 1740
1740 /* 1741 /*
1741 * Set the rssi offset. 1742 * Set the rssi offset.
@@ -1772,6 +1773,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
1772 .rfkill_poll = rt2500usb_rfkill_poll, 1773 .rfkill_poll = rt2500usb_rfkill_poll,
1773 .link_stats = rt2500usb_link_stats, 1774 .link_stats = rt2500usb_link_stats,
1774 .reset_tuner = rt2500usb_reset_tuner, 1775 .reset_tuner = rt2500usb_reset_tuner,
1776 .watchdog = rt2x00usb_watchdog,
1775 .write_tx_desc = rt2500usb_write_tx_desc, 1777 .write_tx_desc = rt2500usb_write_tx_desc,
1776 .write_beacon = rt2500usb_write_beacon, 1778 .write_beacon = rt2500usb_write_beacon,
1777 .get_tx_data_len = rt2500usb_get_tx_data_len, 1779 .get_tx_data_len = rt2500usb_get_tx_data_len,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index e4ab4db66ca0..5aa7563155cd 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -633,6 +633,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
633 if (!modparam_nohwcrypt) 633 if (!modparam_nohwcrypt)
634 __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); 634 __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
635 __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); 635 __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
636 __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
636 637
637 /* 638 /*
638 * Set the rssi offset. 639 * Set the rssi offset.
@@ -655,6 +656,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
655 .link_stats = rt2800_link_stats, 656 .link_stats = rt2800_link_stats,
656 .reset_tuner = rt2800_reset_tuner, 657 .reset_tuner = rt2800_reset_tuner,
657 .link_tuner = rt2800_link_tuner, 658 .link_tuner = rt2800_link_tuner,
659 .watchdog = rt2x00usb_watchdog,
658 .write_tx_desc = rt2800usb_write_tx_desc, 660 .write_tx_desc = rt2800usb_write_tx_desc,
659 .write_tx_data = rt2800usb_write_tx_data, 661 .write_tx_data = rt2800usb_write_tx_data,
660 .write_beacon = rt2800_write_beacon, 662 .write_beacon = rt2800_write_beacon,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index bf5e3f37e705..97b6261fee4f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -332,6 +332,11 @@ struct link {
332 * Work structure for scheduling periodic link tuning. 332 * Work structure for scheduling periodic link tuning.
333 */ 333 */
334 struct delayed_work work; 334 struct delayed_work work;
335
336 /*
337 * Work structure for scheduling periodic watchdog monitoring.
338 */
339 struct delayed_work watchdog_work;
335}; 340};
336 341
337/* 342/*
@@ -543,6 +548,7 @@ struct rt2x00lib_ops {
543 struct link_qual *qual); 548 struct link_qual *qual);
544 void (*link_tuner) (struct rt2x00_dev *rt2x00dev, 549 void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
545 struct link_qual *qual, const u32 count); 550 struct link_qual *qual, const u32 count);
551 void (*watchdog) (struct rt2x00_dev *rt2x00dev);
546 552
547 /* 553 /*
548 * TX control handlers 554 * TX control handlers
@@ -648,6 +654,7 @@ enum rt2x00_flags {
648 DRIVER_SUPPORT_CONTROL_FILTERS, 654 DRIVER_SUPPORT_CONTROL_FILTERS,
649 DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, 655 DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
650 DRIVER_SUPPORT_LINK_TUNING, 656 DRIVER_SUPPORT_LINK_TUNING,
657 DRIVER_SUPPORT_WATCHDOG,
651 658
652 /* 659 /*
653 * Driver configuration 660 * Driver configuration
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 12ee7bdedd02..0906e14b347f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -70,6 +70,11 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
70 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); 70 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
71 71
72 /* 72 /*
73 * Start watchdog monitoring.
74 */
75 rt2x00link_start_watchdog(rt2x00dev);
76
77 /*
73 * Start the TX queues. 78 * Start the TX queues.
74 */ 79 */
75 ieee80211_wake_queues(rt2x00dev->hw); 80 ieee80211_wake_queues(rt2x00dev->hw);
@@ -89,6 +94,11 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
89 rt2x00queue_stop_queues(rt2x00dev); 94 rt2x00queue_stop_queues(rt2x00dev);
90 95
91 /* 96 /*
97 * Stop watchdog monitoring.
98 */
99 rt2x00link_stop_watchdog(rt2x00dev);
100
101 /*
92 * Disable RX. 102 * Disable RX.
93 */ 103 */
94 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); 104 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index ed27de1de57b..dc5c6574aaf4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -30,6 +30,7 @@
30/* 30/*
31 * Interval defines 31 * Interval defines
32 */ 32 */
33#define WATCHDOG_INTERVAL round_jiffies_relative(HZ)
33#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) 34#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ)
34 35
35/* 36/*
@@ -257,11 +258,30 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev);
257void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna); 258void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna);
258 259
259/** 260/**
260 * rt2x00link_register - Initialize link tuning functionality 261 * rt2x00link_start_watchdog - Start periodic watchdog monitoring
261 * @rt2x00dev: Pointer to &struct rt2x00_dev. 262 * @rt2x00dev: Pointer to &struct rt2x00_dev.
262 * 263 *
263 * Initialize work structure and all link tuning related 264 * This start the watchdog periodic work, this work will
264 * parameters. This will not start the link tuning process itself. 265 *be executed periodically until &rt2x00link_stop_watchdog has
266 * been called.
267 */
268void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev);
269
270/**
271 * rt2x00link_stop_watchdog - Stop periodic watchdog monitoring
272 * @rt2x00dev: Pointer to &struct rt2x00_dev.
273 *
274 * After this function completed the watchdog monitoring will not
275 * be running until &rt2x00link_start_watchdog is called.
276 */
277void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev);
278
279/**
280 * rt2x00link_register - Initialize link tuning & watchdog functionality
281 * @rt2x00dev: Pointer to &struct rt2x00_dev.
282 *
283 * Initialize work structure and all link tuning and watchdog related
284 * parameters. This will not start the periodic work itself.
265 */ 285 */
266void rt2x00link_register(struct rt2x00_dev *rt2x00dev); 286void rt2x00link_register(struct rt2x00_dev *rt2x00dev);
267 287
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 9acfc5c70389..666cef3f8472 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -407,7 +407,45 @@ static void rt2x00link_tuner(struct work_struct *work)
407 &link->work, LINK_TUNE_INTERVAL); 407 &link->work, LINK_TUNE_INTERVAL);
408} 408}
409 409
410void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
411{
412 struct link *link = &rt2x00dev->link;
413
414 if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
415 !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
416 return;
417
418 ieee80211_queue_delayed_work(rt2x00dev->hw,
419 &link->watchdog_work, WATCHDOG_INTERVAL);
420}
421
422void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
423{
424 cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work);
425}
426
427static void rt2x00link_watchdog(struct work_struct *work)
428{
429 struct rt2x00_dev *rt2x00dev =
430 container_of(work, struct rt2x00_dev, link.watchdog_work.work);
431 struct link *link = &rt2x00dev->link;
432
433 /*
434 * When the radio is shutting down we should
435 * immediately cease the watchdog monitoring.
436 */
437 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
438 return;
439
440 rt2x00dev->ops->lib->watchdog(rt2x00dev);
441
442 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
443 ieee80211_queue_delayed_work(rt2x00dev->hw,
444 &link->watchdog_work, WATCHDOG_INTERVAL);
445}
446
410void rt2x00link_register(struct rt2x00_dev *rt2x00dev) 447void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
411{ 448{
449 INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
412 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); 450 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
413} 451}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 5097fe0f9f51..a3401d301058 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -688,9 +688,11 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
688 688
689 if (index == Q_INDEX) { 689 if (index == Q_INDEX) {
690 queue->length++; 690 queue->length++;
691 queue->last_index = jiffies;
691 } else if (index == Q_INDEX_DONE) { 692 } else if (index == Q_INDEX_DONE) {
692 queue->length--; 693 queue->length--;
693 queue->count++; 694 queue->count++;
695 queue->last_index_done = jiffies;
694 } 696 }
695 697
696 spin_unlock_irqrestore(&queue->lock, irqflags); 698 spin_unlock_irqrestore(&queue->lock, irqflags);
@@ -704,6 +706,8 @@ static void rt2x00queue_reset(struct data_queue *queue)
704 706
705 queue->count = 0; 707 queue->count = 0;
706 queue->length = 0; 708 queue->length = 0;
709 queue->last_index = jiffies;
710 queue->last_index_done = jiffies;
707 memset(queue->index, 0, sizeof(queue->index)); 711 memset(queue->index, 0, sizeof(queue->index));
708 712
709 spin_unlock_irqrestore(&queue->lock, irqflags); 713 spin_unlock_irqrestore(&queue->lock, irqflags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index bd54f55a8cb9..191e7775a9c0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -446,6 +446,8 @@ struct data_queue {
446 enum data_queue_qid qid; 446 enum data_queue_qid qid;
447 447
448 spinlock_t lock; 448 spinlock_t lock;
449 unsigned long last_index;
450 unsigned long last_index_done;
449 unsigned int count; 451 unsigned int count;
450 unsigned short limit; 452 unsigned short limit;
451 unsigned short threshold; 453 unsigned short threshold;
@@ -599,6 +601,15 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)
599} 601}
600 602
601/** 603/**
604 * rt2x00queue_timeout - Check if a timeout occured for this queue
605 * @queue: Queue to check.
606 */
607static inline int rt2x00queue_timeout(struct data_queue *queue)
608{
609 return time_after(queue->last_index, queue->last_index_done + (HZ / 10));
610}
611
612/**
602 * _rt2x00_desc_read - Read a word from the hardware descriptor. 613 * _rt2x00_desc_read - Read a word from the hardware descriptor.
603 * @desc: Base descriptor address 614 * @desc: Base descriptor address
604 * @word: Word index from where the descriptor should be read. 615 * @word: Word index from where the descriptor should be read.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index a22837c560fd..ff3a36622d1b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -292,6 +292,56 @@ void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
292} 292}
293EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); 293EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);
294 294
295static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
296{
297 struct queue_entry_priv_usb *entry_priv;
298 unsigned short threshold = queue->threshold;
299
300 WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid);
301
302 /*
303 * Temporarily disable the TX queue, this will force mac80211
304 * to use the other queues until this queue has been restored.
305 *
306 * Set the queue threshold to the queue limit. This prevents the
307 * queue from being enabled during the txdone handler.
308 */
309 queue->threshold = queue->limit;
310 ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
311
312 /*
313 * Reset all currently uploaded TX frames.
314 */
315 while (!rt2x00queue_empty(queue)) {
316 entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data;
317 usb_kill_urb(entry_priv->urb);
318
319 /*
320 * We need a short delay here to wait for
321 * the URB to be canceled and invoked the tx_done handler.
322 */
323 udelay(200);
324 }
325
326 /*
327 * The queue has been reset, and mac80211 is allowed to use the
328 * queue again.
329 */
330 queue->threshold = threshold;
331 ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
332}
333
334void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
335{
336 struct data_queue *queue;
337
338 tx_queue_for_each(rt2x00dev, queue) {
339 if (rt2x00queue_timeout(queue))
340 rt2x00usb_watchdog_reset_tx(queue);
341 }
342}
343EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
344
295/* 345/*
296 * RX data handlers. 346 * RX data handlers.
297 */ 347 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 2b7a1889e72f..d3d3ddc40875 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -399,6 +399,16 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
399void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, 399void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
400 const enum data_queue_qid qid); 400 const enum data_queue_qid qid);
401 401
402/**
403 * rt2x00usb_watchdog - Watchdog for USB communication
404 * @rt2x00dev: Pointer to &struct rt2x00_dev
405 *
406 * Check the health of the USB communication and determine
407 * if timeouts have occured. If this is the case, this function
408 * will reset all communication to restore functionality again.
409 */
410void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev);
411
402/* 412/*
403 * Device initialization handlers. 413 * Device initialization handlers.
404 */ 414 */
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 9ea6a672d4e2..cad07b69c53e 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2136,6 +2136,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
2136 if (!modparam_nohwcrypt) 2136 if (!modparam_nohwcrypt)
2137 __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); 2137 __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
2138 __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); 2138 __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
2139 __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
2139 2140
2140 /* 2141 /*
2141 * Set the rssi offset. 2142 * Set the rssi offset.
@@ -2251,6 +2252,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
2251 .link_stats = rt73usb_link_stats, 2252 .link_stats = rt73usb_link_stats,
2252 .reset_tuner = rt73usb_reset_tuner, 2253 .reset_tuner = rt73usb_reset_tuner,
2253 .link_tuner = rt73usb_link_tuner, 2254 .link_tuner = rt73usb_link_tuner,
2255 .watchdog = rt2x00usb_watchdog,
2254 .write_tx_desc = rt73usb_write_tx_desc, 2256 .write_tx_desc = rt73usb_write_tx_desc,
2255 .write_beacon = rt73usb_write_beacon, 2257 .write_beacon = rt73usb_write_beacon,
2256 .get_tx_data_len = rt73usb_get_tx_data_len, 2258 .get_tx_data_len = rt73usb_get_tx_data_len,