Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
Loading...
Note: File does not exist in v5.14.15.
  1/******************************************************************************
  2 *
  3 * GPL LICENSE SUMMARY
  4 *
  5 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of version 2 of the GNU General Public License as
  9 * published by the Free Software Foundation.
 10 *
 11 * This program is distributed in the hope that it will be useful, but
 12 * WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14 * General Public License for more details.
 15 *
 16 * You should have received a copy of the GNU General Public License
 17 * along with this program; if not, write to the Free Software
 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
 19 * USA
 20 *
 21 * The full GNU General Public License is included in this distribution
 22 * in the file called LICENSE.GPL.
 23 *
 24 * Contact Information:
 25 *  Intel Linux Wireless <ilw@linux.intel.com>
 26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 27 *
 28 *****************************************************************************/
 29
 30#include <linux/kernel.h>
 31#include <linux/module.h>
 32#include <linux/init.h>
 33#include <linux/sched.h>
 34
 35#include "iwl-dev.h"
 36#include "iwl-core.h"
 37#include "iwl-4965-calib.h"
 38#include "iwl-sta.h"
 39#include "iwl-io.h"
 40#include "iwl-helpers.h"
 41#include "iwl-4965-hw.h"
 42#include "iwl-4965.h"
 43
 44void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
 45				struct iwl_rx_mem_buffer *rxb)
 46
 47{
 48	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 49	struct iwl_missed_beacon_notif *missed_beacon;
 50
 51	missed_beacon = &pkt->u.missed_beacon;
 52	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
 53	    priv->missed_beacon_threshold) {
 54		IWL_DEBUG_CALIB(priv,
 55		    "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
 56		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
 57		    le32_to_cpu(missed_beacon->total_missed_becons),
 58		    le32_to_cpu(missed_beacon->num_recvd_beacons),
 59		    le32_to_cpu(missed_beacon->num_expected_beacons));
 60		if (!test_bit(STATUS_SCANNING, &priv->status))
 61			iwl4965_init_sensitivity(priv);
 62	}
 63}
 64
 65/* Calculate noise level, based on measurements during network silence just
 66 *   before arriving beacon.  This measurement can be done only if we know
 67 *   exactly when to expect beacons, therefore only when we're associated. */
 68static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
 69{
 70	struct statistics_rx_non_phy *rx_info;
 71	int num_active_rx = 0;
 72	int total_silence = 0;
 73	int bcn_silence_a, bcn_silence_b, bcn_silence_c;
 74	int last_rx_noise;
 75
 76	rx_info = &(priv->_4965.statistics.rx.general);
 77	bcn_silence_a =
 78		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
 79	bcn_silence_b =
 80		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
 81	bcn_silence_c =
 82		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
 83
 84	if (bcn_silence_a) {
 85		total_silence += bcn_silence_a;
 86		num_active_rx++;
 87	}
 88	if (bcn_silence_b) {
 89		total_silence += bcn_silence_b;
 90		num_active_rx++;
 91	}
 92	if (bcn_silence_c) {
 93		total_silence += bcn_silence_c;
 94		num_active_rx++;
 95	}
 96
 97	/* Average among active antennas */
 98	if (num_active_rx)
 99		last_rx_noise = (total_silence / num_active_rx) - 107;
100	else
101		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
102
103	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
104			bcn_silence_a, bcn_silence_b, bcn_silence_c,
105			last_rx_noise);
106}
107
108#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
109/*
110 *  based on the assumption of all statistics counter are in DWORD
111 *  FIXME: This function is for debugging, do not deal with
112 *  the case of counters roll-over.
113 */
114static void iwl4965_accumulative_statistics(struct iwl_priv *priv,
115					__le32 *stats)
116{
117	int i, size;
118	__le32 *prev_stats;
119	u32 *accum_stats;
120	u32 *delta, *max_delta;
121	struct statistics_general_common *general, *accum_general;
122	struct statistics_tx *tx, *accum_tx;
123
124	prev_stats = (__le32 *)&priv->_4965.statistics;
125	accum_stats = (u32 *)&priv->_4965.accum_statistics;
126	size = sizeof(struct iwl_notif_statistics);
127	general = &priv->_4965.statistics.general.common;
128	accum_general = &priv->_4965.accum_statistics.general.common;
129	tx = &priv->_4965.statistics.tx;
130	accum_tx = &priv->_4965.accum_statistics.tx;
131	delta = (u32 *)&priv->_4965.delta_statistics;
132	max_delta = (u32 *)&priv->_4965.max_delta;
133
134	for (i = sizeof(__le32); i < size;
135	     i += sizeof(__le32), stats++, prev_stats++, delta++,
136	     max_delta++, accum_stats++) {
137		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
138			*delta = (le32_to_cpu(*stats) -
139				le32_to_cpu(*prev_stats));
140			*accum_stats += *delta;
141			if (*delta > *max_delta)
142				*max_delta = *delta;
143		}
144	}
145
146	/* reset accumulative statistics for "no-counter" type statistics */
147	accum_general->temperature = general->temperature;
148	accum_general->ttl_timestamp = general->ttl_timestamp;
149}
150#endif
151
152#define REG_RECALIB_PERIOD (60)
153
154void iwl4965_rx_statistics(struct iwl_priv *priv,
155			      struct iwl_rx_mem_buffer *rxb)
156{
157	int change;
158	struct iwl_rx_packet *pkt = rxb_addr(rxb);
159
160	IWL_DEBUG_RX(priv,
161		     "Statistics notification received (%d vs %d).\n",
162		     (int)sizeof(struct iwl_notif_statistics),
163		     le32_to_cpu(pkt->len_n_flags) &
164		     FH_RSCSR_FRAME_SIZE_MSK);
165
166	change = ((priv->_4965.statistics.general.common.temperature !=
167		   pkt->u.stats.general.common.temperature) ||
168		   ((priv->_4965.statistics.flag &
169		   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
170		   (pkt->u.stats.flag &
171		   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
172#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
173	iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
174#endif
175
176	/* TODO: reading some of statistics is unneeded */
177	memcpy(&priv->_4965.statistics, &pkt->u.stats,
178		sizeof(priv->_4965.statistics));
179
180	set_bit(STATUS_STATISTICS, &priv->status);
181
182	/* Reschedule the statistics timer to occur in
183	 * REG_RECALIB_PERIOD seconds to ensure we get a
184	 * thermal update even if the uCode doesn't give
185	 * us one */
186	mod_timer(&priv->statistics_periodic, jiffies +
187		  msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
188
189	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
190	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
191		iwl4965_rx_calc_noise(priv);
192		queue_work(priv->workqueue, &priv->run_time_calib_work);
193	}
194	if (priv->cfg->ops->lib->temp_ops.temperature && change)
195		priv->cfg->ops->lib->temp_ops.temperature(priv);
196}
197
198void iwl4965_reply_statistics(struct iwl_priv *priv,
199			      struct iwl_rx_mem_buffer *rxb)
200{
201	struct iwl_rx_packet *pkt = rxb_addr(rxb);
202
203	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
204#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
205		memset(&priv->_4965.accum_statistics, 0,
206			sizeof(struct iwl_notif_statistics));
207		memset(&priv->_4965.delta_statistics, 0,
208			sizeof(struct iwl_notif_statistics));
209		memset(&priv->_4965.max_delta, 0,
210			sizeof(struct iwl_notif_statistics));
211#endif
212		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
213	}
214	iwl4965_rx_statistics(priv, rxb);
215}