aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/p54/main.c')
-rw-r--r--drivers/net/wireless/p54/main.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 622d27b6d8f..e14a05bbc48 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -524,6 +524,48 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx,
524 return 0; 524 return 0;
525} 525}
526 526
527static unsigned int p54_flush_count(struct p54_common *priv)
528{
529 unsigned int total = 0, i;
530
531 BUILD_BUG_ON(P54_QUEUE_NUM > ARRAY_SIZE(priv->tx_stats));
532
533 /*
534 * Because the firmware has the sole control over any frames
535 * in the P54_QUEUE_BEACON or P54_QUEUE_SCAN queues, they
536 * don't really count as pending or active.
537 */
538 for (i = P54_QUEUE_MGMT; i < P54_QUEUE_NUM; i++)
539 total += priv->tx_stats[i].len;
540 return total;
541}
542
543static void p54_flush(struct ieee80211_hw *dev, bool drop)
544{
545 struct p54_common *priv = dev->priv;
546 unsigned int total, i;
547
548 /*
549 * Currently, it wouldn't really matter if we wait for one second
550 * or 15 minutes. But once someone gets around and completes the
551 * TODOs [ancel stuck frames / reset device] in p54_work, it will
552 * suddenly make sense to wait that long.
553 */
554 i = P54_STATISTICS_UPDATE * 2 / 20;
555
556 /*
557 * In this case no locking is required because as we speak the
558 * queues have already been stopped and no new frames can sneak
559 * up from behind.
560 */
561 while ((total = p54_flush_count(priv) && i--)) {
562 /* waste time */
563 msleep(20);
564 }
565
566 WARN(total, "tx flush timeout, unresponsive firmware");
567}
568
527static const struct ieee80211_ops p54_ops = { 569static const struct ieee80211_ops p54_ops = {
528 .tx = p54_tx_80211, 570 .tx = p54_tx_80211,
529 .start = p54_start, 571 .start = p54_start,
@@ -536,6 +578,7 @@ static const struct ieee80211_ops p54_ops = {
536 .sta_remove = p54_sta_add_remove, 578 .sta_remove = p54_sta_add_remove,
537 .set_key = p54_set_key, 579 .set_key = p54_set_key,
538 .config = p54_config, 580 .config = p54_config,
581 .flush = p54_flush,
539 .bss_info_changed = p54_bss_info_changed, 582 .bss_info_changed = p54_bss_info_changed,
540 .configure_filter = p54_configure_filter, 583 .configure_filter = p54_configure_filter,
541 .conf_tx = p54_conf_tx, 584 .conf_tx = p54_conf_tx,
@@ -611,7 +654,7 @@ EXPORT_SYMBOL_GPL(p54_init_common);
611 654
612int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) 655int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)
613{ 656{
614 struct p54_common *priv = dev->priv; 657 struct p54_common __maybe_unused *priv = dev->priv;
615 int err; 658 int err;
616 659
617 err = ieee80211_register_hw(dev); 660 err = ieee80211_register_hw(dev);
@@ -642,10 +685,12 @@ void p54_free_common(struct ieee80211_hw *dev)
642 kfree(priv->iq_autocal); 685 kfree(priv->iq_autocal);
643 kfree(priv->output_limit); 686 kfree(priv->output_limit);
644 kfree(priv->curve_data); 687 kfree(priv->curve_data);
688 kfree(priv->rssi_db);
645 kfree(priv->used_rxkeys); 689 kfree(priv->used_rxkeys);
646 priv->iq_autocal = NULL; 690 priv->iq_autocal = NULL;
647 priv->output_limit = NULL; 691 priv->output_limit = NULL;
648 priv->curve_data = NULL; 692 priv->curve_data = NULL;
693 priv->rssi_db = NULL;
649 priv->used_rxkeys = NULL; 694 priv->used_rxkeys = NULL;
650 ieee80211_free_hw(dev); 695 ieee80211_free_hw(dev);
651} 696}