aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c104
1 files changed, 94 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 6f36b6e79f5e..5df66382d922 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. 3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 * 4 *
5 * Portions of this file are derived from the ipw3945 project, as well 5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files. 6 * as portions of the ieee80211 subsystem header files.
@@ -473,8 +473,8 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
473 (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| 473 (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
474 (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); 474 (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
475 475
476 /* Set interrupt coalescing timer to 64 x 32 = 2048 usecs */ 476 /* Set interrupt coalescing timer to default (2048 usecs) */
477 iwl_write8(priv, CSR_INT_COALESCING, 0x40); 477 iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
478 478
479 return 0; 479 return 0;
480} 480}
@@ -499,9 +499,10 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
499 struct iwl_missed_beacon_notif *missed_beacon; 499 struct iwl_missed_beacon_notif *missed_beacon;
500 500
501 missed_beacon = &pkt->u.missed_beacon; 501 missed_beacon = &pkt->u.missed_beacon;
502 if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) { 502 if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
503 priv->missed_beacon_threshold) {
503 IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", 504 IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
504 le32_to_cpu(missed_beacon->consequtive_missed_beacons), 505 le32_to_cpu(missed_beacon->consecutive_missed_beacons),
505 le32_to_cpu(missed_beacon->total_missed_becons), 506 le32_to_cpu(missed_beacon->total_missed_becons),
506 le32_to_cpu(missed_beacon->num_recvd_beacons), 507 le32_to_cpu(missed_beacon->num_recvd_beacons),
507 le32_to_cpu(missed_beacon->num_expected_beacons)); 508 le32_to_cpu(missed_beacon->num_expected_beacons));
@@ -511,6 +512,24 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
511} 512}
512EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); 513EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
513 514
515void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
516 struct iwl_rx_mem_buffer *rxb)
517{
518 struct iwl_rx_packet *pkt = rxb_addr(rxb);
519 struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
520
521 if (!report->state) {
522 IWL_DEBUG_11H(priv,
523 "Spectrum Measure Notification: Start\n");
524 return;
525 }
526
527 memcpy(&priv->measure_report, report, sizeof(*report));
528 priv->measurement_status |= MEASUREMENT_READY;
529}
530EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
531
532
514 533
515/* Calculate noise level, based on measurements during network silence just 534/* Calculate noise level, based on measurements during network silence just
516 * before arriving beacon. This measurement can be done only if we know 535 * before arriving beacon. This measurement can be done only if we know
@@ -564,15 +583,24 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
564 int i; 583 int i;
565 __le32 *prev_stats; 584 __le32 *prev_stats;
566 u32 *accum_stats; 585 u32 *accum_stats;
586 u32 *delta, *max_delta;
567 587
568 prev_stats = (__le32 *)&priv->statistics; 588 prev_stats = (__le32 *)&priv->statistics;
569 accum_stats = (u32 *)&priv->accum_statistics; 589 accum_stats = (u32 *)&priv->accum_statistics;
590 delta = (u32 *)&priv->delta_statistics;
591 max_delta = (u32 *)&priv->max_delta;
570 592
571 for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); 593 for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
572 i += sizeof(__le32), stats++, prev_stats++, accum_stats++) 594 i += sizeof(__le32), stats++, prev_stats++, delta++,
573 if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) 595 max_delta++, accum_stats++) {
574 *accum_stats += (le32_to_cpu(*stats) - 596 if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
597 *delta = (le32_to_cpu(*stats) -
575 le32_to_cpu(*prev_stats)); 598 le32_to_cpu(*prev_stats));
599 *accum_stats += *delta;
600 if (*delta > *max_delta)
601 *max_delta = *delta;
602 }
603 }
576 604
577 /* reset accumulative statistics for "no-counter" type statistics */ 605 /* reset accumulative statistics for "no-counter" type statistics */
578 priv->accum_statistics.general.temperature = 606 priv->accum_statistics.general.temperature =
@@ -592,11 +620,15 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
592 620
593#define REG_RECALIB_PERIOD (60) 621#define REG_RECALIB_PERIOD (60)
594 622
623#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n"
595void iwl_rx_statistics(struct iwl_priv *priv, 624void iwl_rx_statistics(struct iwl_priv *priv,
596 struct iwl_rx_mem_buffer *rxb) 625 struct iwl_rx_mem_buffer *rxb)
597{ 626{
598 int change; 627 int change;
599 struct iwl_rx_packet *pkt = rxb_addr(rxb); 628 struct iwl_rx_packet *pkt = rxb_addr(rxb);
629 int combined_plcp_delta;
630 unsigned int plcp_msec;
631 unsigned long plcp_received_jiffies;
600 632
601 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", 633 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
602 (int)sizeof(priv->statistics), 634 (int)sizeof(priv->statistics),
@@ -611,6 +643,56 @@ void iwl_rx_statistics(struct iwl_priv *priv,
611#ifdef CONFIG_IWLWIFI_DEBUG 643#ifdef CONFIG_IWLWIFI_DEBUG
612 iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); 644 iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
613#endif 645#endif
646 /*
647 * check for plcp_err and trigger radio reset if it exceeds
648 * the plcp error threshold plcp_delta.
649 */
650 plcp_received_jiffies = jiffies;
651 plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
652 (long) priv->plcp_jiffies);
653 priv->plcp_jiffies = plcp_received_jiffies;
654 /*
655 * check to make sure plcp_msec is not 0 to prevent division
656 * by zero.
657 */
658 if (plcp_msec) {
659 combined_plcp_delta =
660 (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
661 le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
662 (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
663 le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
664
665 if ((combined_plcp_delta > 0) &&
666 ((combined_plcp_delta * 100) / plcp_msec) >
667 priv->cfg->plcp_delta_threshold) {
668 /*
669 * if plcp_err exceed the threshold, the following
670 * data is printed in csv format:
671 * Text: plcp_err exceeded %d,
672 * Received ofdm.plcp_err,
673 * Current ofdm.plcp_err,
674 * Received ofdm_ht.plcp_err,
675 * Current ofdm_ht.plcp_err,
676 * combined_plcp_delta,
677 * plcp_msec
678 */
679 IWL_DEBUG_RADIO(priv, PLCP_MSG,
680 priv->cfg->plcp_delta_threshold,
681 le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
682 le32_to_cpu(priv->statistics.rx.ofdm.plcp_err),
683 le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
684 le32_to_cpu(
685 priv->statistics.rx.ofdm_ht.plcp_err),
686 combined_plcp_delta, plcp_msec);
687
688 /*
689 * Reset the RF radio due to the high plcp
690 * error rate
691 */
692 iwl_force_rf_reset(priv);
693 }
694 }
695
614 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); 696 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
615 697
616 set_bit(STATUS_STATISTICS, &priv->status); 698 set_bit(STATUS_STATISTICS, &priv->status);
@@ -638,11 +720,13 @@ void iwl_reply_statistics(struct iwl_priv *priv,
638 struct iwl_rx_packet *pkt = rxb_addr(rxb); 720 struct iwl_rx_packet *pkt = rxb_addr(rxb);
639 721
640 if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { 722 if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
641 memset(&priv->statistics, 0,
642 sizeof(struct iwl_notif_statistics));
643#ifdef CONFIG_IWLWIFI_DEBUG 723#ifdef CONFIG_IWLWIFI_DEBUG
644 memset(&priv->accum_statistics, 0, 724 memset(&priv->accum_statistics, 0,
645 sizeof(struct iwl_notif_statistics)); 725 sizeof(struct iwl_notif_statistics));
726 memset(&priv->delta_statistics, 0,
727 sizeof(struct iwl_notif_statistics));
728 memset(&priv->max_delta, 0,
729 sizeof(struct iwl_notif_statistics));
646#endif 730#endif
647 IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); 731 IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
648 } 732 }