Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: 2.6.35-rc3: Reported regressions 2.6.33 -> 2.6.34
From: Luis R. Rodriguez @ 2010-06-21 18:32 UTC (permalink / raw)
  To: linux-wireless, linux-bluetooth
  Cc: Rafael J. Wysocki, reinette chatre, j, adobriyan, tj,
	Satish Eerpini, Petr Pisar, Pavel Machek
In-Reply-To: <g77CuMUl7QI.A.qMH.4ZpHMB@chimera>

On Sun, Jun 20, 2010 at 3:32 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> This message contains a list of some post-2.6.33 regressions introduced before
> 2.6.34, for which there are no fixes in the mainline known to the tracking team.
> If any of them have been fixed already, please let us know.
>
> If you know of any other unresolved post-2.6.33 regressions, please let us know
> either and we'll add them to the list.  Also, please let us know if any
> of the entries below are invalid.
>
> Each entry from the list will be sent additionally in an automatic reply to
> this message with CCs to the people involved in reporting and handling the
> issue.
>
>
> Listed regressions statistics:
>
>  Date          Total  Pending  Unresolved
>  ----------------------------------------
>  2010-06-21      114       36          28
>  2010-06-13      111       40          34
>  2010-05-09       80       27          24
>  2010-05-04       76       26          22
>  2010-04-20       64       35          34
>  2010-04-07       48       35          33
>  2010-03-21       15       13          10

I'm going to just leave in the 802.11, Bluetooth and PCMCIA ones below:

> Unresolved regressions
> ----------------------


> Bug-Entry       : http://bugzilla.kernel.org/show_bug.cgi?id=16111
> Subject         : hostap_pci: infinite registered netdevice wifi0
> Submitter       : Petr Pisar <petr.pisar@atlas.cz>
> Date            : 2010-06-02 20:55 (19 days old)

The last entry on this one says we are not sure how to fix this...

> Bug-Entry       : http://bugzilla.kernel.org/show_bug.cgi?id=16084
> Subject         : iwl3945 bug in 2.6.34
> Submitter       : Satish Eerpini <eerpini@gmail.com>
> Date            : 2010-05-23 6:37 (29 days old)
> Message-ID      : <AANLkTik_7rxDBc0TKlAfoYyM5S6Cf_Hyxbr4W5ORnTsq@mail.gmail.com>
> References      : http://marc.info/?l=linux-kernel&m=127459596015626&w=2

This is getting some love by Reinette.

> Bug-Entry       : http://bugzilla.kernel.org/show_bug.cgi?id=15717
> Subject         : bluetooth oops
> Submitter       : Pavel Machek <pavel@ucw.cz>
> Date            : 2010-03-14 20:14 (99 days old)
> Message-ID      : <20100314201434.GE22059@elf.ucw.cz>
> References      : http://marc.info/?l=linux-kernel&m=126859771528426&w=4
> Handled-By      : Marcel Holtmann <marcel@holtmann.org>

Pavel, is this still happening or was just spurious on 2.6.34-rc1?

> Regressions with patches
> ------------------------


> Bug-Entry       : http://bugzilla.kernel.org/show_bug.cgi?id=16138
> Subject         : PCMCIA regression
> Submitter       : Mikulas Patocka <mpatocka@redhat.com>
> Date            : 2010-05-25 20:25 (27 days old)
> Message-ID      : <Pine.LNX.4.64.1005251619020.12278@hs20-bc2-1.build.redhat.com>
> References      : http://marc.info/?l=linux-kernel&m=127481913909672&w=2
> Handled-By      : Dominik Brodowski <linux@brodo.de>
> Patch           : https://bugzilla.kernel.org/attachment.cgi?id=26685

Linville, are you to get PCMCIA stuff now? Anyway Rafael, please
remove this, this is fixed.

> For details, please visit the bug entries and follow the links given in
> references.
>
> As you can see, there is a Bugzilla entry for each of the listed regressions.
> There also is a Bugzilla entry used for tracking the regressions introduced
> between 2.6.33 and 2.6.34, unresolved as well as resolved, at:
>
> http://bugzilla.kernel.org/show_bug.cgi?id=15310
>
> Please let the tracking teak know if there are any Bugzilla entries that
> should be added to the list in there.
>
> Thanks!
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* [PATCH 9/9] iwlwifi: remove non-exist reference
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1277143600-32554-1-git-send-email-reinette.chatre@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Remove the reference to non-exist function in iwlcore

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.h |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 1c09dc8..5e72d74 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -457,8 +457,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 /* Handlers */
 void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 					  struct iwl_rx_mem_buffer *rxb);
-bool iwl_good_ack_health(struct iwl_priv *priv,
-				 struct iwl_rx_packet *pkt);
 void iwl_recover_from_statistics(struct iwl_priv *priv,
 				struct iwl_rx_packet *pkt);
 void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 7/9] iwlwifi: move calibration from iwlcore to iwlagn
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1277143600-32554-1-git-send-email-reinette.chatre@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

All the calibrations are "agn" only functions, move from iwlcore to
iwlagn.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/Makefile        |    4 +-
 drivers/net/wireless/iwlwifi/iwl-agn-calib.c |  910 +++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-calib.c     |  919 --------------------------
 3 files changed, 912 insertions(+), 921 deletions(-)
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-calib.c
 delete mode 100644 drivers/net/wireless/iwlwifi/iwl-calib.c

diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 9084c52..728bb85 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_IWLWIFI)	+= iwlcore.o
 iwlcore-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
-iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o
+iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
 iwlcore-objs 		+= iwl-scan.o iwl-led.o
 iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
@@ -11,7 +11,7 @@ CFLAGS_iwl-devtrace.o := -I$(src)
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o
 iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
 iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
-iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o
+iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 
 iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
new file mode 100644
index 0000000..d03b5e5
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -0,0 +1,910 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-calib.h"
+
+/*****************************************************************************
+ * INIT calibrations framework
+ *****************************************************************************/
+
+struct statistics_general_data {
+	u32 beacon_silence_rssi_a;
+	u32 beacon_silence_rssi_b;
+	u32 beacon_silence_rssi_c;
+	u32 beacon_energy_a;
+	u32 beacon_energy_b;
+	u32 beacon_energy_c;
+};
+
+int iwl_send_calib_results(struct iwl_priv *priv)
+{
+	int ret = 0;
+	int i = 0;
+
+	struct iwl_host_cmd hcmd = {
+		.id = REPLY_PHY_CALIBRATION_CMD,
+		.flags = CMD_SIZE_HUGE,
+	};
+
+	for (i = 0; i < IWL_CALIB_MAX; i++) {
+		if ((BIT(i) & priv->hw_params.calib_init_cfg) &&
+		    priv->calib_results[i].buf) {
+			hcmd.len = priv->calib_results[i].buf_len;
+			hcmd.data = priv->calib_results[i].buf;
+			ret = iwl_send_cmd_sync(priv, &hcmd);
+			if (ret)
+				goto err;
+		}
+	}
+
+	return 0;
+err:
+	IWL_ERR(priv, "Error %d iteration %d\n", ret, i);
+	return ret;
+}
+
+int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
+{
+	if (res->buf_len != len) {
+		kfree(res->buf);
+		res->buf = kzalloc(len, GFP_ATOMIC);
+	}
+	if (unlikely(res->buf == NULL))
+		return -ENOMEM;
+
+	res->buf_len = len;
+	memcpy(res->buf, buf, len);
+	return 0;
+}
+
+void iwl_calib_free_results(struct iwl_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < IWL_CALIB_MAX; i++) {
+		kfree(priv->calib_results[i].buf);
+		priv->calib_results[i].buf = NULL;
+		priv->calib_results[i].buf_len = 0;
+	}
+}
+
+/*****************************************************************************
+ * RUNTIME calibrations framework
+ *****************************************************************************/
+
+/* "false alarms" are signals that our DSP tries to lock onto,
+ *   but then determines that they are either noise, or transmissions
+ *   from a distant wireless network (also "noise", really) that get
+ *   "stepped on" by stronger transmissions within our own network.
+ * This algorithm attempts to set a sensitivity level that is high
+ *   enough to receive all of our own network traffic, but not so
+ *   high that our DSP gets too busy trying to lock onto non-network
+ *   activity/noise. */
+static int iwl_sens_energy_cck(struct iwl_priv *priv,
+				   u32 norm_fa,
+				   u32 rx_enable_time,
+				   struct statistics_general_data *rx_info)
+{
+	u32 max_nrg_cck = 0;
+	int i = 0;
+	u8 max_silence_rssi = 0;
+	u32 silence_ref = 0;
+	u8 silence_rssi_a = 0;
+	u8 silence_rssi_b = 0;
+	u8 silence_rssi_c = 0;
+	u32 val;
+
+	/* "false_alarms" values below are cross-multiplications to assess the
+	 *   numbers of false alarms within the measured period of actual Rx
+	 *   (Rx is off when we're txing), vs the min/max expected false alarms
+	 *   (some should be expected if rx is sensitive enough) in a
+	 *   hypothetical listening period of 200 time units (TU), 204.8 msec:
+	 *
+	 * MIN_FA/fixed-time < false_alarms/actual-rx-time < MAX_FA/beacon-time
+	 *
+	 * */
+	u32 false_alarms = norm_fa * 200 * 1024;
+	u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
+	u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
+	struct iwl_sensitivity_data *data = NULL;
+	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+
+	data = &(priv->sensitivity_data);
+
+	data->nrg_auto_corr_silence_diff = 0;
+
+	/* Find max silence rssi among all 3 receivers.
+	 * This is background noise, which may include transmissions from other
+	 *    networks, measured during silence before our network's beacon */
+	silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
+			    ALL_BAND_FILTER) >> 8);
+	silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
+			    ALL_BAND_FILTER) >> 8);
+	silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
+			    ALL_BAND_FILTER) >> 8);
+
+	val = max(silence_rssi_b, silence_rssi_c);
+	max_silence_rssi = max(silence_rssi_a, (u8) val);
+
+	/* Store silence rssi in 20-beacon history table */
+	data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi;
+	data->nrg_silence_idx++;
+	if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L)
+		data->nrg_silence_idx = 0;
+
+	/* Find max silence rssi across 20 beacon history */
+	for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) {
+		val = data->nrg_silence_rssi[i];
+		silence_ref = max(silence_ref, val);
+	}
+	IWL_DEBUG_CALIB(priv, "silence a %u, b %u, c %u, 20-bcn max %u\n",
+			silence_rssi_a, silence_rssi_b, silence_rssi_c,
+			silence_ref);
+
+	/* Find max rx energy (min value!) among all 3 receivers,
+	 *   measured during beacon frame.
+	 * Save it in 10-beacon history table. */
+	i = data->nrg_energy_idx;
+	val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c);
+	data->nrg_value[i] = min(rx_info->beacon_energy_a, val);
+
+	data->nrg_energy_idx++;
+	if (data->nrg_energy_idx >= 10)
+		data->nrg_energy_idx = 0;
+
+	/* Find min rx energy (max value) across 10 beacon history.
+	 * This is the minimum signal level that we want to receive well.
+	 * Add backoff (margin so we don't miss slightly lower energy frames).
+	 * This establishes an upper bound (min value) for energy threshold. */
+	max_nrg_cck = data->nrg_value[0];
+	for (i = 1; i < 10; i++)
+		max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
+	max_nrg_cck += 6;
+
+	IWL_DEBUG_CALIB(priv, "rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
+			rx_info->beacon_energy_a, rx_info->beacon_energy_b,
+			rx_info->beacon_energy_c, max_nrg_cck - 6);
+
+	/* Count number of consecutive beacons with fewer-than-desired
+	 *   false alarms. */
+	if (false_alarms < min_false_alarms)
+		data->num_in_cck_no_fa++;
+	else
+		data->num_in_cck_no_fa = 0;
+	IWL_DEBUG_CALIB(priv, "consecutive bcns with few false alarms = %u\n",
+			data->num_in_cck_no_fa);
+
+	/* If we got too many false alarms this time, reduce sensitivity */
+	if ((false_alarms > max_false_alarms) &&
+		(data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK)) {
+		IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u\n",
+		     false_alarms, max_false_alarms);
+		IWL_DEBUG_CALIB(priv, "... reducing sensitivity\n");
+		data->nrg_curr_state = IWL_FA_TOO_MANY;
+		/* Store for "fewer than desired" on later beacon */
+		data->nrg_silence_ref = silence_ref;
+
+		/* increase energy threshold (reduce nrg value)
+		 *   to decrease sensitivity */
+		data->nrg_th_cck = data->nrg_th_cck - NRG_STEP_CCK;
+	/* Else if we got fewer than desired, increase sensitivity */
+	} else if (false_alarms < min_false_alarms) {
+		data->nrg_curr_state = IWL_FA_TOO_FEW;
+
+		/* Compare silence level with silence level for most recent
+		 *   healthy number or too many false alarms */
+		data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref -
+						   (s32)silence_ref;
+
+		IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u, silence diff %d\n",
+			 false_alarms, min_false_alarms,
+			 data->nrg_auto_corr_silence_diff);
+
+		/* Increase value to increase sensitivity, but only if:
+		 * 1a) previous beacon did *not* have *too many* false alarms
+		 * 1b) AND there's a significant difference in Rx levels
+		 *      from a previous beacon with too many, or healthy # FAs
+		 * OR 2) We've seen a lot of beacons (100) with too few
+		 *       false alarms */
+		if ((data->nrg_prev_state != IWL_FA_TOO_MANY) &&
+			((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
+			(data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
+
+			IWL_DEBUG_CALIB(priv, "... increasing sensitivity\n");
+			/* Increase nrg value to increase sensitivity */
+			val = data->nrg_th_cck + NRG_STEP_CCK;
+			data->nrg_th_cck = min((u32)ranges->min_nrg_cck, val);
+		} else {
+			IWL_DEBUG_CALIB(priv, "... but not changing sensitivity\n");
+		}
+
+	/* Else we got a healthy number of false alarms, keep status quo */
+	} else {
+		IWL_DEBUG_CALIB(priv, " FA in safe zone\n");
+		data->nrg_curr_state = IWL_FA_GOOD_RANGE;
+
+		/* Store for use in "fewer than desired" with later beacon */
+		data->nrg_silence_ref = silence_ref;
+
+		/* If previous beacon had too many false alarms,
+		 *   give it some extra margin by reducing sensitivity again
+		 *   (but don't go below measured energy of desired Rx) */
+		if (IWL_FA_TOO_MANY == data->nrg_prev_state) {
+			IWL_DEBUG_CALIB(priv, "... increasing margin\n");
+			if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN))
+				data->nrg_th_cck -= NRG_MARGIN;
+			else
+				data->nrg_th_cck = max_nrg_cck;
+		}
+	}
+
+	/* Make sure the energy threshold does not go above the measured
+	 * energy of the desired Rx signals (reduced by backoff margin),
+	 * or else we might start missing Rx frames.
+	 * Lower value is higher energy, so we use max()!
+	 */
+	data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
+	IWL_DEBUG_CALIB(priv, "new nrg_th_cck %u\n", data->nrg_th_cck);
+
+	data->nrg_prev_state = data->nrg_curr_state;
+
+	/* Auto-correlation CCK algorithm */
+	if (false_alarms > min_false_alarms) {
+
+		/* increase auto_corr values to decrease sensitivity
+		 * so the DSP won't be disturbed by the noise
+		 */
+		if (data->auto_corr_cck < AUTO_CORR_MAX_TH_CCK)
+			data->auto_corr_cck = AUTO_CORR_MAX_TH_CCK + 1;
+		else {
+			val = data->auto_corr_cck + AUTO_CORR_STEP_CCK;
+			data->auto_corr_cck =
+				min((u32)ranges->auto_corr_max_cck, val);
+		}
+		val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK;
+		data->auto_corr_cck_mrc =
+			min((u32)ranges->auto_corr_max_cck_mrc, val);
+	} else if ((false_alarms < min_false_alarms) &&
+	   ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
+	   (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
+
+		/* Decrease auto_corr values to increase sensitivity */
+		val = data->auto_corr_cck - AUTO_CORR_STEP_CCK;
+		data->auto_corr_cck =
+			max((u32)ranges->auto_corr_min_cck, val);
+		val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK;
+		data->auto_corr_cck_mrc =
+			max((u32)ranges->auto_corr_min_cck_mrc, val);
+	}
+
+	return 0;
+}
+
+
+static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv,
+				       u32 norm_fa,
+				       u32 rx_enable_time)
+{
+	u32 val;
+	u32 false_alarms = norm_fa * 200 * 1024;
+	u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
+	u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
+	struct iwl_sensitivity_data *data = NULL;
+	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+
+	data = &(priv->sensitivity_data);
+
+	/* If we got too many false alarms this time, reduce sensitivity */
+	if (false_alarms > max_false_alarms) {
+
+		IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u)\n",
+			     false_alarms, max_false_alarms);
+
+		val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm =
+			min((u32)ranges->auto_corr_max_ofdm, val);
+
+		val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc =
+			min((u32)ranges->auto_corr_max_ofdm_mrc, val);
+
+		val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_x1 =
+			min((u32)ranges->auto_corr_max_ofdm_x1, val);
+
+		val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc_x1 =
+			min((u32)ranges->auto_corr_max_ofdm_mrc_x1, val);
+	}
+
+	/* Else if we got fewer than desired, increase sensitivity */
+	else if (false_alarms < min_false_alarms) {
+
+		IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u\n",
+			     false_alarms, min_false_alarms);
+
+		val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm =
+			max((u32)ranges->auto_corr_min_ofdm, val);
+
+		val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc =
+			max((u32)ranges->auto_corr_min_ofdm_mrc, val);
+
+		val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_x1 =
+			max((u32)ranges->auto_corr_min_ofdm_x1, val);
+
+		val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc_x1 =
+			max((u32)ranges->auto_corr_min_ofdm_mrc_x1, val);
+	} else {
+		IWL_DEBUG_CALIB(priv, "min FA %u < norm FA %u < max FA %u OK\n",
+			 min_false_alarms, false_alarms, max_false_alarms);
+	}
+	return 0;
+}
+
+/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
+static int iwl_sensitivity_write(struct iwl_priv *priv)
+{
+	struct iwl_sensitivity_cmd cmd ;
+	struct iwl_sensitivity_data *data = NULL;
+	struct iwl_host_cmd cmd_out = {
+		.id = SENSITIVITY_CMD,
+		.len = sizeof(struct iwl_sensitivity_cmd),
+		.flags = CMD_ASYNC,
+		.data = &cmd,
+	};
+
+	data = &(priv->sensitivity_data);
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm);
+	cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm_mrc);
+	cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm_x1);
+	cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1);
+
+	cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_cck);
+	cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_cck_mrc);
+
+	cmd.table[HD_MIN_ENERGY_CCK_DET_INDEX] =
+				cpu_to_le16((u16)data->nrg_th_cck);
+	cmd.table[HD_MIN_ENERGY_OFDM_DET_INDEX] =
+				cpu_to_le16((u16)data->nrg_th_ofdm);
+
+	cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
+				cpu_to_le16(data->barker_corr_th_min);
+	cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16(data->barker_corr_th_min_mrc);
+	cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] =
+				cpu_to_le16(data->nrg_th_cca);
+
+	IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
+			data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
+			data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
+			data->nrg_th_ofdm);
+
+	IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n",
+			data->auto_corr_cck, data->auto_corr_cck_mrc,
+			data->nrg_th_cck);
+
+	/* Update uCode's "work" table, and copy it to DSP */
+	cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
+
+	/* Don't send command to uCode if nothing has changed */
+	if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]),
+		    sizeof(u16)*HD_TABLE_SIZE)) {
+		IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n");
+		return 0;
+	}
+
+	/* Copy table for comparison next time */
+	memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
+	       sizeof(u16)*HD_TABLE_SIZE);
+
+	return iwl_send_cmd(priv, &cmd_out);
+}
+
+void iwl_init_sensitivity(struct iwl_priv *priv)
+{
+	int ret = 0;
+	int i;
+	struct iwl_sensitivity_data *data = NULL;
+	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+
+	if (priv->disable_sens_cal)
+		return;
+
+	IWL_DEBUG_CALIB(priv, "Start iwl_init_sensitivity\n");
+
+	/* Clear driver's sensitivity algo data */
+	data = &(priv->sensitivity_data);
+
+	if (ranges == NULL)
+		return;
+
+	memset(data, 0, sizeof(struct iwl_sensitivity_data));
+
+	data->num_in_cck_no_fa = 0;
+	data->nrg_curr_state = IWL_FA_TOO_MANY;
+	data->nrg_prev_state = IWL_FA_TOO_MANY;
+	data->nrg_silence_ref = 0;
+	data->nrg_silence_idx = 0;
+	data->nrg_energy_idx = 0;
+
+	for (i = 0; i < 10; i++)
+		data->nrg_value[i] = 0;
+
+	for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
+		data->nrg_silence_rssi[i] = 0;
+
+	data->auto_corr_ofdm =  ranges->auto_corr_min_ofdm;
+	data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc;
+	data->auto_corr_ofdm_x1  = ranges->auto_corr_min_ofdm_x1;
+	data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1;
+	data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF;
+	data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc;
+	data->nrg_th_cck = ranges->nrg_th_cck;
+	data->nrg_th_ofdm = ranges->nrg_th_ofdm;
+	data->barker_corr_th_min = ranges->barker_corr_th_min;
+	data->barker_corr_th_min_mrc = ranges->barker_corr_th_min_mrc;
+	data->nrg_th_cca = ranges->nrg_th_cca;
+
+	data->last_bad_plcp_cnt_ofdm = 0;
+	data->last_fa_cnt_ofdm = 0;
+	data->last_bad_plcp_cnt_cck = 0;
+	data->last_fa_cnt_cck = 0;
+
+	ret |= iwl_sensitivity_write(priv);
+	IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
+}
+
+void iwl_sensitivity_calibration(struct iwl_priv *priv,
+				    struct iwl_notif_statistics *resp)
+{
+	u32 rx_enable_time;
+	u32 fa_cck;
+	u32 fa_ofdm;
+	u32 bad_plcp_cck;
+	u32 bad_plcp_ofdm;
+	u32 norm_fa_ofdm;
+	u32 norm_fa_cck;
+	struct iwl_sensitivity_data *data = NULL;
+	struct statistics_rx_non_phy *rx_info = &(resp->rx.general);
+	struct statistics_rx *statistics = &(resp->rx);
+	unsigned long flags;
+	struct statistics_general_data statis;
+
+	if (priv->disable_sens_cal)
+		return;
+
+	data = &(priv->sensitivity_data);
+
+	if (!iwl_is_associated(priv)) {
+		IWL_DEBUG_CALIB(priv, "<< - not associated\n");
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
+		IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	/* Extract Statistics: */
+	rx_enable_time = le32_to_cpu(rx_info->channel_load);
+	fa_cck = le32_to_cpu(statistics->cck.false_alarm_cnt);
+	fa_ofdm = le32_to_cpu(statistics->ofdm.false_alarm_cnt);
+	bad_plcp_cck = le32_to_cpu(statistics->cck.plcp_err);
+	bad_plcp_ofdm = le32_to_cpu(statistics->ofdm.plcp_err);
+
+	statis.beacon_silence_rssi_a =
+			le32_to_cpu(statistics->general.beacon_silence_rssi_a);
+	statis.beacon_silence_rssi_b =
+			le32_to_cpu(statistics->general.beacon_silence_rssi_b);
+	statis.beacon_silence_rssi_c =
+			le32_to_cpu(statistics->general.beacon_silence_rssi_c);
+	statis.beacon_energy_a =
+			le32_to_cpu(statistics->general.beacon_energy_a);
+	statis.beacon_energy_b =
+			le32_to_cpu(statistics->general.beacon_energy_b);
+	statis.beacon_energy_c =
+			le32_to_cpu(statistics->general.beacon_energy_c);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
+
+	if (!rx_enable_time) {
+		IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n");
+		return;
+	}
+
+	/* These statistics increase monotonically, and do not reset
+	 *   at each beacon.  Calculate difference from last value, or just
+	 *   use the new statistics value if it has reset or wrapped around. */
+	if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
+		data->last_bad_plcp_cnt_cck = bad_plcp_cck;
+	else {
+		bad_plcp_cck -= data->last_bad_plcp_cnt_cck;
+		data->last_bad_plcp_cnt_cck += bad_plcp_cck;
+	}
+
+	if (data->last_bad_plcp_cnt_ofdm > bad_plcp_ofdm)
+		data->last_bad_plcp_cnt_ofdm = bad_plcp_ofdm;
+	else {
+		bad_plcp_ofdm -= data->last_bad_plcp_cnt_ofdm;
+		data->last_bad_plcp_cnt_ofdm += bad_plcp_ofdm;
+	}
+
+	if (data->last_fa_cnt_ofdm > fa_ofdm)
+		data->last_fa_cnt_ofdm = fa_ofdm;
+	else {
+		fa_ofdm -= data->last_fa_cnt_ofdm;
+		data->last_fa_cnt_ofdm += fa_ofdm;
+	}
+
+	if (data->last_fa_cnt_cck > fa_cck)
+		data->last_fa_cnt_cck = fa_cck;
+	else {
+		fa_cck -= data->last_fa_cnt_cck;
+		data->last_fa_cnt_cck += fa_cck;
+	}
+
+	/* Total aborted signal locks */
+	norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm;
+	norm_fa_cck = fa_cck + bad_plcp_cck;
+
+	IWL_DEBUG_CALIB(priv, "cck: fa %u badp %u  ofdm: fa %u badp %u\n", fa_cck,
+			bad_plcp_cck, fa_ofdm, bad_plcp_ofdm);
+
+	iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
+	iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
+	iwl_sensitivity_write(priv);
+}
+
+static inline u8 find_first_chain(u8 mask)
+{
+	if (mask & ANT_A)
+		return CHAIN_A;
+	if (mask & ANT_B)
+		return CHAIN_B;
+	return CHAIN_C;
+}
+
+/*
+ * Accumulate 20 beacons of signal and noise statistics for each of
+ *   3 receivers/antennas/rx-chains, then figure out:
+ * 1)  Which antennas are connected.
+ * 2)  Differential rx gain settings to balance the 3 receivers.
+ */
+void iwl_chain_noise_calibration(struct iwl_priv *priv,
+				 struct iwl_notif_statistics *stat_resp)
+{
+	struct iwl_chain_noise_data *data = NULL;
+
+	u32 chain_noise_a;
+	u32 chain_noise_b;
+	u32 chain_noise_c;
+	u32 chain_sig_a;
+	u32 chain_sig_b;
+	u32 chain_sig_c;
+	u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
+	u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
+	u32 max_average_sig;
+	u16 max_average_sig_antenna_i;
+	u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
+	u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
+	u16 i = 0;
+	u16 rxon_chnum = INITIALIZATION_VALUE;
+	u16 stat_chnum = INITIALIZATION_VALUE;
+	u8 rxon_band24;
+	u8 stat_band24;
+	u32 active_chains = 0;
+	u8 num_tx_chains;
+	unsigned long flags;
+	struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general);
+	u8 first_chain;
+
+	if (priv->disable_chain_noise_cal)
+		return;
+
+	data = &(priv->chain_noise_data);
+
+	/*
+	 * Accumulate just the first "chain_noise_num_beacons" after
+	 * the first association, then we're done forever.
+	 */
+	if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) {
+		if (data->state == IWL_CHAIN_NOISE_ALIVE)
+			IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n");
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
+		IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK);
+	rxon_chnum = le16_to_cpu(priv->staging_rxon.channel);
+	stat_band24 = !!(stat_resp->flag & STATISTICS_REPLY_FLG_BAND_24G_MSK);
+	stat_chnum = le32_to_cpu(stat_resp->flag) >> 16;
+
+	/* Make sure we accumulate data for just the associated channel
+	 *   (even if scanning). */
+	if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
+		IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
+				rxon_chnum, rxon_band24);
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	/*
+	 *  Accumulate beacon statistics values across
+	 * "chain_noise_num_beacons"
+	 */
+	chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) &
+				IN_BAND_FILTER;
+	chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) &
+				IN_BAND_FILTER;
+	chain_noise_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) &
+				IN_BAND_FILTER;
+
+	chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER;
+	chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
+	chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	data->beacon_count++;
+
+	data->chain_noise_a = (chain_noise_a + data->chain_noise_a);
+	data->chain_noise_b = (chain_noise_b + data->chain_noise_b);
+	data->chain_noise_c = (chain_noise_c + data->chain_noise_c);
+
+	data->chain_signal_a = (chain_sig_a + data->chain_signal_a);
+	data->chain_signal_b = (chain_sig_b + data->chain_signal_b);
+	data->chain_signal_c = (chain_sig_c + data->chain_signal_c);
+
+	IWL_DEBUG_CALIB(priv, "chan=%d, band24=%d, beacon=%d\n",
+			rxon_chnum, rxon_band24, data->beacon_count);
+	IWL_DEBUG_CALIB(priv, "chain_sig: a %d b %d c %d\n",
+			chain_sig_a, chain_sig_b, chain_sig_c);
+	IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n",
+			chain_noise_a, chain_noise_b, chain_noise_c);
+
+	/* If this is the "chain_noise_num_beacons", determine:
+	 * 1)  Disconnected antennas (using signal strengths)
+	 * 2)  Differential gain (using silence noise) to balance receivers */
+	if (data->beacon_count != priv->cfg->chain_noise_num_beacons)
+		return;
+
+	/* Analyze signal for disconnected antenna */
+	average_sig[0] =
+		(data->chain_signal_a) / priv->cfg->chain_noise_num_beacons;
+	average_sig[1] =
+		(data->chain_signal_b) / priv->cfg->chain_noise_num_beacons;
+	average_sig[2] =
+		(data->chain_signal_c) / priv->cfg->chain_noise_num_beacons;
+
+	if (average_sig[0] >= average_sig[1]) {
+		max_average_sig = average_sig[0];
+		max_average_sig_antenna_i = 0;
+		active_chains = (1 << max_average_sig_antenna_i);
+	} else {
+		max_average_sig = average_sig[1];
+		max_average_sig_antenna_i = 1;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	if (average_sig[2] >= max_average_sig) {
+		max_average_sig = average_sig[2];
+		max_average_sig_antenna_i = 2;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
+		     average_sig[0], average_sig[1], average_sig[2]);
+	IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
+		     max_average_sig, max_average_sig_antenna_i);
+
+	/* Compare signal strengths for all 3 receivers. */
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		if (i != max_average_sig_antenna_i) {
+			s32 rssi_delta = (max_average_sig - average_sig[i]);
+
+			/* If signal is very weak, compared with
+			 * strongest, mark it as disconnected. */
+			if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
+				data->disconn_array[i] = 1;
+			else
+				active_chains |= (1 << i);
+			IWL_DEBUG_CALIB(priv, "i = %d  rssiDelta = %d  "
+			     "disconn_array[i] = %d\n",
+			     i, rssi_delta, data->disconn_array[i]);
+		}
+	}
+
+	/*
+	 * The above algorithm sometimes fails when the ucode
+	 * reports 0 for all chains. It's not clear why that
+	 * happens to start with, but it is then causing trouble
+	 * because this can make us enable more chains than the
+	 * hardware really has.
+	 *
+	 * To be safe, simply mask out any chains that we know
+	 * are not on the device.
+	 */
+	active_chains &= priv->hw_params.valid_rx_ant;
+
+	num_tx_chains = 0;
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		/* loops on all the bits of
+		 * priv->hw_setting.valid_tx_ant */
+		u8 ant_msk = (1 << i);
+		if (!(priv->hw_params.valid_tx_ant & ant_msk))
+			continue;
+
+		num_tx_chains++;
+		if (data->disconn_array[i] == 0)
+			/* there is a Tx antenna connected */
+			break;
+		if (num_tx_chains == priv->hw_params.tx_chains_num &&
+		    data->disconn_array[i]) {
+			/*
+			 * If all chains are disconnected
+			 * connect the first valid tx chain
+			 */
+			first_chain =
+				find_first_chain(priv->cfg->valid_tx_ant);
+			data->disconn_array[first_chain] = 0;
+			active_chains |= BIT(first_chain);
+			IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n",
+					first_chain);
+			break;
+		}
+	}
+
+	if (active_chains != priv->hw_params.valid_rx_ant &&
+	    active_chains != priv->chain_noise_data.active_chains)
+		IWL_WARN(priv,
+			 "Detected that not all antennas are connected! "
+			 "Connected: %#x, valid: %#x.\n",
+			 active_chains, priv->hw_params.valid_rx_ant);
+
+	/* Save for use within RXON, TX, SCAN commands, etc. */
+	priv->chain_noise_data.active_chains = active_chains;
+	IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
+			active_chains);
+
+	/* Analyze noise for rx balance */
+	average_noise[0] =
+		((data->chain_noise_a) / priv->cfg->chain_noise_num_beacons);
+	average_noise[1] =
+		((data->chain_noise_b) / priv->cfg->chain_noise_num_beacons);
+	average_noise[2] =
+		((data->chain_noise_c) / priv->cfg->chain_noise_num_beacons);
+
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		if (!(data->disconn_array[i]) &&
+		   (average_noise[i] <= min_average_noise)) {
+			/* This means that chain i is active and has
+			 * lower noise values so far: */
+			min_average_noise = average_noise[i];
+			min_average_noise_antenna_i = i;
+		}
+	}
+
+	IWL_DEBUG_CALIB(priv, "average_noise: a %d b %d c %d\n",
+			average_noise[0], average_noise[1],
+			average_noise[2]);
+
+	IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
+			min_average_noise, min_average_noise_antenna_i);
+
+	if (priv->cfg->ops->utils->gain_computation)
+		priv->cfg->ops->utils->gain_computation(priv, average_noise,
+				min_average_noise_antenna_i, min_average_noise,
+				find_first_chain(priv->cfg->valid_rx_ant));
+
+	/* Some power changes may have been made during the calibration.
+	 * Update and commit the RXON
+	 */
+	if (priv->cfg->ops->lib->update_chain_flags)
+		priv->cfg->ops->lib->update_chain_flags(priv);
+
+	data->state = IWL_CHAIN_NOISE_DONE;
+	iwl_power_update_mode(priv, false);
+}
+
+void iwl_reset_run_time_calib(struct iwl_priv *priv)
+{
+	int i;
+	memset(&(priv->sensitivity_data), 0,
+	       sizeof(struct iwl_sensitivity_data));
+	memset(&(priv->chain_noise_data), 0,
+	       sizeof(struct iwl_chain_noise_data));
+	for (i = 0; i < NUM_RX_CHAINS; i++)
+		priv->chain_noise_data.delta_gain_code[i] =
+				CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
+
+	/* Ask for statistics now, the uCode will send notification
+	 * periodically after association */
+	iwl_send_statistics_request(priv, CMD_ASYNC, true);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
deleted file mode 100644
index 22fa947..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ /dev/null
@@ -1,919 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *  * Neither the name Intel Corporation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
-
-#include <linux/slab.h>
-#include <net/mac80211.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-calib.h"
-
-/*****************************************************************************
- * INIT calibrations framework
- *****************************************************************************/
-
-struct statistics_general_data {
-	u32 beacon_silence_rssi_a;
-	u32 beacon_silence_rssi_b;
-	u32 beacon_silence_rssi_c;
-	u32 beacon_energy_a;
-	u32 beacon_energy_b;
-	u32 beacon_energy_c;
-};
-
-int iwl_send_calib_results(struct iwl_priv *priv)
-{
-	int ret = 0;
-	int i = 0;
-
-	struct iwl_host_cmd hcmd = {
-		.id = REPLY_PHY_CALIBRATION_CMD,
-		.flags = CMD_SIZE_HUGE,
-	};
-
-	for (i = 0; i < IWL_CALIB_MAX; i++) {
-		if ((BIT(i) & priv->hw_params.calib_init_cfg) &&
-		    priv->calib_results[i].buf) {
-			hcmd.len = priv->calib_results[i].buf_len;
-			hcmd.data = priv->calib_results[i].buf;
-			ret = iwl_send_cmd_sync(priv, &hcmd);
-			if (ret)
-				goto err;
-		}
-	}
-
-	return 0;
-err:
-	IWL_ERR(priv, "Error %d iteration %d\n", ret, i);
-	return ret;
-}
-EXPORT_SYMBOL(iwl_send_calib_results);
-
-int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
-{
-	if (res->buf_len != len) {
-		kfree(res->buf);
-		res->buf = kzalloc(len, GFP_ATOMIC);
-	}
-	if (unlikely(res->buf == NULL))
-		return -ENOMEM;
-
-	res->buf_len = len;
-	memcpy(res->buf, buf, len);
-	return 0;
-}
-EXPORT_SYMBOL(iwl_calib_set);
-
-void iwl_calib_free_results(struct iwl_priv *priv)
-{
-	int i;
-
-	for (i = 0; i < IWL_CALIB_MAX; i++) {
-		kfree(priv->calib_results[i].buf);
-		priv->calib_results[i].buf = NULL;
-		priv->calib_results[i].buf_len = 0;
-	}
-}
-EXPORT_SYMBOL(iwl_calib_free_results);
-
-/*****************************************************************************
- * RUNTIME calibrations framework
- *****************************************************************************/
-
-/* "false alarms" are signals that our DSP tries to lock onto,
- *   but then determines that they are either noise, or transmissions
- *   from a distant wireless network (also "noise", really) that get
- *   "stepped on" by stronger transmissions within our own network.
- * This algorithm attempts to set a sensitivity level that is high
- *   enough to receive all of our own network traffic, but not so
- *   high that our DSP gets too busy trying to lock onto non-network
- *   activity/noise. */
-static int iwl_sens_energy_cck(struct iwl_priv *priv,
-				   u32 norm_fa,
-				   u32 rx_enable_time,
-				   struct statistics_general_data *rx_info)
-{
-	u32 max_nrg_cck = 0;
-	int i = 0;
-	u8 max_silence_rssi = 0;
-	u32 silence_ref = 0;
-	u8 silence_rssi_a = 0;
-	u8 silence_rssi_b = 0;
-	u8 silence_rssi_c = 0;
-	u32 val;
-
-	/* "false_alarms" values below are cross-multiplications to assess the
-	 *   numbers of false alarms within the measured period of actual Rx
-	 *   (Rx is off when we're txing), vs the min/max expected false alarms
-	 *   (some should be expected if rx is sensitive enough) in a
-	 *   hypothetical listening period of 200 time units (TU), 204.8 msec:
-	 *
-	 * MIN_FA/fixed-time < false_alarms/actual-rx-time < MAX_FA/beacon-time
-	 *
-	 * */
-	u32 false_alarms = norm_fa * 200 * 1024;
-	u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
-	u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
-	struct iwl_sensitivity_data *data = NULL;
-	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
-
-	data = &(priv->sensitivity_data);
-
-	data->nrg_auto_corr_silence_diff = 0;
-
-	/* Find max silence rssi among all 3 receivers.
-	 * This is background noise, which may include transmissions from other
-	 *    networks, measured during silence before our network's beacon */
-	silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
-			    ALL_BAND_FILTER) >> 8);
-	silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
-			    ALL_BAND_FILTER) >> 8);
-	silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
-			    ALL_BAND_FILTER) >> 8);
-
-	val = max(silence_rssi_b, silence_rssi_c);
-	max_silence_rssi = max(silence_rssi_a, (u8) val);
-
-	/* Store silence rssi in 20-beacon history table */
-	data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi;
-	data->nrg_silence_idx++;
-	if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L)
-		data->nrg_silence_idx = 0;
-
-	/* Find max silence rssi across 20 beacon history */
-	for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) {
-		val = data->nrg_silence_rssi[i];
-		silence_ref = max(silence_ref, val);
-	}
-	IWL_DEBUG_CALIB(priv, "silence a %u, b %u, c %u, 20-bcn max %u\n",
-			silence_rssi_a, silence_rssi_b, silence_rssi_c,
-			silence_ref);
-
-	/* Find max rx energy (min value!) among all 3 receivers,
-	 *   measured during beacon frame.
-	 * Save it in 10-beacon history table. */
-	i = data->nrg_energy_idx;
-	val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c);
-	data->nrg_value[i] = min(rx_info->beacon_energy_a, val);
-
-	data->nrg_energy_idx++;
-	if (data->nrg_energy_idx >= 10)
-		data->nrg_energy_idx = 0;
-
-	/* Find min rx energy (max value) across 10 beacon history.
-	 * This is the minimum signal level that we want to receive well.
-	 * Add backoff (margin so we don't miss slightly lower energy frames).
-	 * This establishes an upper bound (min value) for energy threshold. */
-	max_nrg_cck = data->nrg_value[0];
-	for (i = 1; i < 10; i++)
-		max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
-	max_nrg_cck += 6;
-
-	IWL_DEBUG_CALIB(priv, "rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
-			rx_info->beacon_energy_a, rx_info->beacon_energy_b,
-			rx_info->beacon_energy_c, max_nrg_cck - 6);
-
-	/* Count number of consecutive beacons with fewer-than-desired
-	 *   false alarms. */
-	if (false_alarms < min_false_alarms)
-		data->num_in_cck_no_fa++;
-	else
-		data->num_in_cck_no_fa = 0;
-	IWL_DEBUG_CALIB(priv, "consecutive bcns with few false alarms = %u\n",
-			data->num_in_cck_no_fa);
-
-	/* If we got too many false alarms this time, reduce sensitivity */
-	if ((false_alarms > max_false_alarms) &&
-		(data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK)) {
-		IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u\n",
-		     false_alarms, max_false_alarms);
-		IWL_DEBUG_CALIB(priv, "... reducing sensitivity\n");
-		data->nrg_curr_state = IWL_FA_TOO_MANY;
-		/* Store for "fewer than desired" on later beacon */
-		data->nrg_silence_ref = silence_ref;
-
-		/* increase energy threshold (reduce nrg value)
-		 *   to decrease sensitivity */
-		data->nrg_th_cck = data->nrg_th_cck - NRG_STEP_CCK;
-	/* Else if we got fewer than desired, increase sensitivity */
-	} else if (false_alarms < min_false_alarms) {
-		data->nrg_curr_state = IWL_FA_TOO_FEW;
-
-		/* Compare silence level with silence level for most recent
-		 *   healthy number or too many false alarms */
-		data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref -
-						   (s32)silence_ref;
-
-		IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u, silence diff %d\n",
-			 false_alarms, min_false_alarms,
-			 data->nrg_auto_corr_silence_diff);
-
-		/* Increase value to increase sensitivity, but only if:
-		 * 1a) previous beacon did *not* have *too many* false alarms
-		 * 1b) AND there's a significant difference in Rx levels
-		 *      from a previous beacon with too many, or healthy # FAs
-		 * OR 2) We've seen a lot of beacons (100) with too few
-		 *       false alarms */
-		if ((data->nrg_prev_state != IWL_FA_TOO_MANY) &&
-			((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
-			(data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
-
-			IWL_DEBUG_CALIB(priv, "... increasing sensitivity\n");
-			/* Increase nrg value to increase sensitivity */
-			val = data->nrg_th_cck + NRG_STEP_CCK;
-			data->nrg_th_cck = min((u32)ranges->min_nrg_cck, val);
-		} else {
-			IWL_DEBUG_CALIB(priv, "... but not changing sensitivity\n");
-		}
-
-	/* Else we got a healthy number of false alarms, keep status quo */
-	} else {
-		IWL_DEBUG_CALIB(priv, " FA in safe zone\n");
-		data->nrg_curr_state = IWL_FA_GOOD_RANGE;
-
-		/* Store for use in "fewer than desired" with later beacon */
-		data->nrg_silence_ref = silence_ref;
-
-		/* If previous beacon had too many false alarms,
-		 *   give it some extra margin by reducing sensitivity again
-		 *   (but don't go below measured energy of desired Rx) */
-		if (IWL_FA_TOO_MANY == data->nrg_prev_state) {
-			IWL_DEBUG_CALIB(priv, "... increasing margin\n");
-			if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN))
-				data->nrg_th_cck -= NRG_MARGIN;
-			else
-				data->nrg_th_cck = max_nrg_cck;
-		}
-	}
-
-	/* Make sure the energy threshold does not go above the measured
-	 * energy of the desired Rx signals (reduced by backoff margin),
-	 * or else we might start missing Rx frames.
-	 * Lower value is higher energy, so we use max()!
-	 */
-	data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
-	IWL_DEBUG_CALIB(priv, "new nrg_th_cck %u\n", data->nrg_th_cck);
-
-	data->nrg_prev_state = data->nrg_curr_state;
-
-	/* Auto-correlation CCK algorithm */
-	if (false_alarms > min_false_alarms) {
-
-		/* increase auto_corr values to decrease sensitivity
-		 * so the DSP won't be disturbed by the noise
-		 */
-		if (data->auto_corr_cck < AUTO_CORR_MAX_TH_CCK)
-			data->auto_corr_cck = AUTO_CORR_MAX_TH_CCK + 1;
-		else {
-			val = data->auto_corr_cck + AUTO_CORR_STEP_CCK;
-			data->auto_corr_cck =
-				min((u32)ranges->auto_corr_max_cck, val);
-		}
-		val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK;
-		data->auto_corr_cck_mrc =
-			min((u32)ranges->auto_corr_max_cck_mrc, val);
-	} else if ((false_alarms < min_false_alarms) &&
-	   ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
-	   (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
-
-		/* Decrease auto_corr values to increase sensitivity */
-		val = data->auto_corr_cck - AUTO_CORR_STEP_CCK;
-		data->auto_corr_cck =
-			max((u32)ranges->auto_corr_min_cck, val);
-		val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK;
-		data->auto_corr_cck_mrc =
-			max((u32)ranges->auto_corr_min_cck_mrc, val);
-	}
-
-	return 0;
-}
-
-
-static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv,
-				       u32 norm_fa,
-				       u32 rx_enable_time)
-{
-	u32 val;
-	u32 false_alarms = norm_fa * 200 * 1024;
-	u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
-	u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
-	struct iwl_sensitivity_data *data = NULL;
-	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
-
-	data = &(priv->sensitivity_data);
-
-	/* If we got too many false alarms this time, reduce sensitivity */
-	if (false_alarms > max_false_alarms) {
-
-		IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u)\n",
-			     false_alarms, max_false_alarms);
-
-		val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM;
-		data->auto_corr_ofdm =
-			min((u32)ranges->auto_corr_max_ofdm, val);
-
-		val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM;
-		data->auto_corr_ofdm_mrc =
-			min((u32)ranges->auto_corr_max_ofdm_mrc, val);
-
-		val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM;
-		data->auto_corr_ofdm_x1 =
-			min((u32)ranges->auto_corr_max_ofdm_x1, val);
-
-		val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM;
-		data->auto_corr_ofdm_mrc_x1 =
-			min((u32)ranges->auto_corr_max_ofdm_mrc_x1, val);
-	}
-
-	/* Else if we got fewer than desired, increase sensitivity */
-	else if (false_alarms < min_false_alarms) {
-
-		IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u\n",
-			     false_alarms, min_false_alarms);
-
-		val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM;
-		data->auto_corr_ofdm =
-			max((u32)ranges->auto_corr_min_ofdm, val);
-
-		val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM;
-		data->auto_corr_ofdm_mrc =
-			max((u32)ranges->auto_corr_min_ofdm_mrc, val);
-
-		val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM;
-		data->auto_corr_ofdm_x1 =
-			max((u32)ranges->auto_corr_min_ofdm_x1, val);
-
-		val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM;
-		data->auto_corr_ofdm_mrc_x1 =
-			max((u32)ranges->auto_corr_min_ofdm_mrc_x1, val);
-	} else {
-		IWL_DEBUG_CALIB(priv, "min FA %u < norm FA %u < max FA %u OK\n",
-			 min_false_alarms, false_alarms, max_false_alarms);
-	}
-	return 0;
-}
-
-/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
-static int iwl_sensitivity_write(struct iwl_priv *priv)
-{
-	struct iwl_sensitivity_cmd cmd ;
-	struct iwl_sensitivity_data *data = NULL;
-	struct iwl_host_cmd cmd_out = {
-		.id = SENSITIVITY_CMD,
-		.len = sizeof(struct iwl_sensitivity_cmd),
-		.flags = CMD_ASYNC,
-		.data = &cmd,
-	};
-
-	data = &(priv->sensitivity_data);
-
-	memset(&cmd, 0, sizeof(cmd));
-
-	cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
-				cpu_to_le16((u16)data->auto_corr_ofdm);
-	cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
-				cpu_to_le16((u16)data->auto_corr_ofdm_mrc);
-	cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
-				cpu_to_le16((u16)data->auto_corr_ofdm_x1);
-	cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
-				cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1);
-
-	cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
-				cpu_to_le16((u16)data->auto_corr_cck);
-	cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
-				cpu_to_le16((u16)data->auto_corr_cck_mrc);
-
-	cmd.table[HD_MIN_ENERGY_CCK_DET_INDEX] =
-				cpu_to_le16((u16)data->nrg_th_cck);
-	cmd.table[HD_MIN_ENERGY_OFDM_DET_INDEX] =
-				cpu_to_le16((u16)data->nrg_th_ofdm);
-
-	cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
-				cpu_to_le16(data->barker_corr_th_min);
-	cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
-				cpu_to_le16(data->barker_corr_th_min_mrc);
-	cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] =
-				cpu_to_le16(data->nrg_th_cca);
-
-	IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
-			data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
-			data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
-			data->nrg_th_ofdm);
-
-	IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n",
-			data->auto_corr_cck, data->auto_corr_cck_mrc,
-			data->nrg_th_cck);
-
-	/* Update uCode's "work" table, and copy it to DSP */
-	cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
-
-	/* Don't send command to uCode if nothing has changed */
-	if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]),
-		    sizeof(u16)*HD_TABLE_SIZE)) {
-		IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n");
-		return 0;
-	}
-
-	/* Copy table for comparison next time */
-	memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
-	       sizeof(u16)*HD_TABLE_SIZE);
-
-	return iwl_send_cmd(priv, &cmd_out);
-}
-
-void iwl_init_sensitivity(struct iwl_priv *priv)
-{
-	int ret = 0;
-	int i;
-	struct iwl_sensitivity_data *data = NULL;
-	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
-
-	if (priv->disable_sens_cal)
-		return;
-
-	IWL_DEBUG_CALIB(priv, "Start iwl_init_sensitivity\n");
-
-	/* Clear driver's sensitivity algo data */
-	data = &(priv->sensitivity_data);
-
-	if (ranges == NULL)
-		return;
-
-	memset(data, 0, sizeof(struct iwl_sensitivity_data));
-
-	data->num_in_cck_no_fa = 0;
-	data->nrg_curr_state = IWL_FA_TOO_MANY;
-	data->nrg_prev_state = IWL_FA_TOO_MANY;
-	data->nrg_silence_ref = 0;
-	data->nrg_silence_idx = 0;
-	data->nrg_energy_idx = 0;
-
-	for (i = 0; i < 10; i++)
-		data->nrg_value[i] = 0;
-
-	for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
-		data->nrg_silence_rssi[i] = 0;
-
-	data->auto_corr_ofdm =  ranges->auto_corr_min_ofdm;
-	data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc;
-	data->auto_corr_ofdm_x1  = ranges->auto_corr_min_ofdm_x1;
-	data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1;
-	data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF;
-	data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc;
-	data->nrg_th_cck = ranges->nrg_th_cck;
-	data->nrg_th_ofdm = ranges->nrg_th_ofdm;
-	data->barker_corr_th_min = ranges->barker_corr_th_min;
-	data->barker_corr_th_min_mrc = ranges->barker_corr_th_min_mrc;
-	data->nrg_th_cca = ranges->nrg_th_cca;
-
-	data->last_bad_plcp_cnt_ofdm = 0;
-	data->last_fa_cnt_ofdm = 0;
-	data->last_bad_plcp_cnt_cck = 0;
-	data->last_fa_cnt_cck = 0;
-
-	ret |= iwl_sensitivity_write(priv);
-	IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
-}
-EXPORT_SYMBOL(iwl_init_sensitivity);
-
-void iwl_sensitivity_calibration(struct iwl_priv *priv,
-				    struct iwl_notif_statistics *resp)
-{
-	u32 rx_enable_time;
-	u32 fa_cck;
-	u32 fa_ofdm;
-	u32 bad_plcp_cck;
-	u32 bad_plcp_ofdm;
-	u32 norm_fa_ofdm;
-	u32 norm_fa_cck;
-	struct iwl_sensitivity_data *data = NULL;
-	struct statistics_rx_non_phy *rx_info = &(resp->rx.general);
-	struct statistics_rx *statistics = &(resp->rx);
-	unsigned long flags;
-	struct statistics_general_data statis;
-
-	if (priv->disable_sens_cal)
-		return;
-
-	data = &(priv->sensitivity_data);
-
-	if (!iwl_is_associated(priv)) {
-		IWL_DEBUG_CALIB(priv, "<< - not associated\n");
-		return;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
-		IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return;
-	}
-
-	/* Extract Statistics: */
-	rx_enable_time = le32_to_cpu(rx_info->channel_load);
-	fa_cck = le32_to_cpu(statistics->cck.false_alarm_cnt);
-	fa_ofdm = le32_to_cpu(statistics->ofdm.false_alarm_cnt);
-	bad_plcp_cck = le32_to_cpu(statistics->cck.plcp_err);
-	bad_plcp_ofdm = le32_to_cpu(statistics->ofdm.plcp_err);
-
-	statis.beacon_silence_rssi_a =
-			le32_to_cpu(statistics->general.beacon_silence_rssi_a);
-	statis.beacon_silence_rssi_b =
-			le32_to_cpu(statistics->general.beacon_silence_rssi_b);
-	statis.beacon_silence_rssi_c =
-			le32_to_cpu(statistics->general.beacon_silence_rssi_c);
-	statis.beacon_energy_a =
-			le32_to_cpu(statistics->general.beacon_energy_a);
-	statis.beacon_energy_b =
-			le32_to_cpu(statistics->general.beacon_energy_b);
-	statis.beacon_energy_c =
-			le32_to_cpu(statistics->general.beacon_energy_c);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
-
-	if (!rx_enable_time) {
-		IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n");
-		return;
-	}
-
-	/* These statistics increase monotonically, and do not reset
-	 *   at each beacon.  Calculate difference from last value, or just
-	 *   use the new statistics value if it has reset or wrapped around. */
-	if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
-		data->last_bad_plcp_cnt_cck = bad_plcp_cck;
-	else {
-		bad_plcp_cck -= data->last_bad_plcp_cnt_cck;
-		data->last_bad_plcp_cnt_cck += bad_plcp_cck;
-	}
-
-	if (data->last_bad_plcp_cnt_ofdm > bad_plcp_ofdm)
-		data->last_bad_plcp_cnt_ofdm = bad_plcp_ofdm;
-	else {
-		bad_plcp_ofdm -= data->last_bad_plcp_cnt_ofdm;
-		data->last_bad_plcp_cnt_ofdm += bad_plcp_ofdm;
-	}
-
-	if (data->last_fa_cnt_ofdm > fa_ofdm)
-		data->last_fa_cnt_ofdm = fa_ofdm;
-	else {
-		fa_ofdm -= data->last_fa_cnt_ofdm;
-		data->last_fa_cnt_ofdm += fa_ofdm;
-	}
-
-	if (data->last_fa_cnt_cck > fa_cck)
-		data->last_fa_cnt_cck = fa_cck;
-	else {
-		fa_cck -= data->last_fa_cnt_cck;
-		data->last_fa_cnt_cck += fa_cck;
-	}
-
-	/* Total aborted signal locks */
-	norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm;
-	norm_fa_cck = fa_cck + bad_plcp_cck;
-
-	IWL_DEBUG_CALIB(priv, "cck: fa %u badp %u  ofdm: fa %u badp %u\n", fa_cck,
-			bad_plcp_cck, fa_ofdm, bad_plcp_ofdm);
-
-	iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
-	iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
-	iwl_sensitivity_write(priv);
-}
-EXPORT_SYMBOL(iwl_sensitivity_calibration);
-
-static inline u8 find_first_chain(u8 mask)
-{
-	if (mask & ANT_A)
-		return CHAIN_A;
-	if (mask & ANT_B)
-		return CHAIN_B;
-	return CHAIN_C;
-}
-
-/*
- * Accumulate 20 beacons of signal and noise statistics for each of
- *   3 receivers/antennas/rx-chains, then figure out:
- * 1)  Which antennas are connected.
- * 2)  Differential rx gain settings to balance the 3 receivers.
- */
-void iwl_chain_noise_calibration(struct iwl_priv *priv,
-				 struct iwl_notif_statistics *stat_resp)
-{
-	struct iwl_chain_noise_data *data = NULL;
-
-	u32 chain_noise_a;
-	u32 chain_noise_b;
-	u32 chain_noise_c;
-	u32 chain_sig_a;
-	u32 chain_sig_b;
-	u32 chain_sig_c;
-	u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
-	u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
-	u32 max_average_sig;
-	u16 max_average_sig_antenna_i;
-	u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
-	u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
-	u16 i = 0;
-	u16 rxon_chnum = INITIALIZATION_VALUE;
-	u16 stat_chnum = INITIALIZATION_VALUE;
-	u8 rxon_band24;
-	u8 stat_band24;
-	u32 active_chains = 0;
-	u8 num_tx_chains;
-	unsigned long flags;
-	struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general);
-	u8 first_chain;
-
-	if (priv->disable_chain_noise_cal)
-		return;
-
-	data = &(priv->chain_noise_data);
-
-	/*
-	 * Accumulate just the first "chain_noise_num_beacons" after
-	 * the first association, then we're done forever.
-	 */
-	if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) {
-		if (data->state == IWL_CHAIN_NOISE_ALIVE)
-			IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n");
-		return;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
-		IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return;
-	}
-
-	rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK);
-	rxon_chnum = le16_to_cpu(priv->staging_rxon.channel);
-	stat_band24 = !!(stat_resp->flag & STATISTICS_REPLY_FLG_BAND_24G_MSK);
-	stat_chnum = le32_to_cpu(stat_resp->flag) >> 16;
-
-	/* Make sure we accumulate data for just the associated channel
-	 *   (even if scanning). */
-	if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
-		IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
-				rxon_chnum, rxon_band24);
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return;
-	}
-
-	/*
-	 *  Accumulate beacon statistics values across
-	 * "chain_noise_num_beacons"
-	 */
-	chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) &
-				IN_BAND_FILTER;
-	chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) &
-				IN_BAND_FILTER;
-	chain_noise_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) &
-				IN_BAND_FILTER;
-
-	chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER;
-	chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
-	chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	data->beacon_count++;
-
-	data->chain_noise_a = (chain_noise_a + data->chain_noise_a);
-	data->chain_noise_b = (chain_noise_b + data->chain_noise_b);
-	data->chain_noise_c = (chain_noise_c + data->chain_noise_c);
-
-	data->chain_signal_a = (chain_sig_a + data->chain_signal_a);
-	data->chain_signal_b = (chain_sig_b + data->chain_signal_b);
-	data->chain_signal_c = (chain_sig_c + data->chain_signal_c);
-
-	IWL_DEBUG_CALIB(priv, "chan=%d, band24=%d, beacon=%d\n",
-			rxon_chnum, rxon_band24, data->beacon_count);
-	IWL_DEBUG_CALIB(priv, "chain_sig: a %d b %d c %d\n",
-			chain_sig_a, chain_sig_b, chain_sig_c);
-	IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n",
-			chain_noise_a, chain_noise_b, chain_noise_c);
-
-	/* If this is the "chain_noise_num_beacons", determine:
-	 * 1)  Disconnected antennas (using signal strengths)
-	 * 2)  Differential gain (using silence noise) to balance receivers */
-	if (data->beacon_count != priv->cfg->chain_noise_num_beacons)
-		return;
-
-	/* Analyze signal for disconnected antenna */
-	average_sig[0] =
-		(data->chain_signal_a) / priv->cfg->chain_noise_num_beacons;
-	average_sig[1] =
-		(data->chain_signal_b) / priv->cfg->chain_noise_num_beacons;
-	average_sig[2] =
-		(data->chain_signal_c) / priv->cfg->chain_noise_num_beacons;
-
-	if (average_sig[0] >= average_sig[1]) {
-		max_average_sig = average_sig[0];
-		max_average_sig_antenna_i = 0;
-		active_chains = (1 << max_average_sig_antenna_i);
-	} else {
-		max_average_sig = average_sig[1];
-		max_average_sig_antenna_i = 1;
-		active_chains = (1 << max_average_sig_antenna_i);
-	}
-
-	if (average_sig[2] >= max_average_sig) {
-		max_average_sig = average_sig[2];
-		max_average_sig_antenna_i = 2;
-		active_chains = (1 << max_average_sig_antenna_i);
-	}
-
-	IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
-		     average_sig[0], average_sig[1], average_sig[2]);
-	IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
-		     max_average_sig, max_average_sig_antenna_i);
-
-	/* Compare signal strengths for all 3 receivers. */
-	for (i = 0; i < NUM_RX_CHAINS; i++) {
-		if (i != max_average_sig_antenna_i) {
-			s32 rssi_delta = (max_average_sig - average_sig[i]);
-
-			/* If signal is very weak, compared with
-			 * strongest, mark it as disconnected. */
-			if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
-				data->disconn_array[i] = 1;
-			else
-				active_chains |= (1 << i);
-			IWL_DEBUG_CALIB(priv, "i = %d  rssiDelta = %d  "
-			     "disconn_array[i] = %d\n",
-			     i, rssi_delta, data->disconn_array[i]);
-		}
-	}
-
-	/*
-	 * The above algorithm sometimes fails when the ucode
-	 * reports 0 for all chains. It's not clear why that
-	 * happens to start with, but it is then causing trouble
-	 * because this can make us enable more chains than the
-	 * hardware really has.
-	 *
-	 * To be safe, simply mask out any chains that we know
-	 * are not on the device.
-	 */
-	active_chains &= priv->hw_params.valid_rx_ant;
-
-	num_tx_chains = 0;
-	for (i = 0; i < NUM_RX_CHAINS; i++) {
-		/* loops on all the bits of
-		 * priv->hw_setting.valid_tx_ant */
-		u8 ant_msk = (1 << i);
-		if (!(priv->hw_params.valid_tx_ant & ant_msk))
-			continue;
-
-		num_tx_chains++;
-		if (data->disconn_array[i] == 0)
-			/* there is a Tx antenna connected */
-			break;
-		if (num_tx_chains == priv->hw_params.tx_chains_num &&
-		    data->disconn_array[i]) {
-			/*
-			 * If all chains are disconnected
-			 * connect the first valid tx chain
-			 */
-			first_chain =
-				find_first_chain(priv->cfg->valid_tx_ant);
-			data->disconn_array[first_chain] = 0;
-			active_chains |= BIT(first_chain);
-			IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n",
-					first_chain);
-			break;
-		}
-	}
-
-	if (active_chains != priv->hw_params.valid_rx_ant &&
-	    active_chains != priv->chain_noise_data.active_chains)
-		IWL_WARN(priv,
-			 "Detected that not all antennas are connected! "
-			 "Connected: %#x, valid: %#x.\n",
-			 active_chains, priv->hw_params.valid_rx_ant);
-
-	/* Save for use within RXON, TX, SCAN commands, etc. */
-	priv->chain_noise_data.active_chains = active_chains;
-	IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
-			active_chains);
-
-	/* Analyze noise for rx balance */
-	average_noise[0] =
-		((data->chain_noise_a) / priv->cfg->chain_noise_num_beacons);
-	average_noise[1] =
-		((data->chain_noise_b) / priv->cfg->chain_noise_num_beacons);
-	average_noise[2] =
-		((data->chain_noise_c) / priv->cfg->chain_noise_num_beacons);
-
-	for (i = 0; i < NUM_RX_CHAINS; i++) {
-		if (!(data->disconn_array[i]) &&
-		   (average_noise[i] <= min_average_noise)) {
-			/* This means that chain i is active and has
-			 * lower noise values so far: */
-			min_average_noise = average_noise[i];
-			min_average_noise_antenna_i = i;
-		}
-	}
-
-	IWL_DEBUG_CALIB(priv, "average_noise: a %d b %d c %d\n",
-			average_noise[0], average_noise[1],
-			average_noise[2]);
-
-	IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
-			min_average_noise, min_average_noise_antenna_i);
-
-	if (priv->cfg->ops->utils->gain_computation)
-		priv->cfg->ops->utils->gain_computation(priv, average_noise,
-				min_average_noise_antenna_i, min_average_noise,
-				find_first_chain(priv->cfg->valid_rx_ant));
-
-	/* Some power changes may have been made during the calibration.
-	 * Update and commit the RXON
-	 */
-	if (priv->cfg->ops->lib->update_chain_flags)
-		priv->cfg->ops->lib->update_chain_flags(priv);
-
-	data->state = IWL_CHAIN_NOISE_DONE;
-	iwl_power_update_mode(priv, false);
-}
-EXPORT_SYMBOL(iwl_chain_noise_calibration);
-
-
-void iwl_reset_run_time_calib(struct iwl_priv *priv)
-{
-	int i;
-	memset(&(priv->sensitivity_data), 0,
-	       sizeof(struct iwl_sensitivity_data));
-	memset(&(priv->chain_noise_data), 0,
-	       sizeof(struct iwl_chain_noise_data));
-	for (i = 0; i < NUM_RX_CHAINS; i++)
-		priv->chain_noise_data.delta_gain_code[i] =
-				CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
-
-	/* Ask for statistics now, the uCode will send notification
-	 * periodically after association */
-	iwl_send_statistics_request(priv, CMD_ASYNC, true);
-}
-EXPORT_SYMBOL(iwl_reset_run_time_calib);
-
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 8/9] iwlwifi: code cleanup to remove un-necessary "goto"
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1277143600-32554-1-git-send-email-reinette.chatre@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Break out of loop and log the error message when encounter error; this is
better approach than using "goto".

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-calib.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index d03b5e5..400eb31 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -96,14 +96,14 @@ int iwl_send_calib_results(struct iwl_priv *priv)
 			hcmd.len = priv->calib_results[i].buf_len;
 			hcmd.data = priv->calib_results[i].buf;
 			ret = iwl_send_cmd_sync(priv, &hcmd);
-			if (ret)
-				goto err;
+			if (ret) {
+				IWL_ERR(priv, "Error %d iteration %d\n",
+					ret, i);
+				break;
+			}
 		}
 	}
 
-	return 0;
-err:
-	IWL_ERR(priv, "Error %d iteration %d\n", ret, i);
 	return ret;
 }
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 6/9] iwlwifi: move _agn statistics related structure
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1277143600-32554-1-git-send-email-reinette.chatre@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

agn and 3945 has different statistics_notif data structure; since 3945
has it statistics_notif data structure inside the _3945 portion of
iwl_priv, it make sense to move the agn statistics_notif into _agn
portion.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-4965.c        |    7 +-
 drivers/net/wireless/iwlwifi/iwl-5000.c        |    2 +-
 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c |   72 ++++++++++++------------
 drivers/net/wireless/iwlwifi/iwl-agn-lib.c     |    3 +-
 drivers/net/wireless/iwlwifi/iwl-agn-rx.c      |   58 ++++++++++----------
 drivers/net/wireless/iwlwifi/iwl-agn.c         |   14 ++--
 drivers/net/wireless/iwlwifi/iwl-dev.h         |   14 ++--
 7 files changed, 86 insertions(+), 84 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index fee276b..67526a1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1580,7 +1580,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
 	u32 R4;
 
 	if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
-		(priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
+	    (priv->_agn.statistics.flag &
+			STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
 		IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
 		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
 		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
@@ -1604,8 +1605,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
 	if (!test_bit(STATUS_TEMPERATURE, &priv->status))
 		vt = sign_extend(R4, 23);
 	else
-		vt = sign_extend(
-			le32_to_cpu(priv->statistics.general.temperature), 23);
+		vt = sign_extend(le32_to_cpu(
+				priv->_agn.statistics.general.temperature), 23);
 
 	IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 32710a8..c6ccc25 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -264,7 +264,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)
 	u32 vt = 0;
 	s32 offset =  iwl_temp_calib_to_offset(priv);
 
-	vt = le32_to_cpu(priv->statistics.general.temperature);
+	vt = le32_to_cpu(priv->_agn.statistics.general.temperature);
 	vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
 	/* now vt hold the temperature in Kelvin */
 	priv->temperature = KELVIN_TO_CELSIUS(vt);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
index 3d08dc8..75d6bfc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
@@ -33,17 +33,17 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
 	int p = 0;
 
 	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
-		       le32_to_cpu(priv->statistics.flag));
-	if (le32_to_cpu(priv->statistics.flag) &
+		       le32_to_cpu(priv->_agn.statistics.flag));
+	if (le32_to_cpu(priv->_agn.statistics.flag) &
 			UCODE_STATISTICS_CLEAR_MSK)
 		p += scnprintf(buf + p, bufsz - p,
 			       "\tStatistics have been cleared\n");
 	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
-		       (le32_to_cpu(priv->statistics.flag) &
+		       (le32_to_cpu(priv->_agn.statistics.flag) &
 			UCODE_STATISTICS_FREQUENCY_MSK)
 			? "2.4 GHz" : "5.2 GHz");
 	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
-		       (le32_to_cpu(priv->statistics.flag) &
+		       (le32_to_cpu(priv->_agn.statistics.flag) &
 			UCODE_STATISTICS_NARROW_BAND_MSK)
 			? "enabled" : "disabled");
 	return p;
@@ -79,22 +79,22 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
 	 * the last statistics notification from uCode
 	 * might not reflect the current uCode activity
 	 */
-	ofdm = &priv->statistics.rx.ofdm;
-	cck = &priv->statistics.rx.cck;
-	general = &priv->statistics.rx.general;
-	ht = &priv->statistics.rx.ofdm_ht;
-	accum_ofdm = &priv->accum_statistics.rx.ofdm;
-	accum_cck = &priv->accum_statistics.rx.cck;
-	accum_general = &priv->accum_statistics.rx.general;
-	accum_ht = &priv->accum_statistics.rx.ofdm_ht;
-	delta_ofdm = &priv->delta_statistics.rx.ofdm;
-	delta_cck = &priv->delta_statistics.rx.cck;
-	delta_general = &priv->delta_statistics.rx.general;
-	delta_ht = &priv->delta_statistics.rx.ofdm_ht;
-	max_ofdm = &priv->max_delta.rx.ofdm;
-	max_cck = &priv->max_delta.rx.cck;
-	max_general = &priv->max_delta.rx.general;
-	max_ht = &priv->max_delta.rx.ofdm_ht;
+	ofdm = &priv->_agn.statistics.rx.ofdm;
+	cck = &priv->_agn.statistics.rx.cck;
+	general = &priv->_agn.statistics.rx.general;
+	ht = &priv->_agn.statistics.rx.ofdm_ht;
+	accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm;
+	accum_cck = &priv->_agn.accum_statistics.rx.cck;
+	accum_general = &priv->_agn.accum_statistics.rx.general;
+	accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht;
+	delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm;
+	delta_cck = &priv->_agn.delta_statistics.rx.cck;
+	delta_general = &priv->_agn.delta_statistics.rx.general;
+	delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht;
+	max_ofdm = &priv->_agn.max_delta.rx.ofdm;
+	max_cck = &priv->_agn.max_delta.rx.cck;
+	max_general = &priv->_agn.max_delta.rx.general;
+	max_ht = &priv->_agn.max_delta.rx.ofdm_ht;
 
 	pos += iwl_statistics_flag(priv, buf, bufsz);
 	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
@@ -560,10 +560,10 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	tx = &priv->statistics.tx;
-	accum_tx = &priv->accum_statistics.tx;
-	delta_tx = &priv->delta_statistics.tx;
-	max_tx = &priv->max_delta.tx;
+	tx = &priv->_agn.statistics.tx;
+	accum_tx = &priv->_agn.accum_statistics.tx;
+	delta_tx = &priv->_agn.delta_statistics.tx;
+	max_tx = &priv->_agn.max_delta.tx;
 	pos += iwl_statistics_flag(priv, buf, bufsz);
 	pos += scnprintf(buf + pos, bufsz - pos,  "%-32s     current"
 			 "acumulative       delta         max\n",
@@ -777,18 +777,18 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	general = &priv->statistics.general;
-	dbg = &priv->statistics.general.dbg;
-	div = &priv->statistics.general.div;
-	accum_general = &priv->accum_statistics.general;
-	delta_general = &priv->delta_statistics.general;
-	max_general = &priv->max_delta.general;
-	accum_dbg = &priv->accum_statistics.general.dbg;
-	delta_dbg = &priv->delta_statistics.general.dbg;
-	max_dbg = &priv->max_delta.general.dbg;
-	accum_div = &priv->accum_statistics.general.div;
-	delta_div = &priv->delta_statistics.general.div;
-	max_div = &priv->max_delta.general.div;
+	general = &priv->_agn.statistics.general;
+	dbg = &priv->_agn.statistics.general.dbg;
+	div = &priv->_agn.statistics.general.div;
+	accum_general = &priv->_agn.accum_statistics.general;
+	delta_general = &priv->_agn.delta_statistics.general;
+	max_general = &priv->_agn.max_delta.general;
+	accum_dbg = &priv->_agn.accum_statistics.general.dbg;
+	delta_dbg = &priv->_agn.delta_statistics.general.dbg;
+	max_dbg = &priv->_agn.max_delta.general.dbg;
+	accum_div = &priv->_agn.accum_statistics.general.div;
+	delta_div = &priv->_agn.delta_statistics.general.div;
+	max_div = &priv->_agn.max_delta.general.div;
 	pos += iwl_statistics_flag(priv, buf, bufsz);
 	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
 			 "acumulative       delta         max\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 0e7b066..5f1e7d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -361,7 +361,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
 void iwlagn_temperature(struct iwl_priv *priv)
 {
 	/* store temperature from statistics (in Celsius) */
-	priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
+	priv->temperature =
+		le32_to_cpu(priv->_agn.statistics.general.temperature);
 	iwl_tt_handler(priv);
 }
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 20343b1..ad2bead 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -68,7 +68,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
 static void iwl_rx_calc_noise(struct iwl_priv *priv)
 {
 	struct statistics_rx_non_phy *rx_info
-				= &(priv->statistics.rx.general);
+				= &(priv->_agn.statistics.rx.general);
 	int num_active_rx = 0;
 	int total_silence = 0;
 	int bcn_silence_a =
@@ -117,10 +117,10 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
 	u32 *accum_stats;
 	u32 *delta, *max_delta;
 
-	prev_stats = (__le32 *)&priv->statistics;
-	accum_stats = (u32 *)&priv->accum_statistics;
-	delta = (u32 *)&priv->delta_statistics;
-	max_delta = (u32 *)&priv->max_delta;
+	prev_stats = (__le32 *)&priv->_agn.statistics;
+	accum_stats = (u32 *)&priv->_agn.accum_statistics;
+	delta = (u32 *)&priv->_agn.delta_statistics;
+	max_delta = (u32 *)&priv->_agn.max_delta;
 
 	for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
 	     i += sizeof(__le32), stats++, prev_stats++, delta++,
@@ -135,18 +135,18 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
 	}
 
 	/* reset accumulative statistics for "no-counter" type statistics */
-	priv->accum_statistics.general.temperature =
-		priv->statistics.general.temperature;
-	priv->accum_statistics.general.temperature_m =
-		priv->statistics.general.temperature_m;
-	priv->accum_statistics.general.ttl_timestamp =
-		priv->statistics.general.ttl_timestamp;
-	priv->accum_statistics.tx.tx_power.ant_a =
-		priv->statistics.tx.tx_power.ant_a;
-	priv->accum_statistics.tx.tx_power.ant_b =
-		priv->statistics.tx.tx_power.ant_b;
-	priv->accum_statistics.tx.tx_power.ant_c =
-		priv->statistics.tx.tx_power.ant_c;
+	priv->_agn.accum_statistics.general.temperature =
+		priv->_agn.statistics.general.temperature;
+	priv->_agn.accum_statistics.general.temperature_m =
+		priv->_agn.statistics.general.temperature_m;
+	priv->_agn.accum_statistics.general.ttl_timestamp =
+		priv->_agn.statistics.general.ttl_timestamp;
+	priv->_agn.accum_statistics.tx.tx_power.ant_a =
+		priv->_agn.statistics.tx.tx_power.ant_a;
+	priv->_agn.accum_statistics.tx.tx_power.ant_b =
+		priv->_agn.statistics.tx.tx_power.ant_b;
+	priv->_agn.accum_statistics.tx.tx_power.ant_c =
+		priv->_agn.statistics.tx.tx_power.ant_c;
 }
 #endif
 
@@ -181,9 +181,9 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
 	if (plcp_msec) {
 		combined_plcp_delta =
 			(le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
-			le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
+			le32_to_cpu(priv->_agn.statistics.rx.ofdm.plcp_err)) +
 			(le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
-			le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
+			le32_to_cpu(priv->_agn.statistics.rx.ofdm_ht.plcp_err));
 
 		if ((combined_plcp_delta > 0) &&
 		    ((combined_plcp_delta * 100) / plcp_msec) >
@@ -204,10 +204,10 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
 				priv->cfg->plcp_delta_threshold,
 				le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
 				le32_to_cpu(
-				       priv->statistics.rx.ofdm.plcp_err),
+				       priv->_agn.statistics.rx.ofdm.plcp_err),
 				le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
 				le32_to_cpu(
-				  priv->statistics.rx.ofdm_ht.plcp_err),
+				  priv->_agn.statistics.rx.ofdm_ht.plcp_err),
 				combined_plcp_delta, plcp_msec);
 			rc = false;
 		}
@@ -223,12 +223,12 @@ void iwl_rx_statistics(struct iwl_priv *priv,
 
 
 	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
-		     (int)sizeof(priv->statistics),
+		     (int)sizeof(priv->_agn.statistics),
 		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
 
-	change = ((priv->statistics.general.temperature !=
+	change = ((priv->_agn.statistics.general.temperature !=
 		   pkt->u.stats.general.temperature) ||
-		  ((priv->statistics.flag &
+		  ((priv->_agn.statistics.flag &
 		    STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
 		   (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
 
@@ -237,8 +237,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
 #endif
 	iwl_recover_from_statistics(priv, pkt);
 
-	memcpy(&priv->statistics, &pkt->u.stats,
-	       sizeof(priv->statistics));
+	memcpy(&priv->_agn.statistics, &pkt->u.stats,
+	       sizeof(priv->_agn.statistics));
 
 	set_bit(STATUS_STATISTICS, &priv->status);
 
@@ -265,11 +265,11 @@ void iwl_reply_statistics(struct iwl_priv *priv,
 
 	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-		memset(&priv->accum_statistics, 0,
+		memset(&priv->_agn.accum_statistics, 0,
 			sizeof(struct iwl_notif_statistics));
-		memset(&priv->delta_statistics, 0,
+		memset(&priv->_agn.delta_statistics, 0,
 			sizeof(struct iwl_notif_statistics));
-		memset(&priv->max_delta, 0,
+		memset(&priv->_agn.max_delta, 0,
 			sizeof(struct iwl_notif_statistics));
 #endif
 		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index fd245c4..7488a68 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1461,13 +1461,13 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
 
 	actual_ack_cnt_delta =
 		le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
-		le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
+		le32_to_cpu(priv->_agn.statistics.tx.actual_ack_cnt);
 	expected_ack_cnt_delta =
 		le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
-		le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
+		le32_to_cpu(priv->_agn.statistics.tx.expected_ack_cnt);
 	ba_timeout_delta =
 		le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
-		le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
+		le32_to_cpu(priv->_agn.statistics.tx.agg.ba_timeout);
 	if ((priv->_agn.agg_tids_count > 0) &&
 	    (expected_ack_cnt_delta > 0) &&
 	    (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta)
@@ -1484,10 +1484,10 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
 		 * DEBUG is not, these will just compile out.
 		 */
 		IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
-				priv->delta_statistics.tx.rx_detected_cnt);
+				priv->_agn.delta_statistics.tx.rx_detected_cnt);
 		IWL_DEBUG_RADIO(priv,
 				"ack_or_ba_timeout_collision delta = %d\n",
-				priv->delta_statistics.tx.
+				priv->_agn.delta_statistics.tx.
 				ack_or_ba_timeout_collision);
 #endif
 		IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
@@ -2935,9 +2935,9 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
 	}
 
 	if (priv->start_calib) {
-		iwl_chain_noise_calibration(priv, &priv->statistics);
+		iwl_chain_noise_calibration(priv, &priv->_agn.statistics);
 
-		iwl_sensitivity_calibration(priv, &priv->statistics);
+		iwl_sensitivity_calibration(priv, &priv->_agn.statistics);
 	}
 
 	mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index da54e6c..1af845c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1224,13 +1224,6 @@ struct iwl_priv {
 	struct iwl_power_mgr power_data;
 	struct iwl_tt_mgmt thermal_throttle;
 
-	struct iwl_notif_statistics statistics;
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	struct iwl_notif_statistics accum_statistics;
-	struct iwl_notif_statistics delta_statistics;
-	struct iwl_notif_statistics max_delta;
-#endif
-
 	/* context information */
 	u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
 
@@ -1323,6 +1316,13 @@ struct iwl_priv {
 
 			u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
 			u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
+
+			struct iwl_notif_statistics statistics;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+			struct iwl_notif_statistics accum_statistics;
+			struct iwl_notif_statistics delta_statistics;
+			struct iwl_notif_statistics max_delta;
+#endif
 		} _agn;
 #endif
 	};
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 5/9] iwlwifi: move agn specific rx related code to iwl-agn-rx.c
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1277143600-32554-1-git-send-email-reinette.chatre@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

To avoid having unnecessary functions in iwlcore.ko, those that
are not shared by agn and 3945, move agn specific rx related code
to iwl-agn-rx.c.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/Makefile     |    2 +-
 drivers/net/wireless/iwlwifi/iwl-agn-rx.c |  278 +++++++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-agn.h    |   10 +
 drivers/net/wireless/iwlwifi/iwl-core.h   |    8 -
 drivers/net/wireless/iwlwifi/iwl-rx.c     |  238 ------------------------
 5 files changed, 289 insertions(+), 247 deletions(-)
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-rx.c

diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 7c72353..9084c52 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -11,7 +11,7 @@ CFLAGS_iwl-devtrace.o := -I$(src)
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o
 iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
 iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
-iwlagn-objs		+= iwl-agn-lib.o
+iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 
 iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
new file mode 100644
index 0000000..20343b1
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -0,0 +1,278 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-calib.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-agn-hw.h"
+#include "iwl-agn.h"
+
+void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_missed_beacon_notif *missed_beacon;
+
+	missed_beacon = &pkt->u.missed_beacon;
+	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
+	    priv->missed_beacon_threshold) {
+		IWL_DEBUG_CALIB(priv,
+		    "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
+		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
+		    le32_to_cpu(missed_beacon->total_missed_becons),
+		    le32_to_cpu(missed_beacon->num_recvd_beacons),
+		    le32_to_cpu(missed_beacon->num_expected_beacons));
+		if (!test_bit(STATUS_SCANNING, &priv->status))
+			iwl_init_sensitivity(priv);
+	}
+}
+
+/* Calculate noise level, based on measurements during network silence just
+ *   before arriving beacon.  This measurement can be done only if we know
+ *   exactly when to expect beacons, therefore only when we're associated. */
+static void iwl_rx_calc_noise(struct iwl_priv *priv)
+{
+	struct statistics_rx_non_phy *rx_info
+				= &(priv->statistics.rx.general);
+	int num_active_rx = 0;
+	int total_silence = 0;
+	int bcn_silence_a =
+		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
+	int bcn_silence_b =
+		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
+	int bcn_silence_c =
+		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
+	int last_rx_noise;
+
+	if (bcn_silence_a) {
+		total_silence += bcn_silence_a;
+		num_active_rx++;
+	}
+	if (bcn_silence_b) {
+		total_silence += bcn_silence_b;
+		num_active_rx++;
+	}
+	if (bcn_silence_c) {
+		total_silence += bcn_silence_c;
+		num_active_rx++;
+	}
+
+	/* Average among active antennas */
+	if (num_active_rx)
+		last_rx_noise = (total_silence / num_active_rx) - 107;
+	else
+		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+
+	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
+			bcn_silence_a, bcn_silence_b, bcn_silence_c,
+			last_rx_noise);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+/*
+ *  based on the assumption of all statistics counter are in DWORD
+ *  FIXME: This function is for debugging, do not deal with
+ *  the case of counters roll-over.
+ */
+static void iwl_accumulative_statistics(struct iwl_priv *priv,
+					__le32 *stats)
+{
+	int i;
+	__le32 *prev_stats;
+	u32 *accum_stats;
+	u32 *delta, *max_delta;
+
+	prev_stats = (__le32 *)&priv->statistics;
+	accum_stats = (u32 *)&priv->accum_statistics;
+	delta = (u32 *)&priv->delta_statistics;
+	max_delta = (u32 *)&priv->max_delta;
+
+	for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
+	     i += sizeof(__le32), stats++, prev_stats++, delta++,
+	     max_delta++, accum_stats++) {
+		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+			*delta = (le32_to_cpu(*stats) -
+				le32_to_cpu(*prev_stats));
+			*accum_stats += *delta;
+			if (*delta > *max_delta)
+				*max_delta = *delta;
+		}
+	}
+
+	/* reset accumulative statistics for "no-counter" type statistics */
+	priv->accum_statistics.general.temperature =
+		priv->statistics.general.temperature;
+	priv->accum_statistics.general.temperature_m =
+		priv->statistics.general.temperature_m;
+	priv->accum_statistics.general.ttl_timestamp =
+		priv->statistics.general.ttl_timestamp;
+	priv->accum_statistics.tx.tx_power.ant_a =
+		priv->statistics.tx.tx_power.ant_a;
+	priv->accum_statistics.tx.tx_power.ant_b =
+		priv->statistics.tx.tx_power.ant_b;
+	priv->accum_statistics.tx.tx_power.ant_c =
+		priv->statistics.tx.tx_power.ant_c;
+}
+#endif
+
+#define REG_RECALIB_PERIOD (60)
+
+/**
+ * iwl_good_plcp_health - checks for plcp error.
+ *
+ * When the plcp error is exceeding the thresholds, reset the radio
+ * to improve the throughput.
+ */
+bool iwl_good_plcp_health(struct iwl_priv *priv,
+				struct iwl_rx_packet *pkt)
+{
+	bool rc = true;
+	int combined_plcp_delta;
+	unsigned int plcp_msec;
+	unsigned long plcp_received_jiffies;
+
+	/*
+	 * check for plcp_err and trigger radio reset if it exceeds
+	 * the plcp error threshold plcp_delta.
+	 */
+	plcp_received_jiffies = jiffies;
+	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
+					(long) priv->plcp_jiffies);
+	priv->plcp_jiffies = plcp_received_jiffies;
+	/*
+	 * check to make sure plcp_msec is not 0 to prevent division
+	 * by zero.
+	 */
+	if (plcp_msec) {
+		combined_plcp_delta =
+			(le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
+			le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
+			(le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
+			le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
+
+		if ((combined_plcp_delta > 0) &&
+		    ((combined_plcp_delta * 100) / plcp_msec) >
+			priv->cfg->plcp_delta_threshold) {
+			/*
+			 * if plcp_err exceed the threshold,
+			 * the following data is printed in csv format:
+			 *    Text: plcp_err exceeded %d,
+			 *    Received ofdm.plcp_err,
+			 *    Current ofdm.plcp_err,
+			 *    Received ofdm_ht.plcp_err,
+			 *    Current ofdm_ht.plcp_err,
+			 *    combined_plcp_delta,
+			 *    plcp_msec
+			 */
+			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
+				"%u, %u, %u, %u, %d, %u mSecs\n",
+				priv->cfg->plcp_delta_threshold,
+				le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
+				le32_to_cpu(
+				       priv->statistics.rx.ofdm.plcp_err),
+				le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
+				le32_to_cpu(
+				  priv->statistics.rx.ofdm_ht.plcp_err),
+				combined_plcp_delta, plcp_msec);
+			rc = false;
+		}
+	}
+	return rc;
+}
+
+void iwl_rx_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	int change;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+
+	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
+		     (int)sizeof(priv->statistics),
+		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
+
+	change = ((priv->statistics.general.temperature !=
+		   pkt->u.stats.general.temperature) ||
+		  ((priv->statistics.flag &
+		    STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+		   (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
+#endif
+	iwl_recover_from_statistics(priv, pkt);
+
+	memcpy(&priv->statistics, &pkt->u.stats,
+	       sizeof(priv->statistics));
+
+	set_bit(STATUS_STATISTICS, &priv->status);
+
+	/* Reschedule the statistics timer to occur in
+	 * REG_RECALIB_PERIOD seconds to ensure we get a
+	 * thermal update even if the uCode doesn't give
+	 * us one */
+	mod_timer(&priv->statistics_periodic, jiffies +
+		  msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
+
+	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
+		iwl_rx_calc_noise(priv);
+		queue_work(priv->workqueue, &priv->run_time_calib_work);
+	}
+	if (priv->cfg->ops->lib->temp_ops.temperature && change)
+		priv->cfg->ops->lib->temp_ops.temperature(priv);
+}
+
+void iwl_reply_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+		memset(&priv->accum_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->delta_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->max_delta, 0,
+			sizeof(struct iwl_notif_statistics));
+#endif
+		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
+	}
+	iwl_rx_statistics(priv, rxb);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 5c32777..be9d298 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -201,6 +201,16 @@ static inline bool iwl_is_tx_success(u32 status)
 	       (status == TX_STATUS_DIRECT_DONE);
 }
 
+/* rx */
+void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb);
+bool iwl_good_plcp_health(struct iwl_priv *priv,
+			  struct iwl_rx_packet *pkt);
+void iwl_rx_statistics(struct iwl_priv *priv,
+		       struct iwl_rx_mem_buffer *rxb);
+void iwl_reply_statistics(struct iwl_priv *priv,
+			  struct iwl_rx_mem_buffer *rxb);
+
 /* scan */
 void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 76288c5..1c09dc8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -455,20 +455,12 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
 int iwl_rx_queue_space(const struct iwl_rx_queue *q);
 void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 /* Handlers */
-void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
-			       struct iwl_rx_mem_buffer *rxb);
 void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 					  struct iwl_rx_mem_buffer *rxb);
-bool iwl_good_plcp_health(struct iwl_priv *priv,
-				 struct iwl_rx_packet *pkt);
 bool iwl_good_ack_health(struct iwl_priv *priv,
 				 struct iwl_rx_packet *pkt);
 void iwl_recover_from_statistics(struct iwl_priv *priv,
 				struct iwl_rx_packet *pkt);
-void iwl_rx_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb);
-void iwl_reply_statistics(struct iwl_priv *priv,
-			  struct iwl_rx_mem_buffer *rxb);
 void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
 void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 86a3537..b437f31 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -205,26 +205,6 @@ err_bd:
 }
 EXPORT_SYMBOL(iwl_rx_queue_alloc);
 
-void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_missed_beacon_notif *missed_beacon;
-
-	missed_beacon = &pkt->u.missed_beacon;
-	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
-	    priv->missed_beacon_threshold) {
-		IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
-		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
-		    le32_to_cpu(missed_beacon->total_missed_becons),
-		    le32_to_cpu(missed_beacon->num_recvd_beacons),
-		    le32_to_cpu(missed_beacon->num_expected_beacons));
-		if (!test_bit(STATUS_SCANNING, &priv->status))
-			iwl_init_sensitivity(priv);
-	}
-}
-EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
 
 void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 					  struct iwl_rx_mem_buffer *rxb)
@@ -243,161 +223,6 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
 
-
-
-/* Calculate noise level, based on measurements during network silence just
- *   before arriving beacon.  This measurement can be done only if we know
- *   exactly when to expect beacons, therefore only when we're associated. */
-static void iwl_rx_calc_noise(struct iwl_priv *priv)
-{
-	struct statistics_rx_non_phy *rx_info
-				= &(priv->statistics.rx.general);
-	int num_active_rx = 0;
-	int total_silence = 0;
-	int bcn_silence_a =
-		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
-	int bcn_silence_b =
-		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
-	int bcn_silence_c =
-		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
-	int last_rx_noise;
-
-	if (bcn_silence_a) {
-		total_silence += bcn_silence_a;
-		num_active_rx++;
-	}
-	if (bcn_silence_b) {
-		total_silence += bcn_silence_b;
-		num_active_rx++;
-	}
-	if (bcn_silence_c) {
-		total_silence += bcn_silence_c;
-		num_active_rx++;
-	}
-
-	/* Average among active antennas */
-	if (num_active_rx)
-		last_rx_noise = (total_silence / num_active_rx) - 107;
-	else
-		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-
-	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
-			bcn_silence_a, bcn_silence_b, bcn_silence_c,
-			last_rx_noise);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-/*
- *  based on the assumption of all statistics counter are in DWORD
- *  FIXME: This function is for debugging, do not deal with
- *  the case of counters roll-over.
- */
-static void iwl_accumulative_statistics(struct iwl_priv *priv,
-					__le32 *stats)
-{
-	int i;
-	__le32 *prev_stats;
-	u32 *accum_stats;
-	u32 *delta, *max_delta;
-
-	prev_stats = (__le32 *)&priv->statistics;
-	accum_stats = (u32 *)&priv->accum_statistics;
-	delta = (u32 *)&priv->delta_statistics;
-	max_delta = (u32 *)&priv->max_delta;
-
-	for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
-	     i += sizeof(__le32), stats++, prev_stats++, delta++,
-	     max_delta++, accum_stats++) {
-		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
-			*delta = (le32_to_cpu(*stats) -
-				le32_to_cpu(*prev_stats));
-			*accum_stats += *delta;
-			if (*delta > *max_delta)
-				*max_delta = *delta;
-		}
-	}
-
-	/* reset accumulative statistics for "no-counter" type statistics */
-	priv->accum_statistics.general.temperature =
-		priv->statistics.general.temperature;
-	priv->accum_statistics.general.temperature_m =
-		priv->statistics.general.temperature_m;
-	priv->accum_statistics.general.ttl_timestamp =
-		priv->statistics.general.ttl_timestamp;
-	priv->accum_statistics.tx.tx_power.ant_a =
-		priv->statistics.tx.tx_power.ant_a;
-	priv->accum_statistics.tx.tx_power.ant_b =
-		priv->statistics.tx.tx_power.ant_b;
-	priv->accum_statistics.tx.tx_power.ant_c =
-		priv->statistics.tx.tx_power.ant_c;
-}
-#endif
-
-#define REG_RECALIB_PERIOD (60)
-
-/**
- * iwl_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-bool iwl_good_plcp_health(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
-{
-	bool rc = true;
-	int combined_plcp_delta;
-	unsigned int plcp_msec;
-	unsigned long plcp_received_jiffies;
-
-	/*
-	 * check for plcp_err and trigger radio reset if it exceeds
-	 * the plcp error threshold plcp_delta.
-	 */
-	plcp_received_jiffies = jiffies;
-	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
-					(long) priv->plcp_jiffies);
-	priv->plcp_jiffies = plcp_received_jiffies;
-	/*
-	 * check to make sure plcp_msec is not 0 to prevent division
-	 * by zero.
-	 */
-	if (plcp_msec) {
-		combined_plcp_delta =
-			(le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
-			le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
-			(le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
-			le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
-
-		if ((combined_plcp_delta > 0) &&
-		    ((combined_plcp_delta * 100) / plcp_msec) >
-			priv->cfg->plcp_delta_threshold) {
-			/*
-			 * if plcp_err exceed the threshold,
-			 * the following data is printed in csv format:
-			 *    Text: plcp_err exceeded %d,
-			 *    Received ofdm.plcp_err,
-			 *    Current ofdm.plcp_err,
-			 *    Received ofdm_ht.plcp_err,
-			 *    Current ofdm_ht.plcp_err,
-			 *    combined_plcp_delta,
-			 *    plcp_msec
-			 */
-			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
-				"%u, %u, %u, %u, %d, %u mSecs\n",
-				priv->cfg->plcp_delta_threshold,
-				le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
-				le32_to_cpu(priv->statistics.rx.ofdm.plcp_err),
-				le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
-				le32_to_cpu(
-				  priv->statistics.rx.ofdm_ht.plcp_err),
-				combined_plcp_delta, plcp_msec);
-			rc = false;
-		}
-	}
-	return rc;
-}
-EXPORT_SYMBOL(iwl_good_plcp_health);
-
 void iwl_recover_from_statistics(struct iwl_priv *priv,
 				struct iwl_rx_packet *pkt)
 {
@@ -431,69 +256,6 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_recover_from_statistics);
 
-void iwl_rx_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	int change;
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-
-	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
-		     (int)sizeof(priv->statistics),
-		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
-
-	change = ((priv->statistics.general.temperature !=
-		   pkt->u.stats.general.temperature) ||
-		  ((priv->statistics.flag &
-		    STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
-		   (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
-#endif
-	iwl_recover_from_statistics(priv, pkt);
-
-	memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
-
-	set_bit(STATUS_STATISTICS, &priv->status);
-
-	/* Reschedule the statistics timer to occur in
-	 * REG_RECALIB_PERIOD seconds to ensure we get a
-	 * thermal update even if the uCode doesn't give
-	 * us one */
-	mod_timer(&priv->statistics_periodic, jiffies +
-		  msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
-
-	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
-	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
-		iwl_rx_calc_noise(priv);
-		queue_work(priv->workqueue, &priv->run_time_calib_work);
-	}
-	if (priv->cfg->ops->lib->temp_ops.temperature && change)
-		priv->cfg->ops->lib->temp_ops.temperature(priv);
-}
-EXPORT_SYMBOL(iwl_rx_statistics);
-
-void iwl_reply_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		memset(&priv->accum_statistics, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->delta_statistics, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->max_delta, 0,
-			sizeof(struct iwl_notif_statistics));
-#endif
-		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
-	}
-	iwl_rx_statistics(priv, rxb);
-}
-EXPORT_SYMBOL(iwl_reply_statistics);
-
 /*
  * returns non-zero if packet should be dropped
  */
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/9] iwlagn: use mutex for aggregation
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1277143600-32554-1-git-send-email-reinette.chatre@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

Now that the ampdu_action callback can sleep,
we can use the mutex to properly protect the
aggregation data, and return useful errors if
they should happen.

Also, add some sleep and mutex debugging so
we won't call any of the functions that now
require being able to sleep and/or the mutex
to be held in an invalid context.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-4965.c   |    5 +++-
 drivers/net/wireless/iwlwifi/iwl-agn-tx.c |    5 +++-
 drivers/net/wireless/iwlwifi/iwl-agn.c    |   29 +++++++++++++--------------
 drivers/net/wireless/iwlwifi/iwl-sta.c    |   31 ++++++++++++++++++++--------
 drivers/net/wireless/iwlwifi/iwl-sta.h    |    2 +-
 5 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 83e6a42..fee276b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1785,6 +1785,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 {
 	unsigned long flags;
 	u16 ra_tid;
+	int ret;
 
 	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
 	    (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -1800,7 +1801,9 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 	ra_tid = BUILD_RAxTID(sta_id, tid);
 
 	/* Modify device's station table to Tx this TID */
-	iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	if (ret)
+		return ret;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 84df7fc..2573234 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -233,6 +233,7 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 {
 	unsigned long flags;
 	u16 ra_tid;
+	int ret;
 
 	if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
 	    (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -248,7 +249,9 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 	ra_tid = BUILD_RAxTID(sta_id, tid);
 
 	/* Modify device's station table to Tx this TID */
-	iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	if (ret)
+		return ret;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index d857f84..294b7ed 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3374,7 +3374,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 				struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
 	struct iwl_priv *priv = hw->priv;
-	int ret;
+	int ret = -EINVAL;
 
 	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
 		     sta->addr, tid);
@@ -3382,17 +3382,19 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 	if (!(priv->cfg->sku & IWL_SKU_N))
 		return -EACCES;
 
+	mutex_lock(&priv->mutex);
+
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 		IWL_DEBUG_HT(priv, "start Rx\n");
-		return iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
+		ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
+		break;
 	case IEEE80211_AMPDU_RX_STOP:
 		IWL_DEBUG_HT(priv, "stop Rx\n");
 		ret = iwl_sta_rx_agg_stop(priv, sta, tid);
 		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-			return 0;
-		else
-			return ret;
+			ret = 0;
+		break;
 	case IEEE80211_AMPDU_TX_START:
 		IWL_DEBUG_HT(priv, "start Tx\n");
 		ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
@@ -3401,7 +3403,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 			IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
 				     priv->_agn.agg_tids_count);
 		}
-		return ret;
+		break;
 	case IEEE80211_AMPDU_TX_STOP:
 		IWL_DEBUG_HT(priv, "stop Tx\n");
 		ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
@@ -3411,18 +3413,15 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 				     priv->_agn.agg_tids_count);
 		}
 		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-			return 0;
-		else
-			return ret;
+			ret = 0;
+		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		/* do nothing */
-		return -EOPNOTSUPP;
-	default:
-		IWL_DEBUG_HT(priv, "unknown\n");
-		return -EINVAL;
+		/* do nothing, return value ignored */
 		break;
 	}
-	return 0;
+	mutex_unlock(&priv->mutex);
+
+	return ret;
 }
 
 static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index d57df6c..a62a032 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -30,6 +30,7 @@
 #include <net/mac80211.h>
 #include <linux/etherdevice.h>
 #include <linux/sched.h>
+#include <linux/lockdep.h>
 
 #include "iwl-dev.h"
 #include "iwl-core.h"
@@ -145,8 +146,10 @@ int iwl_send_add_sta(struct iwl_priv *priv,
 
 	if (flags & CMD_ASYNC)
 		cmd.callback = iwl_add_sta_callback;
-	else
+	else {
 		cmd.flags |= CMD_WANT_SKB;
+		might_sleep();
+	}
 
 	cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
 	ret = iwl_send_cmd(priv, &cmd);
@@ -1268,17 +1271,22 @@ EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station);
 /**
  * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
  */
-void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
+int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
 {
 	unsigned long flags;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	/* Remove "disable" flag, to enable Tx for this TID */
 	spin_lock_irqsave(&priv->sta_lock, flags);
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
 	priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
 
@@ -1287,6 +1295,9 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
 {
 	unsigned long flags;
 	int sta_id;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	sta_id = iwl_sta_id(sta);
 	if (sta_id == IWL_INVALID_STATION)
@@ -1298,10 +1309,10 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
 	priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
 	priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
-				CMD_ASYNC);
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 EXPORT_SYMBOL(iwl_sta_rx_agg_start);
 
@@ -1309,7 +1320,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			int tid)
 {
 	unsigned long flags;
-	int sta_id, ret;
+	int sta_id;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	sta_id = iwl_sta_id(sta);
 	if (sta_id == IWL_INVALID_STATION) {
@@ -1322,11 +1336,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
 	priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return ret;
-
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 5b1b1e4..619bb99 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -73,7 +73,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
 		       const u8 *addr);
 int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta);
-void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
+int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
 int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			 int tid, u16 ssn);
 int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 4/9] iwlwifi: display ucode SW Error in hex
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Jay Sternberg, Reinette Chatre
In-Reply-To: <1277143600-32554-1-git-send-email-reinette.chatre@intel.com>

From: Jay Sternberg <jay.e.sternberg@intel.com>

errors are defined in hex but displayed as decimal.  displaying as hex
debugging easier and eliminated having to manually convert.

Signed-off-by: Jay Sternberg <jay.e.sternberg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c      |    4 ++--
 drivers/net/wireless/iwlwifi/iwl3945-base.c |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 294b7ed..fd245c4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2310,9 +2310,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
 	trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
 				      blink1, blink2, ilink1, ilink2);
 
-	IWL_ERR(priv, "Desc                               Time       "
+	IWL_ERR(priv, "Desc                                  Time       "
 		"data1      data2      line\n");
-	IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
+	IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
 		desc_lookup(desc), desc, time, data1, data2, line);
 	IWL_ERR(priv, "pc      blink1  blink2  ilink1  ilink2  hcmd\n");
 	IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 697fa6c..8eb3471 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1424,7 +1424,7 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
 		    iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32));
 
 		IWL_ERR(priv,
-			"%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
+			"%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
 			desc_lookup(desc), desc, time, blink1, blink2,
 			ilink1, ilink2, data1);
 		trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0,
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 3/9] iwlwifi: return ucode errors from station management
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1277143600-32554-1-git-send-email-reinette.chatre@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

When station management calls to ucode return
an error we could previously do nothing, but
now that almost all calls are synchronous we
can actually let the error bubble up. Use EIO
as the error as it best indicates a problem
with the device.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-sta.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index d39bfac..6a9cd08 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -55,18 +55,19 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
 	}
 }
 
-static void iwl_process_add_sta_resp(struct iwl_priv *priv,
-				     struct iwl_addsta_cmd *addsta,
-				     struct iwl_rx_packet *pkt,
-				     bool sync)
+static int iwl_process_add_sta_resp(struct iwl_priv *priv,
+				    struct iwl_addsta_cmd *addsta,
+				    struct iwl_rx_packet *pkt,
+				    bool sync)
 {
 	u8 sta_id = addsta->sta.sta_id;
 	unsigned long flags;
+	int ret = -EIO;
 
 	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
 		IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
 			pkt->hdr.flags);
-		return;
+		return ret;
 	}
 
 	IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
@@ -78,6 +79,7 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv,
 	case ADD_STA_SUCCESS_MSK:
 		IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
 		iwl_sta_ucode_activate(priv, sta_id);
+		ret = 0;
 		break;
 	case ADD_STA_NO_ROOM_IN_TABLE:
 		IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
@@ -115,6 +117,8 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv,
 		       STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
 		       addsta->sta.addr);
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return ret;
 }
 
 static void iwl_add_sta_callback(struct iwl_priv *priv,
@@ -159,7 +163,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
 
 	if (ret == 0) {
 		pkt = (struct iwl_rx_packet *)cmd.reply_page;
-		iwl_process_add_sta_resp(priv, sta, pkt, true);
+		ret = iwl_process_add_sta_resp(priv, sta, pkt, true);
 	}
 	iwl_free_pages(priv, cmd.reply_page);
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/9] iwlwifi: use sync commands for keys
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1277143600-32554-1-git-send-email-reinette.chatre@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

Key management can use sync commands
instead of asynchronous ones to have
better error checking.

Also add checks that the commands all
should have the mutex held.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-sta.c |   29 ++++++++++++++++++-----------
 1 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index a62a032..d39bfac 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -834,7 +834,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
 {
 	unsigned long flags;
 	__le16 key_flags = 0;
-	int ret;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
 
@@ -874,11 +876,10 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
-	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return ret;
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 
 static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
@@ -887,7 +888,9 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
 {
 	unsigned long flags;
 	__le16 key_flags = 0;
-	int ret;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
 	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
@@ -922,11 +925,10 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
-	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return ret;
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 
 static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
@@ -1016,9 +1018,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
 				u8 sta_id)
 {
 	unsigned long flags;
-	int ret = 0;
 	u16 key_flags;
 	u8 keyidx;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	priv->key_mapping_key--;
 
@@ -1065,9 +1069,10 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
 		spin_unlock_irqrestore(&priv->sta_lock, flags);
 		return 0;
 	}
-	ret =  iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
-	return ret;
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 EXPORT_SYMBOL(iwl_remove_dynamic_key);
 
@@ -1076,6 +1081,8 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
 {
 	int ret;
 
+	lockdep_assert_held(&priv->mutex);
+
 	priv->key_mapping_key++;
 	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 0/9] iwlwifi updates for 2.6.36
From: Reinette Chatre @ 2010-06-21 18:06 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

mac80211 recently received changes to enable driver's ampdu actions to
sleep. In this series we include changes in driver to make use of this
feature for better data protection and error handling. The key management
calls can also sleep and driver is now modified to utilize this also.
Better error reporting is added to station management also. The rest of
this series consist of code cleanup where, for example, we are moving a
significant amount of code to the appropriate module (agn specific code
to iwlagn module).

These patches are also available from wireless-next-2.6 branch on
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git

Jay Sternberg (1):
  iwlwifi: display ucode SW Error in hex

Johannes Berg (3):
  iwlagn: use mutex for aggregation
  iwlwifi: use sync commands for keys
  iwlwifi: return ucode errors from station management

Wey-Yi Guy (5):
  iwlwifi: move agn specific rx related code to iwl-agn-rx.c
  iwlwifi: move _agn statistics related structure
  iwlwifi: move calibration from iwlcore to iwlagn
  iwlwifi: code cleanup to remove un-necessary "goto"
  iwlwifi: remove non-exist reference

 drivers/net/wireless/iwlwifi/Makefile          |    4 +-
 drivers/net/wireless/iwlwifi/iwl-4965.c        |   12 +-
 drivers/net/wireless/iwlwifi/iwl-5000.c        |    2 +-
 drivers/net/wireless/iwlwifi/iwl-agn-calib.c   |  910 +++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c |   72 +-
 drivers/net/wireless/iwlwifi/iwl-agn-lib.c     |    3 +-
 drivers/net/wireless/iwlwifi/iwl-agn-rx.c      |  278 +++++++
 drivers/net/wireless/iwlwifi/iwl-agn-tx.c      |    5 +-
 drivers/net/wireless/iwlwifi/iwl-agn.c         |   47 +-
 drivers/net/wireless/iwlwifi/iwl-agn.h         |   10 +
 drivers/net/wireless/iwlwifi/iwl-calib.c       |  919 ------------------------
 drivers/net/wireless/iwlwifi/iwl-core.h        |   10 -
 drivers/net/wireless/iwlwifi/iwl-dev.h         |   14 +-
 drivers/net/wireless/iwlwifi/iwl-rx.c          |  238 ------
 drivers/net/wireless/iwlwifi/iwl-sta.c         |   76 ++-
 drivers/net/wireless/iwlwifi/iwl-sta.h         |    2 +-
 drivers/net/wireless/iwlwifi/iwl3945-base.c    |    2 +-
 17 files changed, 1333 insertions(+), 1271 deletions(-)
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-calib.c
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-rx.c
 delete mode 100644 drivers/net/wireless/iwlwifi/iwl-calib.c


^ permalink raw reply

* Re: [RFC] refactor ath9k_platform to sound sane for use in both ath9k and ath5k
From: Luis R. Rodriguez @ 2010-06-21 18:02 UTC (permalink / raw)
  To: Daniel Golle; +Cc: linux-wireless, ath5k-devel, ath9k-devel
In-Reply-To: <4C1F51A3.5000407@gmail.com>

On Mon, Jun 21, 2010 at 4:48 AM, Daniel Golle <daniel.golle@gmail.com> wrote:
> I'm developing on OpenWrt to work with EEPROM-less ath5k mini-pci devices.
> This is needed to support the ar71xx-based Senao EAP7660D board which got
> two AR5413 modules soldered into its mini-pci slots. In the original
> Firmware, MAC addresses as well as calibration-data seems to be part of the
> firmware blob stored on the board flash.
> See https://lists.openwrt.org/pipermail/openwrt-devel/2010-June/007366.html
> for the corresponding discussion on OpenWrt-devel.

I don't see much "discussion" there.

> Similarly to the way this happens for ath9k, I managed to get ath5k to use
> the MAC address and eeprom-data supplied by ath9k_platform_data.
> Including ath9k_platform.h in ath5k-sources looks confusing as the name
> ath9k_platform suggests that the supplied ath9k_platform_info struct is
> specific to ath9k devices.
> Consequently, I believe ath9k_platform.h should be renamed into
> ath_platform.h, the macro ATH9K_PLAT_EEP_MAX_WORDS into
> ATH_PLAT_EEP_MAX_WORDS and struct ath9k_platform_data should be refactored
> to be struct ath_platform_data.
> Please let me know if you agree with this in theory; if yes, I'll start
> posting the patches to OpenWrt.

You can stuff any general stuff into the ath module which is shared by both.

  Luis

^ permalink raw reply

* Re: [PATCH 2/2] wl1251: fix ELP_CTRL register reads
From: Bob Copeland @ 2010-06-21 17:54 UTC (permalink / raw)
  To: Denis 'GNUtoo' Carikli
  Cc: Kalle Valo, Grazvydas Ignotas, John W.Linville, linux-wireless
In-Reply-To: <1277124410.28895.23.camel@gnutoo-laptop>

On Mon, Jun 21, 2010 at 8:46 AM, Denis 'GNUtoo' Carikli
<GNUtoo@no-log.org> wrote:

> Hi, me and some other people are trying to run standard GNU/Linux (not
> android ) on the htcdream.

> [ 1556.425354] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> [ 1556.734130] mmc0: Command timeout

In this case it was only up for 1/3 second before it quit
responding to reads.  With power saving disabled it works?

Probably not relevant to power saving, but:

Are you using the dedicated irq line or sdio interrupt?
It makes a big difference in overall throughput to use
the former.

> +       /*
> +        * FIXME: scanning while associated causes lockups,
> +        * so we don't allow that
> +        */
> +       if (wl->associated)
> +               return -EBUSY;

Any idea why?  Could you turn on lockdep?

-- 
Bob Copeland %% www.bobcopeland.com

^ permalink raw reply

* RE: wireless-regdb: Add A band in IL - And general point regarding tx  power limits in the dbase
From: Michael Green @ 2010-06-21 17:41 UTC (permalink / raw)
  To: Emmanuel Grumbach
  Cc: John W. Linville, linux-wireless@vger.kernel.org, David Quan
In-Reply-To: <AANLkTinGczUb2xTX5RUtnrRnc2BitOjZnpkDeHPV9Hwf@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1039 bytes --]



Michael Green
Atheros Communications, Inc.
mgreen@atheros.com
Desk:   +1-781-400-1491
Mobile: +1-508-380-4921

-----Original Message-----
From: Emmanuel Grumbach [mailto:egrumbach@gmail.com] 
Sent: Monday, June 21, 2010 1:12 PM
To: Michael Green
Cc: John W. Linville; linux-wireless@vger.kernel.org; David Quan
Subject: Re: wireless-regdb: Add A band in IL - And general point regarding tx power limits in the dbase

On Mon, Jun 21, 2010 at 17:51, Michael Green <Michael.Green@atheros.com> wrote:
> Here are my comments on the proposed patch...
>
> country IL:
>> >       (2402 - 2482 @ 40), (N/A, 20)
>> > +     (5150 - 5250 @ 40). (N/A, 200 mW), NO-OUTDOOR
>> > +     (5250 - 5350 @ 40). (N/A, 200 mW), NO-OUTDOOR, DFS
>


> b) I think all entries in the dbase should be in dBm (not mW).   dBm vs. mW are absolutely equivalent. No reason to retain "mW" unit from the source docs.  I think this was agreed by all before, but wanted to reiterate.

Can you please help me translation from mW to db ?

Thanks

[-- Attachment #2: dBm to mW.pdf --]
[-- Type: application/pdf, Size: 33631 bytes --]

^ permalink raw reply

* Re: wireless-regdb: Add A band in IL - And general point regarding tx power limits in the dbase
From: Emmanuel Grumbach @ 2010-06-21 17:12 UTC (permalink / raw)
  To: Michael Green
  Cc: John W. Linville, linux-wireless@vger.kernel.org, David Quan
In-Reply-To: <93781E992CBA7843962D8B0E7D683F3C1172BD0B6D@SC1EXMB-MBCL.global.atheros.com>

On Mon, Jun 21, 2010 at 17:51, Michael Green <Michael.Green@atheros.com> wrote:
> Here are my comments on the proposed patch...
>
> country IL:
>> >       (2402 - 2482 @ 40), (N/A, 20)
>> > +     (5150 - 5250 @ 40). (N/A, 200 mW), NO-OUTDOOR
>> > +     (5250 - 5350 @ 40). (N/A, 200 mW), NO-OUTDOOR, DFS
>


> b) I think all entries in the dbase should be in dBm (not mW).   dBm vs. mW are absolutely equivalent. No reason to retain "mW" unit from the source docs.  I think this was agreed by all before, but wanted to reiterate.

Can you please help me translation from mW to db ?

Thanks

^ permalink raw reply

* Re: wireless-regdb: Add A band in IL - And general point regarding tx power limits in the dbase
From: John W. Linville @ 2010-06-21 14:57 UTC (permalink / raw)
  To: Michael Green
  Cc: linux-wireless@vger.kernel.org, David Quan, Emmanuel Grumbach
In-Reply-To: <93781E992CBA7843962D8B0E7D683F3C1172BD0B6D@SC1EXMB-MBCL.global.atheros.com>

On Mon, Jun 21, 2010 at 07:51:56AM -0700, Michael Green wrote:
> Here are my comments on the proposed patch...
> 
> country IL:
> > >       (2402 - 2482 @ 40), (N/A, 20)
> > > +     (5150 - 5250 @ 40). (N/A, 200 mW), NO-OUTDOOR
> > > +     (5250 - 5350 @ 40). (N/A, 200 mW), NO-OUTDOOR, DFS

> b) I think all entries in the dbase should be in dBm (not mW).
> dBm vs. mW are absolutely equivalent. No reason to retain "mW"
> unit from the source docs.  I think this was agreed by all before,
> but wanted to reiterate.

I'm not sure I see the fuss.  If anything, using the same units as
the source docs seems less error-prone to me.  Why not stick with
the source units and let the tool do the conversion rather than risk
introducing an error in the manual conversion?

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* wireless-regdb: Add A band in IL - And general point regarding tx power limits in the dbase
From: Michael Green @ 2010-06-21 14:51 UTC (permalink / raw)
  To: John W. Linville
  Cc: linux-wireless@vger.kernel.org, David Quan, Emmanuel Grumbach
In-Reply-To: <AANLkTimN8oZ63m7cp2lE5MuFiEJ8iAGKswKIENTjIhMg@mail.gmail.com>

Here are my comments on the proposed patch...

country IL:
> >       (2402 - 2482 @ 40), (N/A, 20)
> > +     (5150 - 5250 @ 40). (N/A, 200 mW), NO-OUTDOOR
> > +     (5250 - 5350 @ 40). (N/A, 200 mW), NO-OUTDOOR, DFS


a) I agree with channels above and enabling HT40 per above.

b) I think all entries in the dbase should be in dBm (not mW).   dBm vs. mW are absolutely equivalent. No reason to retain "mW" unit from the source docs.  I think this was agreed by all before, but wanted to reiterate. 

c) I don't understand why "Indoor/Outdoor" is stated in the table for any/all countries.   5150-5250 is globally allocated for indoor use.  So I am not reviewing/commenting on the indoor/outdoor comments in the dbase.


d) Reminder...Israel and most other countries state max tx power limit in 'EIRP' (ie takes into account actual antenna gain of the end device).  Therefore, the entire dbase must be clearly flagged so developers know the tx power limits in this dbase only apply when devices have 0dB (or negative) gain antennas.  

In other words, the software (or the hw/sw developer) must somehow reduce tx powers below the values in the dbase, dB-for-dB, when antenna+cable has positive gain.

The exception is FCC target power, where FCC (and the dBase) quotes "conducted power" rather than EIRP.

Issue d) is not a concern for manufacturers/developers who produce products that limit regulatory tx powers in the hw (factory set/limited). In that case they take into account actual antenna gains during original conformance testing and program in compliant tx powers into hw (and don't rely at all on the tx powers in the dbase).

But developers who don't have tx powers limited in hw, who actually use the tx power in the dbase, must take into account antenna gain as explained above, else the product may not comply with tx limits for most countries.  

Fine if you want to discuss point d) separately since it's a global issue (not limited to this particular IL patch).

tks,

Michael Green
Atheros Communications, Inc.
mgreen@atheros.com
Desk:   +1-781-400-1491
Mobile: +1-508-380-4921


-----Original Message-----
From: Emmanuel Grumbach [mailto:egrumbach@gmail.com] 
Sent: Sunday, June 20, 2010 1:41 AM
To: John W. Linville
Cc: Emmanuel Grumbach; linux-wireless@vger.kernel.org; Michael Green; David Quan
Subject: Re: [RFC] wireless-regdb: Add A band in IL

Emmanuel Grumbach
egrumbach@gmail.com


On Fri, Jun 18, 2010 at 21:42, John W. Linville <linville@tuxdriver.com> wrote:
>
> On Wed, May 26, 2010 at 09:49:29AM +0300, Emmanuel Grumbach wrote:
> > A band in allowed in IL, according to official document issued by the Ministry
> > of Communications: http://www.moc.gov.il/sip_storage/FILES/1/1061.pdf.
> >
> > 5150 - 5250 200mW e.i.r.p. OUTDOOR forbidden
> > 5250 - 5350 200mW e.i.r.p. OUTDOOR forbidden DFS mandatory
> >
> > 40Mhz is allowed in A band for every WiFi-Alliance certified equipment.
> >
> > ***************************************************************
> > Not to be merged for the moment
> > ***************************************************************
> >
> > CC: Michael Green <Michael.Green@atheros.com>
> > CC: David Quan <David.Quan@atheros.com>
> > Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> > ---
> >  db.txt |    2 ++
> >  1 files changed, 2 insertions(+), 0 deletions(-)
> >
> > diff --git a/db.txt b/db.txt
> > index e63a43e..d49c397 100644
> > --- a/db.txt
> > +++ b/db.txt
> > @@ -319,6 +319,8 @@ country IE:
> >
> >  country IL:
> >       (2402 - 2482 @ 40), (N/A, 20)
> > +     (5150 - 5250 @ 40). (N/A, 200 mW), NO-OUTDOOR
> > +     (5250 - 5350 @ 40). (N/A, 200 mW), NO-OUTDOOR, DFS
> >
> >  country IN:
> >       (2402 - 2482 @ 40), (N/A, 20)
>
> Is this issue now settled?

Yes, I think that Michael Green agreed for this patch. Once he will
reply to make sure, we will be able to move on to a real patch.

^ permalink raw reply

* Re: 2.6.35-rc3: Reported regressions from 2.6.34
From: Nick Bowler @ 2010-06-21 13:58 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Maciej Rutecki, Andrew Morton,
	Linus Torvalds, Kernel Testers List, Network Development,
	Linux ACPI, Linux PM List, Linux SCSI List, Linux Wireless List,
	DRI
In-Reply-To: <lc60d4toGTL.A.QzD._LpHMB@chimera>

On 00:11 Mon 21 Jun     , Rafael J. Wysocki wrote:
> If you know of any other unresolved regressions from 2.6.34, please let us
> know either and we'll add them to the list.  Also, please let us know
> if any of the entries below are invalid.

Didn't see this one in the list:

  Why is kslowd accumulating so much CPU time?
  http://thread.gmane.org/gmane.linux.kernel/996907

-- 
Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/)

^ permalink raw reply

* Re: [PATCH 2/2] wl1251: fix ELP_CTRL register reads
From: Denis 'GNUtoo' Carikli @ 2010-06-21 12:46 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Grazvydas Ignotas, John W.Linville, linux-wireless
In-Reply-To: <AANLkTinqgUGCjCBzg8j7bXGY05EW3-jfW7vlnrvCuwRd@mail.gmail.com>

On Sat, 2010-06-05 at 10:04 +0300, Kalle Valo wrote:
> On 5 June 2010 02:25, Grazvydas Ignotas <notasas@gmail.com> wrote:
> > Reading the ELP_CTRL register with sdio_readb causes problems because
> > hardware seems to be performing a write using stuff bits in the request
> > (those bits contain write data in write request). This indicates that it
> > actually expects RAW (read after write) type of request, so perform that
> > when reading ELP_CTRL instead. Also cache last written value so we know
> > what to write when doing RAW request.
> >
> > Because of the above it was not possible to wake the chip from ELP power
> > saving mode, PM had to be disabled to have the driver usable in SDIO
> > mode. After this patch PM is functional.
> 
> Excellent that Power Save is now working SDIO. Thank you very much!
Hi, me and some other people are trying to run standard GNU/Linux (not
android ) on the htcdream.
The htcdream has a wl1251_sdio with a msm sdio controller.
we currently work on a 2.6.32 kenrel.
As it's a phone, power management is important and so I tried with PS
enabled by default in the kernel:
CONFIG_CFG80211_DEFAULT_PS=y
CONFIG_CFG80211_DEFAULT_PS_VALUE=1

I've tried lastest compat-wireless (2010-06-20) with the following
patches:

Index:
compat-wireless-2010-06-19/drivers/net/wireless/wl12xx/wl1251_sdio.c
===================================================================
---
compat-wireless-2010-06-19.orig/drivers/net/wireless/wl12xx/wl1251_sdio.c	2010-06-20 23:00:09.755843242 +0200
+++ compat-wireless-2010-06-19/drivers/net/wireless/wl12xx/wl1251_sdio.c
2010-06-20 23:01:34.733958063 +0200
@@ -106,7 +106,7 @@
 	 * request).
 	 */
 	sdio_claim_host(func);
-	*val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret);
+	*val = sdio_readb_ext(func, addr, &ret, 1);
 	sdio_release_host(func);
 
 	if (ret)

Index:
compat-wireless-2010-06-19/drivers/net/wireless/wl12xx/wl1251_sdio.c
===================================================================
---
compat-wireless-2010-06-19.orig/drivers/net/wireless/wl12xx/wl1251_sdio.c	2010-06-20 22:04:12.776553632 +0200
+++ compat-wireless-2010-06-19/drivers/net/wireless/wl12xx/wl1251_sdio.c
2010-06-20 22:06:30.375232047 +0200
@@ -131,6 +131,20 @@
 
 static void wl1251_sdio_reset(struct wl1251 *wl)
 {
+	extern int sdio_reset_comm(struct mmc_card *card);
+	struct sdio_func *func = wl_to_func(wl);
+	int ret;
+
+	sdio_claim_host(func);
+	sdio_reset_comm(func->card);
+	ret = sdio_enable_func(func);
+	if (ret)
+		goto release;
+
+	sdio_set_block_size(func, 512);
+
+release:
+	sdio_release_host(func);
 }
 
 static void wl1251_sdio_enable_irq(struct wl1251 *wl)
@@ -271,6 +285,9 @@
 	ret = wl1251_init_ieee80211(wl);
 	if (ret)
 		goto out_free_irq;
+	
+	/* we can power it down now until it's started */
+	wl->set_power(0);
 
 	sdio_set_drvdata(func, wl);
 	return ret;

Index: compat-wireless-2010-06-19/drivers/net/wireless/wl12xx/wl1251.h
===================================================================
--- compat-wireless-2010-06-19.orig/drivers/net/wireless/wl12xx/wl1251.h
2010-06-20 22:07:29.346389894 +0200
+++ compat-wireless-2010-06-19/drivers/net/wireless/wl12xx/wl1251.h
2010-06-20 22:08:41.974607260 +0200
@@ -381,6 +381,8 @@
 
 	u32 chip_id;
 	char fw_ver[21];
+
+	bool associated;
 };
 
 int wl1251_plt_start(struct wl1251 *wl);
Index:
compat-wireless-2010-06-19/drivers/net/wireless/wl12xx/wl1251_main.c
===================================================================
---
compat-wireless-2010-06-19.orig/drivers/net/wireless/wl12xx/wl1251_main.c	2010-06-20 22:07:36.606391128 +0200
+++ compat-wireless-2010-06-19/drivers/net/wireless/wl12xx/wl1251_main.c
2010-06-20 22:10:11.594572491 +0200
@@ -869,6 +869,13 @@
 
 	wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan");
 
+	/*
+	 * FIXME: scanning while associated causes lockups,
+	 * so we don't allow that
+	 */
+	if (wl->associated)
+		return -EBUSY;
+
 	if (req->n_ssids) {
 		ssid = req->ssids[0].ssid;
 		ssid_len = req->ssids[0].ssid_len;
and a minor build patch:
Index: compat-wireless-2010-06-19/scripts/gen-compat-autoconf.sh
===================================================================
--- compat-wireless-2010-06-19.orig/scripts/gen-compat-autoconf.sh
2010-06-20 17:40:48.586388753 +0200
+++ compat-wireless-2010-06-19/scripts/gen-compat-autoconf.sh	2010-06-20
17:41:07.833335272 +0200
@@ -192,7 +192,7 @@
 		define_config_multiple_deps CONFIG_MAC80211_QOS y $ALL_DEPS
 		rm -f $MULT_DEP_FILE
 		# Kernels >= 2.6.32 can disable WEXT :D
-		if [ $SUBLEVEL -lt 32 ]; then
+		if [ $SUBLEVEL -le 32 ]; then
 			define_config_dep CONFIG_CFG80211_WEXT 1 CONFIG_WIRELESS_EXT
 		fi
 	fi


And I've the following messages in dmesg:
[ 1412.632263] cfg80211: Calling CRDA to update world regulatory domain
[ 1413.038391] wifi probe start
[ 1413.038452] trout_wifi_power: 1
[ 1413.240142] trout_wifi_reset: 0
[ 1413.291748] trout_wifi_set_carddetect: 1
[ 1413.291778] mmc0: card_present 1
[ 1413.291809] mmc0: Slot status change detected (0 -> 1)
[ 1413.291839] wifi probe done
[ 1415.828735] mmc0: Command timeout
[ 1415.834259] mmc0: card claims to support voltages below the defined
range. These will be ignored.
[ 1415.838806] mmc0: new SDIO card at address 0001
[ 1415.855041] wl1251: using SDIO interrupt
[ 1415.985321] phy0: Selected rate control algorithm 'minstrel'
[ 1415.990325] wl1251: loaded
[ 1415.991363] wl1251: initialized
[ 1433.640594] request_suspend_state: sleep (0->3) at 1427975218412
(2010-06-21 12:31:23.116053303 UTC)
[ 1433.641845] msm_i2c msm_i2c.0: Warning bus was busy (8)
[ 1464.390441] sdio_reset_comm():
[ 1465.120025] wl1251: 151 tx blocks at 0x3b788, 35 rx blocks at 0x3a780
[ 1465.140136] wl1251: firmware booted (Rev 4.0.4.3.5)
[ 1465.280761] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[ 1556.024566] wlan0: authenticate with 00:24:01:63:89:bd (try 1)
[ 1556.036285] wlan0: authenticated
[ 1556.114501] wlan0: associate with 00:24:01:63:89:bd (try 1)
[ 1556.126525] wlan0: RX AssocResp from 00:24:01:63:89:bd (capab=0x401
status=0 aid=3)
[ 1556.126556] wlan0: associated
[ 1556.425354] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
[ 1556.734130] mmc0: Command timeout
[ 1556.739166] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1557.454101] mmc0: Command CRC error
[ 1557.454162] wl1251: ERROR sdio_writeb failed (-84)
[ 1557.763610] mmc0: Command timeout
[ 1557.768829] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1558.773071] mmc0: Command CRC error
[ 1558.773132] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1559.782562] mmc0: Command timeout
[ 1559.787628] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1560.792022] mmc0: Command CRC error
[ 1560.792083] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1561.821563] mmc0: Command timeout
[ 1561.826629] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1562.831085] mmc0: Command CRC error
[ 1562.831146] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1563.860534] mmc0: Command timeout
[ 1563.865570] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1564.869995] mmc0: Command CRC error
[ 1564.870056] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1565.899475] mmc0: Command timeout
[ 1565.904541] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1566.449127] wlan0: no IPv6 routers present
[ 1566.908996] mmc0: Command CRC error
[ 1566.909057] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1567.918518] mmc0: Command timeout
[ 1567.923553] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1568.928009] mmc0: Command CRC error
[ 1568.928100] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1569.937500] mmc0: Command timeout
[ 1569.942565] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1570.946990] mmc0: Command CRC error
[ 1570.947052] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1571.956481] mmc0: Command timeout
[ 1571.961547] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1572.966003] mmc0: Command CRC error
[ 1572.966064] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1573.975463] mmc0: Command timeout
[ 1573.980529] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1574.984985] mmc0: Command CRC error
[ 1574.985046] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1576.244323] mmc0: Command timeout
[ 1576.249359] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1577.253845] mmc0: Command CRC error
[ 1577.253906] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1578.563140] mmc0: Command timeout
[ 1578.568237] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1578.667968] mmc0: Command CRC error
[ 1578.668029] wl1251: ERROR sdio_writeb failed (-84)
[ 1579.572692] mmc0: Command timeout
[ 1579.577758] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1580.582153] mmc0: Command CRC error
[ 1580.582214] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1581.591705] mmc0: Command timeout
[ 1581.596771] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1582.601165] mmc0: Command CRC error
[ 1582.601226] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1583.610626] mmc0: Command timeout
[ 1583.615692] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1584.620117] mmc0: Command CRC error
[ 1584.620178] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1585.629638] mmc0: Command timeout
[ 1585.634704] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1586.639129] mmc0: Command CRC error
[ 1586.639190] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1587.648681] mmc0: Command timeout
[ 1587.653717] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1588.658142] mmc0: Command CRC error
[ 1588.658203] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1589.667663] mmc0: Command timeout
[ 1589.672729] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1590.677093] mmc0: Command CRC error
[ 1590.677185] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1591.686614] mmc0: Command timeout
[ 1591.691680] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1592.696075] mmc0: Command CRC error
[ 1592.696136] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1593.705657] mmc0: Command timeout
[ 1593.710693] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1594.715087] mmc0: Command CRC error
[ 1594.715148] mmc0:0001: error -84 reading SDIO_CCCR_INTx
[ 1595.724639] mmc0: Command timeout
[ 1595.729705] mmc0:0001: error -110 reading SDIO_CCCR_INTx
[ 1596.734100] mmc0: Command CRC error
[ 1596.734161] mmc0:0001: error -84 reading SDIO_CCCR_INTx
etc....
So I use the wifi,listen to a webradio,browse the web etc...
but after a while it stop working,and after a while it stops working.
and when it occurs,iwconfig say that it's still associated...
Denis.



^ permalink raw reply

* [RFC] refactor ath9k_platform to sound sane for use in both ath9k and ath5k
From: Daniel Golle @ 2010-06-21 11:48 UTC (permalink / raw)
  To: linux-wireless, ath5k-devel, ath9k-devel

I'm developing on OpenWrt to work with EEPROM-less ath5k mini-pci 
devices. This is needed to support the ar71xx-based Senao EAP7660D board 
which got two AR5413 modules soldered into its mini-pci slots. In the 
original Firmware, MAC addresses as well as calibration-data seems to be 
part of the firmware blob stored on the board flash.
See 
https://lists.openwrt.org/pipermail/openwrt-devel/2010-June/007366.html 
for the corresponding discussion on OpenWrt-devel.
Similarly to the way this happens for ath9k, I managed to get ath5k to 
use the MAC address and eeprom-data supplied by ath9k_platform_data.
Including ath9k_platform.h in ath5k-sources looks confusing as the name 
ath9k_platform suggests that the supplied ath9k_platform_info struct is 
specific to ath9k devices.
Consequently, I believe ath9k_platform.h should be renamed into 
ath_platform.h, the macro ATH9K_PLAT_EEP_MAX_WORDS into 
ATH_PLAT_EEP_MAX_WORDS and struct ath9k_platform_data should be 
refactored to be struct ath_platform_data.
Please let me know if you agree with this in theory; if yes, I'll start 
posting the patches to OpenWrt.

Cheers

Daniel

^ permalink raw reply

* [RFC PATCHv2] iw: Add support for setting transmit power level
From: Juuso Oikarinen @ 2010-06-21 10:50 UTC (permalink / raw)
  To: linux-wireless

Add a "set txpower" option to specify the current transmit power level. Modes
supported are automatic, fixed and limited, and the limit may be specified
in signed mBm units.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 nl80211.h |   22 ++++++++++++++++++++++
 phy.c     |   50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 71 insertions(+), 1 deletions(-)

diff --git a/nl80211.h b/nl80211.h
index 64fb32b..2c87016 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -725,6 +725,12 @@ enum nl80211_commands {
  * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations
  *	connected to this BSS.
  *
+ * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See
+ *      &enum nl80211_tx_power_setting for possible values.
+ * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units.
+ *      This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
+ *      for non-automatic settings.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -882,6 +888,9 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_AP_ISOLATE,
 
+	NL80211_ATTR_WIPHY_TX_POWER_SETTING,
+	NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -1659,4 +1668,17 @@ enum nl80211_cqm_rssi_threshold_event {
 	NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
 };
 
+
+/**
+ * enum nl80211_tx_power_setting - TX power adjustment
+ * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power
+ * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter
+ * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter
+ */
+enum nl80211_tx_power_setting {
+	NL80211_TX_POWER_AUTOMATIC,
+	NL80211_TX_POWER_LIMITED,
+	NL80211_TX_POWER_FIXED,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/phy.c b/phy.c
index 8f8d757..f042dc2 100644
--- a/phy.c
+++ b/phy.c
@@ -175,7 +175,7 @@ static int handle_netns(struct nl80211_state *state,
 		return 1;
 
 	NLA_PUT_U32(msg, NL80211_ATTR_PID,
-		    strtoul(argv[0], &end, 10)); 
+		    strtoul(argv[0], &end, 10));
 
 	if (*end != '\0')
 		return 1;
@@ -258,3 +258,51 @@ COMMAND(set, distance, "<distance>",
 	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_distance,
 	"Set appropriate coverage class for given link distance in meters.\n"
 	"Valid values: 0 - 114750");
+
+static int handle_txpower(struct nl80211_state *state,
+			  struct nl_cb *cb,
+			  struct nl_msg *msg,
+			  int argc, char **argv)
+{
+	enum nl80211_tx_power_setting type;
+	int ret = -ENOSPC;
+	int mbm;
+
+	/* get the required args */
+	if (argc != 1 && argc != 2)
+		return 1;
+
+	if (!strcmp(argv[0], "auto"))
+		type = NL80211_TX_POWER_AUTOMATIC;
+	else if (!strcmp(argv[0], "fixed"))
+		type = NL80211_TX_POWER_FIXED;
+	else if (!strcmp(argv[0], "limit"))
+		type = NL80211_TX_POWER_LIMITED;
+	else {
+		printf("Invalid parameter: %s\n", argv[0]);
+		return 2;
+	}
+
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING, type);
+
+	if (type != NL80211_TX_POWER_AUTOMATIC) {
+		if (argc != 2) {
+			printf("Missing TX power level argument.\n");
+			return 2;
+		}
+
+		mbm = atoi(argv[1]);
+		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm);
+	}
+
+	ret = 0;
+
+ nla_put_failure:
+	return ret;
+}
+COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
+	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txpower,
+	"Specify transmit power level and setting type.");
+COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
+	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txpower,
+	"Specify transmit power level and setting type.");
-- 
1.6.3.3


^ permalink raw reply related

* Re: [RFC PATCHv2 1/2] cfg80211/mac80211: Update set_tx_power to use mBm instead of dBm units
From: Samuel Ortiz @ 2010-06-21 10:45 UTC (permalink / raw)
  To: Juuso Oikarinen; +Cc: linux-wireless@vger.kernel.org, Jussi Kivilinna
In-Reply-To: <1277116766-4764-1-git-send-email-juuso.oikarinen@nokia.com>

On Mon, Jun 21, 2010 at 11:39:25AM +0100, Juuso Oikarinen wrote:
> In preparation for a TX power setting interface in the nl80211, change the
> .set_tx_power function to use mBm units instead of dBm for greater accuracy and
> smaller power levels.
> 
> Also, already in advance move the tx_power_setting enumeration to nl80211.
> 
> This change affects the .tx_set_power function prototype. As a result, the
> corresponding changes are needed to modules using it. These are mac80211,
> iwmc3200wifi and rndis_wlan.
For the iwm part:
Acked-by: Samuel Ortiz <samuel.ortiz@intel.com>

Cheers,
Samuel.

-- 
Intel Open Source Technology Centre
http://oss.intel.com/
---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.


^ permalink raw reply

* [RFC PATCHv2 1/2] cfg80211/mac80211: Update set_tx_power to use mBm instead of dBm units
From: Juuso Oikarinen @ 2010-06-21 10:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Samuel Ortiz, Jussi Kivilinna

In preparation for a TX power setting interface in the nl80211, change the
.set_tx_power function to use mBm units instead of dBm for greater accuracy and
smaller power levels.

Also, already in advance move the tx_power_setting enumeration to nl80211.

This change affects the .tx_set_power function prototype. As a result, the
corresponding changes are needed to modules using it. These are mac80211,
iwmc3200wifi and rndis_wlan.

Cc: Samuel Ortiz <samuel.ortiz@intel.com>
Cc: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 drivers/net/wireless/iwmc3200wifi/cfg80211.c |   12 ++++++++----
 drivers/net/wireless/rndis_wlan.c            |   20 +++++++++++++-------
 include/linux/nl80211.h                      |   13 +++++++++++++
 include/net/cfg80211.h                       |   15 +--------------
 net/mac80211/cfg.c                           |   22 +++++++++++-----------
 net/wireless/wext-compat.c                   |   10 +++++-----
 6 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
index 902e95f..6061967 100644
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -670,20 +670,24 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
-				    enum tx_power_setting type, int dbm)
+				    enum nl80211_tx_power_setting type, int mbm)
 {
 	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 	int ret;
 
 	switch (type) {
-	case TX_POWER_AUTOMATIC:
+	case NL80211_TX_POWER_AUTOMATIC:
 		return 0;
-	case TX_POWER_FIXED:
+	case NL80211_TX_POWER_FIXED:
+		if (mbm < 0 || (mbm % 100))
+			return -EOPNOTSUPP;
+
 		if (!test_bit(IWM_STATUS_READY, &iwm->status))
 			return 0;
 
 		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
-					      CFG_TX_PWR_LIMIT_USR, dbm * 2);
+					      CFG_TX_PWR_LIMIT_USR,
+					      MBM_TO_DBM(mbm) * 2);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 4102cca..5e26edb 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -520,8 +520,9 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
 
 static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
 
-static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
-				int dbm);
+static int rndis_set_tx_power(struct wiphy *wiphy,
+			      enum nl80211_tx_power_setting type,
+			      int mbm);
 static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm);
 
 static int rndis_connect(struct wiphy *wiphy, struct net_device *dev,
@@ -1856,20 +1857,25 @@ static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 	return 0;
 }
 
-static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
-				int dbm)
+static int rndis_set_tx_power(struct wiphy *wiphy,
+			      enum nl80211_tx_power_setting type,
+			      int mbm)
 {
 	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
 	struct usbnet *usbdev = priv->usbdev;
 
-	netdev_dbg(usbdev->net, "%s(): type:0x%x dbm:%i\n",
-		   __func__, type, dbm);
+	netdev_dbg(usbdev->net, "%s(): type:0x%x mbm:%i\n",
+		   __func__, type, mbm);
+
+	if (mbm < 0 || (mbm % 100))
+		return -ENOTSUPP;
 
 	/* Device doesn't support changing txpower after initialization, only
 	 * turn off/on radio. Support 'auto' mode and setting same dBm that is
 	 * currently used.
 	 */
-	if (type == TX_POWER_AUTOMATIC || dbm == get_bcm4320_power_dbm(priv)) {
+	if (type == NL80211_TX_POWER_AUTOMATIC ||
+	    MBM_TO_DBM(mbm) == get_bcm4320_power_dbm(priv)) {
 		if (!priv->radio_on)
 			disassociate(usbdev, true); /* turn on radio */
 
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 64fb32b..07aa046 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1659,4 +1659,17 @@ enum nl80211_cqm_rssi_threshold_event {
 	NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
 };
 
+
+/**
+ * enum nl80211_tx_power_setting - TX power adjustment
+ * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power
+ * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter
+ * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter
+ */
+enum nl80211_tx_power_setting {
+	NL80211_TX_POWER_AUTOMATIC,
+	NL80211_TX_POWER_LIMITED,
+	NL80211_TX_POWER_FIXED,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 64374f4..9b8b3f4 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -875,19 +875,6 @@ enum wiphy_params_flags {
 	WIPHY_PARAM_COVERAGE_CLASS	= 1 << 4,
 };
 
-/**
- * enum tx_power_setting - TX power adjustment
- *
- * @TX_POWER_AUTOMATIC: the dbm parameter is ignored
- * @TX_POWER_LIMITED: limit TX power by the dbm parameter
- * @TX_POWER_FIXED: fix TX power to the dbm parameter
- */
-enum tx_power_setting {
-	TX_POWER_AUTOMATIC,
-	TX_POWER_LIMITED,
-	TX_POWER_FIXED,
-};
-
 /*
  * cfg80211_bitrate_mask - masks for bitrate control
  */
@@ -1149,7 +1136,7 @@ struct cfg80211_ops {
 	int	(*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
 
 	int	(*set_tx_power)(struct wiphy *wiphy,
-				enum tx_power_setting type, int dbm);
+				enum nl80211_tx_power_setting type, int mbm);
 	int	(*get_tx_power)(struct wiphy *wiphy, int *dbm);
 
 	int	(*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 003b6ad..f4efbfa 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1329,28 +1329,28 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 }
 
 static int ieee80211_set_tx_power(struct wiphy *wiphy,
-				  enum tx_power_setting type, int dbm)
+				  enum nl80211_tx_power_setting type, int mbm)
 {
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_channel *chan = local->hw.conf.channel;
 	u32 changes = 0;
 
 	switch (type) {
-	case TX_POWER_AUTOMATIC:
+	case NL80211_TX_POWER_AUTOMATIC:
 		local->user_power_level = -1;
 		break;
-	case TX_POWER_LIMITED:
-		if (dbm < 0)
-			return -EINVAL;
-		local->user_power_level = dbm;
+	case NL80211_TX_POWER_LIMITED:
+		if (mbm < 0 || (mbm % 100))
+			return -EOPNOTSUPP;
+		local->user_power_level = MBM_TO_DBM(mbm);
 		break;
-	case TX_POWER_FIXED:
-		if (dbm < 0)
-			return -EINVAL;
+	case NL80211_TX_POWER_FIXED:
+		if (mbm < 0 || (mbm % 100))
+			return -EOPNOTSUPP;
 		/* TODO: move to cfg80211 when it knows the channel */
-		if (dbm > chan->max_power)
+		if (MBM_TO_DBM(mbm) > chan->max_power)
 			return -EINVAL;
-		local->user_power_level = dbm;
+		local->user_power_level = MBM_TO_DBM(mbm);
 		break;
 	}
 
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 9634299..1ff1e9f 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -829,7 +829,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
-	enum tx_power_setting type;
+	enum nl80211_tx_power_setting type;
 	int dbm = 0;
 
 	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
@@ -852,7 +852,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
 			if (data->txpower.value < 0)
 				return -EINVAL;
 			dbm = data->txpower.value;
-			type = TX_POWER_FIXED;
+			type = NL80211_TX_POWER_FIXED;
 			/* TODO: do regulatory check! */
 		} else {
 			/*
@@ -860,10 +860,10 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
 			 * passed in from userland.
 			 */
 			if (data->txpower.value < 0) {
-				type = TX_POWER_AUTOMATIC;
+				type = NL80211_TX_POWER_AUTOMATIC;
 			} else {
 				dbm = data->txpower.value;
-				type = TX_POWER_LIMITED;
+				type = NL80211_TX_POWER_LIMITED;
 			}
 		}
 	} else {
@@ -872,7 +872,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
 		return 0;
 	}
 
-	return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);
+	return rdev->ops->set_tx_power(wdev->wiphy, type, DBM_TO_MBM(dbm));
 }
 EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
 
-- 
1.6.3.3


^ permalink raw reply related

* [RFC PATCHv2 2/2] nl80211: Add option to adjust transmit power
From: Juuso Oikarinen @ 2010-06-21 10:39 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1277116766-4764-1-git-send-email-juuso.oikarinen@nokia.com>

This patch adds transmit power setting type and transmit power level attributes
to NL80211_CMD_SET_WIPHY in order to facilitate adjusting of the transmit power
level of the device.

The added attributes allow selection of automatic, limited or fixed transmit
power level, with the level definable in signed mBm format.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 include/linux/nl80211.h |    9 +++++++++
 net/wireless/nl80211.c  |   31 +++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 07aa046..2c87016 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -725,6 +725,12 @@ enum nl80211_commands {
  * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations
  *	connected to this BSS.
  *
+ * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See
+ *      &enum nl80211_tx_power_setting for possible values.
+ * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units.
+ *      This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
+ *      for non-automatic settings.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -882,6 +888,9 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_AP_ISOLATE,
 
+	NL80211_ATTR_WIPHY_TX_POWER_SETTING,
+	NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 41529ac..a999fc1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -153,6 +153,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
 	[NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
 	[NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
+
+	[NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
+	[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
 };
 
 /* policy for the attributes */
@@ -869,6 +872,34 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 			goto bad_res;
 	}
 
+	if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
+		enum nl80211_tx_power_setting type;
+		int idx, mbm = 0;
+
+		if (!rdev->ops->set_tx_power) {
+			return -EOPNOTSUPP;
+			goto bad_res;
+		}
+
+		idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
+		type = nla_get_u32(info->attrs[idx]);
+
+		if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
+		    (type != NL80211_TX_POWER_AUTOMATIC)) {
+			result = -EINVAL;
+			goto bad_res;
+		}
+
+		if (type != NL80211_TX_POWER_AUTOMATIC) {
+			idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
+			mbm = nla_get_u32(info->attrs[idx]);
+		}
+
+		result = rdev->ops->set_tx_power(&rdev->wiphy, type, mbm);
+		if (result)
+			goto bad_res;
+	}
+
 	changed = 0;
 
 	if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH] mac80211: allow selection of minstrel_ht as default rc algo
From: Helmut Schaa @ 2010-06-21  8:59 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Johannes Berg, Felix Fietkau

Allow selection of minstrel_ht as default rate control algorithm. At the
moment minstrel_ht can only be requested by the driver code but not selected
as default in make menuconfig.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
 net/mac80211/Kconfig |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 83eec7a..3ad82cd 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -64,6 +64,11 @@ config MAC80211_RC_DEFAULT_MINSTREL
 	---help---
 	  Select Minstrel as the default rate control algorithm.
 
+config MAC80211_RC_DEFAULT_MINSTREL_HT
+	bool "Minstrel HT"
+	depends on MAC80211_RC_MINSTREL_HT
+	---help---
+	  Select Minstrel HT as the default rate control algorithm.
 
 endchoice
 
@@ -71,6 +76,7 @@ config MAC80211_RC_DEFAULT
 	string
 	default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
 	default "pid" if MAC80211_RC_DEFAULT_PID
+	default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL_HT
 	default ""
 
 endif
-- 
1.6.4.2


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox