Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: 2.6.33 iwl5350 firmware crash
From: reinette chatre @ 2010-04-16 20:07 UTC (permalink / raw)
  To: Andrew Lutomirski
  Cc: ilw@linux.intel.com, linux-wireless@vger.kernel.org, stable
In-Reply-To: <1271442365.14052.13562.camel@rchatre-DESK>

On Fri, 2010-04-16 at 11:26 -0700, reinette chatre wrote:
> On Thu, 2010-04-15 at 14:08 -0700, Andrew Lutomirski wrote:
> > [74944.425130] iwlagn 0000:03:00.0: Microcode SW error detected.
> > Restarting 0x2000000.
> > [74944.425154] iwlagn 0000:03:00.0: Start IWL Error Log Dump:
> > [74944.425160] iwlagn 0000:03:00.0: Status: 0x000212E4, count: 5
> > [74944.425291] iwlagn 0000:03:00.0: Desc
> > Time       data1      data2      line
> > [74944.425301] iwlagn 0000:03:00.0: NMI_INTERRUPT_WDG            (#04)
> > 1638059893 0x00000002 0x07030000 3664
> 
> [...]
> 
> > [74981.401945] ------------[ cut here ]------------
> > [74981.401980] WARNING: at net/mac80211/agg-tx.c:152
> > ___ieee80211_stop_tx_ba_session+0x87/0x8c [mac80211]()
> 
> 
> Please see https://bugzilla.kernel.org/show_bug.cgi?id=15374 - it has
> patches that will help aggregation recovery after this NMI problem.
> Unfortunately there is nothing we can do at this time to the firmware
> error. I'll try to get these patches into 2.6.34 today.

The patches are already included in 2.6.34. I did try to get this
included into 2.6.33 and submitted it to stable on 03/18/2010,
unfortunately it was not accepted.

Reinette



^ permalink raw reply

* Re: [RFC PATCH] mac80211: Prevent running sta_cleanup timer unnecessarily
From: Johannes Berg @ 2010-04-16 20:17 UTC (permalink / raw)
  To: Juuso Oikarinen; +Cc: linux-wireless
In-Reply-To: <1271403308-23416-2-git-send-email-juuso.oikarinen@nokia.com>

On Fri, 2010-04-16 at 10:35 +0300, Juuso Oikarinen wrote:
> The sta_cleanup timer is used to periodically expire buffered frames from the
> tx buf. The timer is executing periodically, regardless of the need for it.
> This is wasting resources.
> 
> Fix this simply by not restarting the sta_cleanup timer if the tx buffer was
> empty. Restart the timer when there is some more tx-traffic.
> 
> Cc: Janne Ylälehto <janne.ylalehto@nokia.com>
> Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
> ---
>  net/mac80211/sta_info.c |   13 ++++++++++---
>  net/mac80211/tx.c       |    7 +++++++
>  2 files changed, 17 insertions(+), 3 deletions(-)
> 
> diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
> index ff0eb94..3de7a22 100644
> --- a/net/mac80211/sta_info.c
> +++ b/net/mac80211/sta_info.c
> @@ -575,7 +575,7 @@ static int sta_info_buffer_expired(struct sta_info *sta,
>  }
>  
> 
> -static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
> +static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
>  					     struct sta_info *sta)
>  {
>  	unsigned long flags;
> @@ -583,7 +583,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
>  	struct ieee80211_sub_if_data *sdata;
>  
>  	if (skb_queue_empty(&sta->ps_tx_buf))
> -		return;
> +		return false;
>  
>  	for (;;) {
>  		spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
> @@ -608,6 +608,8 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
>  		if (skb_queue_empty(&sta->ps_tx_buf))
>  			sta_info_clear_tim_bit(sta);
>  	}
> +
> +	return true;
>  }
>  
>  static int __must_check __sta_info_destroy(struct sta_info *sta)
> @@ -755,15 +757,20 @@ static void sta_info_cleanup(unsigned long data)
>  {
>  	struct ieee80211_local *local = (struct ieee80211_local *) data;
>  	struct sta_info *sta;
> +	bool timer_needed = false;
>  
>  	rcu_read_lock();
>  	list_for_each_entry_rcu(sta, &local->sta_list, list)
> -		sta_info_cleanup_expire_buffered(local, sta);
> +		if (sta_info_cleanup_expire_buffered(local, sta))
> +			timer_needed = true;
>  	rcu_read_unlock();
>  
>  	if (local->quiescing)
>  		return;
>  
> +	if (!timer_needed)
> +		return;
> +
>  	local->sta_cleanup.expires =
>  		round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
>  	add_timer(&local->sta_cleanup);
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> index 2cb7726..e2aa972 100644
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -429,6 +429,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
>  	struct sta_info *sta = tx->sta;
>  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
>  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
> +	struct ieee80211_local *local = tx->local;
>  	u32 staflags;
>  
>  	if (unlikely(!sta ||
> @@ -476,6 +477,12 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
>  		info->control.vif = &tx->sdata->vif;
>  		info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
>  		skb_queue_tail(&sta->ps_tx_buf, tx->skb);
> +
> +		if (!timer_pending(&local->sta_cleanup))
> +			mod_timer(&local->sta_cleanup,
> +				  round_jiffies(jiffies +
> +						STA_INFO_CLEANUP_INTERVAL));
> +

Why bother to check !timer_pending?

johannes


^ permalink raw reply

* timeout in zd1211rw with zotac mini-itx (geforce 9300)
From: Tsuwei Chen @ 2010-04-16 20:34 UTC (permalink / raw)
  To: zd1211-devs; +Cc: linux-wireless

Has anyone use the zd1211 usb adapter with mini-itx board based on
geforce 9300? I have been experience some annoying issues ever since I
got this motherboard. The problem is that sometime the card just
cannot be switched on. It complains about ioread32() error -110. And I
have spent a few days and try a few different combination, and here is
what I have found so far:

1, with 1 wifi adapter directly plugged into the board, the wifi
adapter works fine most of the time (have seen a couple failure, but
is hard to reproduce)
2. with 1 wifi adapter, plugged in through a USB hub, the driver
complains ioread32 error. I've try 2 USB hubs: a cheap 4-port USB
dongle and also the USB hubs built into my DELL monitor. Both showed
the same problem.
3. If I plugged in 2 wifi adapters directly to the board, more than
50% of chance one of the wifi adapter would fail during the 'ifconifg
up'.

I tried to dig our more on this. I am using kernel 2.6.24-26 (ubuntu).
I had turned on the debug message output and I have traced out that
the failure was first detected in the zd_mac_open(). Probably around
the call to zd_chip_switch_radio_on(). The error message is printed in
the zd_usb_ioread16v(), and probably indicate the driver is
experiencing a timeout while it is trying to read the register from
the adapter.

What exactly does this mean? Why adding a usb hub cause such a huge
differnce? Has anyone experienced similar problem before? Any pointer
that can help me solve this problem is appreciated.

BTW, I never had this problem before when I was still using a regular
HP desktop PC, even with the same version of kernel and same USB hub.
I switched to mini-itx because I am building a small system. So if
anyone is currently using this adapter with a mini-ITX board, please
also let me know which model you use.

TIA,
Tsuwei

^ permalink raw reply

* Re: timeout in zd1211rw with zotac mini-itx (geforce 9300)
From: Gábor Stefanik @ 2010-04-16 20:51 UTC (permalink / raw)
  To: Tsuwei Chen; +Cc: zd1211-devs, linux-wireless
In-Reply-To: <k2r8108ad761004161334x894f9298xf3728846ff69b36b@mail.gmail.com>

On Fri, Apr 16, 2010 at 10:34 PM, Tsuwei Chen <tsuwei@gmail.com> wrote:
> Has anyone use the zd1211 usb adapter with mini-itx board based on
> geforce 9300? I have been experience some annoying issues ever since I
> got this motherboard. The problem is that sometime the card just
> cannot be switched on. It complains about ioread32() error -110. And I
> have spent a few days and try a few different combination, and here is
> what I have found so far:
>
> 1, with 1 wifi adapter directly plugged into the board, the wifi
> adapter works fine most of the time (have seen a couple failure, but
> is hard to reproduce)
> 2. with 1 wifi adapter, plugged in through a USB hub, the driver
> complains ioread32 error. I've try 2 USB hubs: a cheap 4-port USB
> dongle and also the USB hubs built into my DELL monitor. Both showed
> the same problem.
> 3. If I plugged in 2 wifi adapters directly to the board, more than
> 50% of chance one of the wifi adapter would fail during the 'ifconifg
> up'.
>
> I tried to dig our more on this. I am using kernel 2.6.24-26 (ubuntu).

Please try a more recent kernel - 2.6.24 contains
zd1211rw-ieee80211softmac, which is no longer developed.

> I had turned on the debug message output and I have traced out that
> the failure was first detected in the zd_mac_open(). Probably around
> the call to zd_chip_switch_radio_on(). The error message is printed in
> the zd_usb_ioread16v(), and probably indicate the driver is
> experiencing a timeout while it is trying to read the register from
> the adapter.
>
> What exactly does this mean? Why adding a usb hub cause such a huge
> differnce? Has anyone experienced similar problem before? Any pointer
> that can help me solve this problem is appreciated.
>
> BTW, I never had this problem before when I was still using a regular
> HP desktop PC, even with the same version of kernel and same USB hub.
> I switched to mini-itx because I am building a small system. So if
> anyone is currently using this adapter with a mini-ITX board, please
> also let me know which model you use.
>
> TIA,
> Tsuwei
> --
> 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
>



-- 
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)

^ permalink raw reply

* Re: [PATCH 2/2] iwmc3200wifi: check sparse endianness annotations
From: Pavel Roskin @ 2010-04-16 20:55 UTC (permalink / raw)
  To: Zhu Yi; +Cc: linville, linux-wireless, Samuel Ortiz
In-Reply-To: <1271381324-21044-2-git-send-email-yi.zhu@intel.com>

On Fri, 2010-04-16 at 09:28 +0800, Zhu Yi wrote:
> From: Samuel Ortiz <sameo@linux.intel.com>
> 
> Add -D__CHECK_ENDIAN__ to driver ccflags so that sparse will
> always check endianness by default.

I believe it's wrong.  I would be fine with enabling __CHECK_ENDIAN__
for the whole kernel by default (perhaps with an option to disable it).
But there is no reason why some particular drivers need that check more
than the rest of the kernel.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: [PATCH 2/2] iwmc3200wifi: check sparse endianness annotations
From: Johannes Berg @ 2010-04-16 20:57 UTC (permalink / raw)
  To: Pavel Roskin; +Cc: Zhu Yi, linville, linux-wireless, Samuel Ortiz
In-Reply-To: <1271451350.16507.2.camel@mj>

On Fri, 2010-04-16 at 16:55 -0400, Pavel Roskin wrote:
> On Fri, 2010-04-16 at 09:28 +0800, Zhu Yi wrote:
> > From: Samuel Ortiz <sameo@linux.intel.com>
> > 
> > Add -D__CHECK_ENDIAN__ to driver ccflags so that sparse will
> > always check endianness by default.
> 
> I believe it's wrong.  I would be fine with enabling __CHECK_ENDIAN__
> for the whole kernel by default (perhaps with an option to disable it).
> But there is no reason why some particular drivers need that check more
> than the rest of the kernel.

We've done it on other drivers -- we can't do it for all of the kernel
because that would drown people in warnings, but for those drivers that
_should_ be clean it ought to be fine to add it by default.

johannes


^ permalink raw reply

* Re: [ath5k-devel] [PATCH] ath5k/ath9k: Fix 64 bits TSF reads
From: Pavel Roskin @ 2010-04-16 21:13 UTC (permalink / raw)
  To: Benoit Papillault; +Cc: lrodriguez, ath5k-devel, linux-wireless, ath9k-devel
In-Reply-To: <1271369246-6892-1-git-send-email-benoit.papillault@free.fr>

On Fri, 2010-04-16 at 00:07 +0200, Benoit Papillault wrote:

> It follows the logic mentionned by Derek, with only 2 register reads
> needed at each additional steps instead of 3 (the minimum number of
> register reads is still 3).

I would prefer an approach whereas tsf_upper2 or tsf_upper1 is chosen
based on whether tsf_lower is more or less than 0x80000000 if
(tsf_upper2 - tsf_upper1) is 1.  If the difference is not 0 or 1, either
the hardware is broken or the kernel was stuck for so long (71 minutes!)
that getting the exact tsf should be the least worry.  That's when
WARN_ON would be appropriate.

The problem with overengineered code is that it doesn't break when it's
better to break and expose the problem :-)

But it's just a suggestion, not a NACK.  It's better to have some fix
than no fix at all.
 
-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: [PATCH] wireless: rt2x00: rt2800usb: delete Allwin devices
From: Gertjan van Wingerde @ 2010-04-16 21:19 UTC (permalink / raw)
  To: Xose Vazquez Perez; +Cc: John W. Linville, Ivo Van Doorn, linux-wireless, users
In-Reply-To: <20100416134326.GD8554@tuxdriver.com>

On 04/16/10 15:43, John W. Linville wrote:
> On Fri, Apr 16, 2010 at 01:17:07PM +0200, Ivo Van Doorn wrote:
>> On Fri, Apr 16, 2010 at 12:16 PM, Xose Vazquez Perez
>> <xose.vazquez@gmail.com> wrote:
>>> Common sense says:
>>> (0x8516, 0x2070) is RT2070
>>> (0x8516, 0x2770) is RT2770
>>> (0x8516, 0x2870) is RT2870
>>> [...]
>>>
>>> but Allwin doesn't sell USB dongles nor PCI boards, only voip-routers
>>> http://www.allwin.com.tw/eng/modules/tinyd0/content/index.php?id=1
>>
>> But how about the case where the company name is wrong and the ID's are valid?
>> That means we only should update the comment, rather then deleting the ID's.
> 
> Or the case where someone ports Linux to those voip routers...

And finally, these devices are still mentioned in the Ralink windows driver,
so we must assume that they actually exist.

However, the common sense approach may be appropriate, so moving these devices
to the correct section does seem okay.

---
Gertjan.

^ permalink raw reply

* Re: [PATCH 2/2] iwmc3200wifi: check sparse endianness annotations
From: Pavel Roskin @ 2010-04-16 21:34 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Zhu Yi, linville, linux-wireless, Samuel Ortiz
In-Reply-To: <1271451466.8043.0.camel@jlt3.sipsolutions.net>

On Fri, 2010-04-16 at 22:57 +0200, Johannes Berg wrote:

> We've done it on other drivers -- we can't do it for all of the kernel
> because that would drown people in warnings, but for those drivers that
> _should_ be clean it ought to be fine to add it by default.

Oh, I see, there are several precedents.

That said, there are not many warnings added by __CHECK_ENDIAN__.  In my
x86_64 configuration, sparse produces 2316 lines of output without
__CHECK_ENDIAN__ and 3526 lines with __CHECK_ENDIAN__, a 52% increase.
That's hardly "drowning".

Also, the warnings about endianess are perhaps the most useful of all
sparse warnings.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: compat-wireless doesn't compile against 2.6.32 on Ubuntu beta
From: Pavel Roskin @ 2010-04-16 21:50 UTC (permalink / raw)
  To: Andrey Semyonov; +Cc: linux-wireless
In-Reply-To: <t2wd01f95791004151011n1a5077a3oca9f7b641b311ac2@mail.gmail.com>

On Thu, 2010-04-15 at 21:11 +0400, Andrey Semyonov wrote:
> I get this when trying to compile current drivers:
> 
> 
> /usr/local/src/compat-wireless-2010-04-14# make
> make -C /lib/modules/2.6.32-19-generic/build
> M=/usr/local/src/compat-wireless-2010-04-14 modules
> make[1]: Вход в каталог `/usr/src/linux-headers-2.6.32-19-generic'
>  CC [M]  /usr/local/src/compat-wireless-2010-04-14/net/mac80211/main.o
> /usr/local/src/compat-wireless-2010-04-14/net/mac80211/main.c: In
> function 'ieee80211_alloc_hw':
> /usr/local/src/compat-wireless-2010-04-14/net/mac80211/main.c:394:
> error: implicit declaration of function '__hw_addr_init'

I confirm the problem.  Basically, the bleeding edge compat-wireless is
useless now.  Perhaps we need a check to to prevent broken tarballs from
being uploaded.  It's better than force users to search for the last
working tarball.

compat-wireless-2.6.34-rc4 should be OK for Linux 2.6.27 and newer,
although it lacks some fixes needed for older kernels.  It also lacks
the experimental wireless code that is not scheduled for Linux 2.6.34.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* [PATCH 0/2] iwlwifi fixes for 2.6.34
From: Reinette Chatre @ 2010-04-16 21:50 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

We include two fixes for 2.6.34. A scan race resulting in system crashes is
fixed with "iwlwifi: fix scan races" - this issue is tracked in
https://bugzilla.kernel.org/show_bug.cgi?id=15667 . The second fixes how
regulatory information is read from the 6000 series EEPROM. Channels that
were previously wrongly identified as not supporting IBSS are now correctly
identified as now supporting IBSS.

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

Johannes Berg (1):
  iwlwifi: fix scan races

Shanyu Zhao (1):
  iwlwifi: correct 6000 EEPROM regulatory address

 drivers/net/wireless/iwlwifi/iwl-6000.c   |    4 +-
 drivers/net/wireless/iwlwifi/iwl-agn.c    |    1 +
 drivers/net/wireless/iwlwifi/iwl-core.c   |    1 -
 drivers/net/wireless/iwlwifi/iwl-core.h   |    2 +-
 drivers/net/wireless/iwlwifi/iwl-dev.h    |    1 +
 drivers/net/wireless/iwlwifi/iwl-eeprom.h |    4 +++
 drivers/net/wireless/iwlwifi/iwl-scan.c   |   31 ++++++++++++++++++----------
 7 files changed, 29 insertions(+), 15 deletions(-)


^ permalink raw reply

* [PATCH 2/2] iwlwifi: correct 6000 EEPROM regulatory address
From: Reinette Chatre @ 2010-04-16 21:50 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Shanyu Zhao, Reinette Chatre
In-Reply-To: <1271454614-14272-1-git-send-email-reinette.chatre@intel.com>

From: Shanyu Zhao <shanyu.zhao@intel.com>

For 6000 series, the 2.4G HT40 band regulatory settings address in EEPROM
was off by 2.

Before the fix, you'll see this in dmesg:
[79535.788877] ieee80211 phy8: U iwl_mod_ht40_chan_info HT40 Ch. 7 [2.4GHz]
WIDE (0x61 0dBm): Ad-Hoc not supported
[79535.788880] ieee80211 phy8: U iwl_mod_ht40_chan_info HT40 Ch. 11 [2.4GHz]
WIDE (0x61 0dBm): Ad-Hoc not supported

And after the fix:
[91132.688706] ieee80211 phy14: U iwl_mod_ht40_chan_info HT40 Ch. 7 [2.4GHz]
IBSS ACTIVE WIDE (0x6f 0dBm): Ad-Hoc supported
[91132.688709] ieee80211 phy14: U iwl_mod_ht40_chan_info HT40 Ch. 11 [2.4GHz]
IBSS ACTIVE WIDE (0x6f 0dBm): Ad-Hoc supported

Signed-off-by: Shanyu Zhao <shanyu.zhao@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-6000.c   |    4 ++--
 drivers/net/wireless/iwlwifi/iwl-eeprom.h |    4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index c4844ad..92b3e64 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -259,7 +259,7 @@ static struct iwl_lib_ops iwl6000_lib = {
 			EEPROM_5000_REG_BAND_3_CHANNELS,
 			EEPROM_5000_REG_BAND_4_CHANNELS,
 			EEPROM_5000_REG_BAND_5_CHANNELS,
-			EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_5000_REG_BAND_52_HT40_CHANNELS
 		},
 		.verify_signature  = iwlcore_eeprom_verify_signature,
@@ -323,7 +323,7 @@ static struct iwl_lib_ops iwl6050_lib = {
 			EEPROM_5000_REG_BAND_3_CHANNELS,
 			EEPROM_5000_REG_BAND_4_CHANNELS,
 			EEPROM_5000_REG_BAND_5_CHANNELS,
-			EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_5000_REG_BAND_52_HT40_CHANNELS
 		},
 		.verify_signature  = iwlcore_eeprom_verify_signature,
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 4e1ba82..8171c70 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -203,6 +203,10 @@ struct iwl_eeprom_enhanced_txpwr {
 #define EEPROM_5000_REG_BAND_52_HT40_CHANNELS  ((0x92)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 22  bytes */
 
+/* 6000 regulatory - indirect access */
+#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS  ((0x80)\
+		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 14  bytes */
+
 /* 6000 and up regulatory tx power - indirect access */
 /* max. elements per section */
 #define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS	(8)
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 1/2] iwlwifi: fix scan races
From: Reinette Chatre @ 2010-04-16 21:50 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1271454614-14272-1-git-send-email-reinette.chatre@intel.com>

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

When an internal scan is started, nothing protects the
is_internal_short_scan variable which can cause crashes,
cf. https://bugzilla.kernel.org/show_bug.cgi?id=15667.
Fix this by making the short scan request use the mutex
for locking, which requires making the request go to a
work struct so that it can sleep.

Reported-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c  |    1 +
 drivers/net/wireless/iwlwifi/iwl-core.c |    1 -
 drivers/net/wireless/iwlwifi/iwl-core.h |    2 +-
 drivers/net/wireless/iwlwifi/iwl-dev.h  |    1 +
 drivers/net/wireless/iwlwifi/iwl-scan.c |   31 ++++++++++++++++++++-----------
 5 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index e4c2e1e..ba0fdba 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3330,6 +3330,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
 
 	cancel_delayed_work_sync(&priv->init_alive_start);
 	cancel_delayed_work(&priv->scan_check);
+	cancel_work_sync(&priv->start_internal_scan);
 	cancel_delayed_work(&priv->alive_start);
 	cancel_work_sync(&priv->beacon_update);
 	del_timer_sync(&priv->statistics_periodic);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 894bcb8..1459cdb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -3357,7 +3357,6 @@ static void iwl_force_rf_reset(struct iwl_priv *priv)
 	 */
 	IWL_DEBUG_INFO(priv, "perform radio reset.\n");
 	iwl_internal_short_hw_scan(priv);
-	return;
 }
 
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 732590f..36940a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -506,7 +506,7 @@ void iwl_init_scan_params(struct iwl_priv *priv);
 int iwl_scan_cancel(struct iwl_priv *priv);
 int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
 int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
-int iwl_internal_short_hw_scan(struct iwl_priv *priv);
+void iwl_internal_short_hw_scan(struct iwl_priv *priv);
 int iwl_force_reset(struct iwl_priv *priv, int mode);
 u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
 		       const u8 *ie, int ie_len, int left);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 6054c5f..ef1720a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1296,6 +1296,7 @@ struct iwl_priv {
 	struct work_struct tt_work;
 	struct work_struct ct_enter;
 	struct work_struct ct_exit;
+	struct work_struct start_internal_scan;
 
 	struct tasklet_struct irq_tasklet;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index bd2f7c4..5062f4e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -469,6 +469,8 @@ EXPORT_SYMBOL(iwl_init_scan_params);
 
 static int iwl_scan_initiate(struct iwl_priv *priv)
 {
+	WARN_ON(!mutex_is_locked(&priv->mutex));
+
 	IWL_DEBUG_INFO(priv, "Starting scan...\n");
 	set_bit(STATUS_SCANNING, &priv->status);
 	priv->is_internal_short_scan = false;
@@ -546,24 +548,31 @@ EXPORT_SYMBOL(iwl_mac_hw_scan);
  * internal short scan, this function should only been called while associated.
  * It will reset and tune the radio to prevent possible RF related problem
  */
-int iwl_internal_short_hw_scan(struct iwl_priv *priv)
+void iwl_internal_short_hw_scan(struct iwl_priv *priv)
 {
-	int ret = 0;
+	queue_work(priv->workqueue, &priv->start_internal_scan);
+}
+
+static void iwl_bg_start_internal_scan(struct work_struct *work)
+{
+	struct iwl_priv *priv =
+		container_of(work, struct iwl_priv, start_internal_scan);
+
+	mutex_lock(&priv->mutex);
 
 	if (!iwl_is_ready_rf(priv)) {
-		ret = -EIO;
 		IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
-		goto out;
+		goto unlock;
 	}
+
 	if (test_bit(STATUS_SCANNING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
-		ret = -EAGAIN;
-		goto out;
+		goto unlock;
 	}
+
 	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
-		ret = -EAGAIN;
-		goto out;
+		goto unlock;
 	}
 
 	priv->scan_bands = 0;
@@ -576,9 +585,8 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv)
 	set_bit(STATUS_SCANNING, &priv->status);
 	priv->is_internal_short_scan = true;
 	queue_work(priv->workqueue, &priv->request_scan);
-
-out:
-	return ret;
+ unlock:
+	mutex_unlock(&priv->mutex);
 }
 EXPORT_SYMBOL(iwl_internal_short_hw_scan);
 
@@ -964,6 +972,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
 	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
 	INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
 	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
+	INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
 	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
 }
 EXPORT_SYMBOL(iwl_setup_scan_deferred_work);
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 00/21] iwlwifi updates for 2.6.35
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

We include a variety of changes. For statistics display in debugfs we add
some generic functions that will help us add similar functions for all
devices soon. Included are a few cleanups to the scanning code, removing
unnecessary code and making code synchronous when it can sleep. We include
some preparation work for the support of new hardware. The rest is small
stand alone cleanups.

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

Abhijeet Kolekar (1):
  iwlwifi: add debugfs ops to iwlwifi

Johannes Berg (11):
  iwlwifi: remove scan_bands logic
  iwlwifi: correct atomic bitops usage
  iwlwifi: remove next_scan_jiffies
  iwlwifi: remove scan_pass_start
  iwlwifi: rename priv->scan to priv->scan_cmd
  iwlwifi: trigger scan synchronously
  iwlwifi: make BT coex config a virtual method
  iwlwifi: rename TX_CMD_FLG_BT_DIS_MSK
  iwlwifi: don't check monitor for scanning
  iwlwifi: remove monitor check
  iwlwifi: make scan antenna forcing more generic

Shanyu Zhao (2):
  iwlwifi: bring up 6000 Series 2x2 AGN Gen2 adapters
  iwlwifi: remove redundant iwl_dump_lq_cmd()

Wey-Yi Guy (7):
  iwlwifi: set correct single/dual stream mask
  iwlwifi: more generic eeprom defines
  iwlwifi: remove duplicated debug functions
  iwlwifi: add hw revision for 6000g2 NIC
  iwlwifi: PA type for 6000g2 series
  iwlwifi: sanity check for turn on aggregation tid
  iwlwifi: more code clean up for agn devices

 drivers/net/wireless/iwlwifi/Makefile          |    1 +
 drivers/net/wireless/iwlwifi/iwl-1000.c        |    6 +
 drivers/net/wireless/iwlwifi/iwl-3945.c        |    2 +
 drivers/net/wireless/iwlwifi/iwl-3945.h        |    3 +
 drivers/net/wireless/iwlwifi/iwl-4965.c        |   15 +-
 drivers/net/wireless/iwlwifi/iwl-5000.c        |   11 +
 drivers/net/wireless/iwlwifi/iwl-6000.c        |   33 +-
 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c |  834 ++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h |   56 ++
 drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c    |    2 +
 drivers/net/wireless/iwlwifi/iwl-agn-lib.c     |  403 +++++++++++-
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c      |   47 +-
 drivers/net/wireless/iwlwifi/iwl-agn-tx.c      |   42 +-
 drivers/net/wireless/iwlwifi/iwl-agn-ucode.c   |   36 +-
 drivers/net/wireless/iwlwifi/iwl-agn.c         |   50 +--
 drivers/net/wireless/iwlwifi/iwl-agn.h         |    3 +
 drivers/net/wireless/iwlwifi/iwl-commands.h    |    2 +-
 drivers/net/wireless/iwlwifi/iwl-core.c        |   42 +--
 drivers/net/wireless/iwlwifi/iwl-core.h        |   18 +-
 drivers/net/wireless/iwlwifi/iwl-csr.h         |    1 +
 drivers/net/wireless/iwlwifi/iwl-debug.h       |    2 +
 drivers/net/wireless/iwlwifi/iwl-debugfs.c     |  775 +---------------------
 drivers/net/wireless/iwlwifi/iwl-dev.h         |    9 +-
 drivers/net/wireless/iwlwifi/iwl-eeprom.h      |   32 +-
 drivers/net/wireless/iwlwifi/iwl-prph.h        |   80 ++--
 drivers/net/wireless/iwlwifi/iwl-scan.c        |  500 +--------------
 drivers/net/wireless/iwlwifi/iwl-sta.c         |   13 +-
 drivers/net/wireless/iwlwifi/iwl3945-base.c    |   87 +--
 28 files changed, 1599 insertions(+), 1506 deletions(-)
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h


^ permalink raw reply

* [PATCH 02/21] iwlwifi: remove scan_bands logic
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

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

Since mac80211 will now never request scanning
multiple bands, we can remove all the associated
logic and scan a single band only in each scan.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    2 +-
 drivers/net/wireless/iwlwifi/iwl-scan.c     |   59 ++++++++-------------------
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   16 +++----
 3 files changed, 25 insertions(+), 52 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index b2d94c7..ee4cb02 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1054,7 +1054,7 @@ struct iwl_priv {
 	unsigned long scan_pass_start;
 	unsigned long scan_start_tsf;
 	void *scan;
-	int scan_bands;
+	enum ieee80211_band scan_band;
 	struct cfg80211_scan_request *scan_request;
 	bool is_internal_short_scan;
 	u8 scan_tx_ant[IEEE80211_NUM_BANDS];
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index c3b06c4..3904bb4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -223,29 +223,16 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 	clear_bit(STATUS_SCAN_HW, &priv->status);
 
 	IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n",
-		       (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
-						"2.4" : "5.2",
+		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
 		       jiffies_to_msecs(elapsed_jiffies
 					(priv->scan_pass_start, jiffies)));
 
-	/* Remove this scanned band from the list of pending
-	 * bands to scan, band G precedes A in order of scanning
-	 * as seen in iwl_bg_request_scan */
-	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ))
-		priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ);
-	else if (priv->scan_bands &  BIT(IEEE80211_BAND_5GHZ))
-		priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);
-
 	/* If a request to abort was given, or the scan did not succeed
 	 * then we reset the scan state machine and terminate,
 	 * re-queuing another scan if one has been requested */
 	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
 		IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");
 		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-	} else {
-		/* If there are more bands on this scan pass reschedule */
-		if (priv->scan_bands)
-			goto reschedule;
 	}
 
 	if (!priv->is_internal_short_scan)
@@ -259,12 +246,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 		jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));
 
 	queue_work(priv->workqueue, &priv->scan_completed);
-
-	return;
-
-reschedule:
-	priv->scan_pass_start = jiffies;
-	queue_work(priv->workqueue, &priv->request_scan);
 }
 
 void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
@@ -489,10 +470,13 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 {
 	unsigned long flags;
 	struct iwl_priv *priv = hw->priv;
-	int ret, i;
+	int ret;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
+	if (req->n_channels == 0)
+		return -EINVAL;
+
 	mutex_lock(&priv->mutex);
 	spin_lock_irqsave(&priv->lock, flags);
 
@@ -526,10 +510,8 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 		goto out_unlock;
 	}
 
-	priv->scan_bands = 0;
-	for (i = 0; i < req->n_channels; i++)
-		priv->scan_bands |= BIT(req->channels[i]->band);
-
+	/* mac80211 will only ask for one band at a time */
+	priv->scan_band = req->channels[0]->band;
 	priv->scan_request = req;
 
 	ret = iwl_scan_initiate(priv);
@@ -575,11 +557,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
 		goto unlock;
 	}
 
-	priv->scan_bands = 0;
-	if (priv->band == IEEE80211_BAND_5GHZ)
-		priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
-	else
-		priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
+	priv->scan_band = priv->band;
 
 	IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
 	set_bit(STATUS_SCANNING, &priv->status);
@@ -727,11 +705,6 @@ static void iwl_bg_request_scan(struct work_struct *data)
 		goto done;
 	}
 
-	if (!priv->scan_bands) {
-		IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n");
-		goto done;
-	}
-
 	if (!priv->scan) {
 		priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
 				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
@@ -798,9 +771,8 @@ static void iwl_bg_request_scan(struct work_struct *data)
 	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
 	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
 
-
-	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
-		band = IEEE80211_BAND_2GHZ;
+	switch (priv->scan_band) {
+	case IEEE80211_BAND_2GHZ:
 		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
 		chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
 				       >> RXON_FLG_CHANNEL_MODE_POS;
@@ -811,8 +783,8 @@ static void iwl_bg_request_scan(struct work_struct *data)
 			rate_flags = RATE_MCS_CCK_MSK;
 		}
 		scan->good_CRC_th = 0;
-	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
-		band = IEEE80211_BAND_5GHZ;
+		break;
+	case IEEE80211_BAND_5GHZ:
 		rate = IWL_RATE_6M_PLCP;
 		/*
 		 * If active scaning is requested but a certain channel
@@ -827,13 +799,16 @@ static void iwl_bg_request_scan(struct work_struct *data)
 		 */
 		if (priv->cfg->off_channel_workaround)
 			rx_ant = ANT_BC;
-	} else {
+		break;
+	default:
 		IWL_WARN(priv, "Invalid scan band count\n");
 		goto done;
 	}
 
+	band = priv->scan_band;
+
 	priv->scan_tx_ant[band] =
-			 iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
+			iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
 	rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
 	scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 24e9694..e266695 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2852,11 +2852,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 		goto done;
 	}
 
-	if (!priv->scan_bands) {
-		IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n");
-		goto done;
-	}
-
 	if (!priv->scan) {
 		priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) +
 				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
@@ -2934,12 +2929,14 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
 	/* flags + rate selection */
 
-	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
+	switch (priv->scan_band) {
+	case IEEE80211_BAND_2GHZ:
 		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
 		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
 		scan->good_CRC_th = 0;
 		band = IEEE80211_BAND_2GHZ;
-	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
+		break;
+	case IEEE80211_BAND_5GHZ:
 		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
 		/*
 		 * If active scaning is requested but a certain channel
@@ -2948,8 +2945,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 		 */
 		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
 		band = IEEE80211_BAND_5GHZ;
-	} else {
-		IWL_WARN(priv, "Invalid scan band count\n");
+		break;
+	default:
+		IWL_WARN(priv, "Invalid scan band\n");
 		goto done;
 	}
 
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 01/21] iwlwifi: set correct single/dual stream mask
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

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

Even the initial single/dual stream values will be overridden later when
issue link quality command; but still make sense not to use hard-code
value during initialization. Single/Dual stream mask are used to indicate the
best antenna for SISO/MIMO; different NIC has different tx antenna
configuration; so the parameter need to based on the valid tx antenna.

1x2 device: single tx antenna available, only SISO is valid
configuration, but still need to set up MIMO configuration, so set it up
with antenna A & B as default.
2x2 device: two tx antenna available, dual_stream will use both valid
antenna.

3x3 device: three tx antenna available, skip the first antenna and
choice the second and third antenna for dual_stream.

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-rs.c |   13 +++++++++++--
 drivers/net/wireless/iwlwifi/iwl-sta.c    |   12 +++++++++++-
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 3c1cd41..5bc406c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -2557,8 +2557,17 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
 		     lq_sta->active_mimo3_rate);
 
 	/* These values will be overridden later */
-	lq_sta->lq.general_params.single_stream_ant_msk = ANT_A;
-	lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
+	lq_sta->lq.general_params.single_stream_ant_msk =
+		first_antenna(priv->hw_params.valid_tx_ant);
+	lq_sta->lq.general_params.dual_stream_ant_msk =
+		priv->hw_params.valid_tx_ant &
+		~first_antenna(priv->hw_params.valid_tx_ant);
+	if (!lq_sta->lq.general_params.dual_stream_ant_msk) {
+		lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
+	} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
+		lq_sta->lq.general_params.dual_stream_ant_msk =
+			priv->hw_params.valid_tx_ant;
+	}
 
 	/* as default allow aggregation for all tids */
 	lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index d86ecd2..09d9c4d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -451,7 +451,17 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap)
 
 	link_cmd.general_params.single_stream_ant_msk =
 				first_antenna(priv->hw_params.valid_tx_ant);
-	link_cmd.general_params.dual_stream_ant_msk = 3;
+
+	link_cmd.general_params.dual_stream_ant_msk =
+		priv->hw_params.valid_tx_ant &
+		~first_antenna(priv->hw_params.valid_tx_ant);
+	if (!link_cmd.general_params.dual_stream_ant_msk) {
+		link_cmd.general_params.dual_stream_ant_msk = ANT_AB;
+	} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
+		link_cmd.general_params.dual_stream_ant_msk =
+			priv->hw_params.valid_tx_ant;
+	}
+
 	link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
 	link_cmd.agg_params.agg_time_limit =
 		cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 03/21] iwlwifi: correct atomic bitops usage
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

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

With atomic bitops, test_and_{set,clear}_bit
should be used instead of separate test_bit
and set_bit/clear_bit.

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

diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 3904bb4..7982b19 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -68,9 +68,8 @@ int iwl_scan_cancel(struct iwl_priv *priv)
 	}
 
 	if (test_bit(STATUS_SCANNING, &priv->status)) {
-		if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+		if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
 			IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n");
-			set_bit(STATUS_SCAN_ABORTING, &priv->status);
 			queue_work(priv->workqueue, &priv->abort_scan);
 
 		} else
@@ -227,13 +226,13 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 		       jiffies_to_msecs(elapsed_jiffies
 					(priv->scan_pass_start, jiffies)));
 
-	/* If a request to abort was given, or the scan did not succeed
+	/*
+	 * If a request to abort was given, or the scan did not succeed
 	 * then we reset the scan state machine and terminate,
-	 * re-queuing another scan if one has been requested */
-	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+	 * re-queuing another scan if one has been requested
+	 */
+	if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status))
 		IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");
-		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-	}
 
 	if (!priv->is_internal_short_scan)
 		priv->next_scan_jiffies = 0;
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 12/21] iwlwifi: remove redundant iwl_dump_lq_cmd()
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Shanyu Zhao, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

From: Shanyu Zhao <shanyu.zhao@intel.com>

This function is called twice in a row, remove the second one.

Signed-off-by: Shanyu Zhao <shanyu.zhao@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-sta.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 09d9c4d..db93447 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -1206,7 +1206,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
 	iwl_dump_lq_cmd(priv, lq);
 	BUG_ON(init && (cmd.flags & CMD_ASYNC));
 
-	iwl_dump_lq_cmd(priv, lq);
 	ret = iwl_send_cmd(priv, &cmd);
 	if (ret || (cmd.flags & CMD_ASYNC))
 		return ret;
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 04/21] iwlwifi: remove next_scan_jiffies
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

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

This logic is just confusing, if anything it
belongs into mac80211. Also, even if we do
scan during the EAPOL handshake, that will
not cause any problems, just a short delay.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c     |    9 ---------
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    1 -
 drivers/net/wireless/iwlwifi/iwl-scan.c     |   20 --------------------
 drivers/net/wireless/iwlwifi/iwl3945-base.c |    5 -----
 4 files changed, 0 insertions(+), 35 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 73f5fc6..9d300b2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1867,7 +1867,6 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv)
 	iwlcore_commit_rxon(priv);
 }
 
-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
 void iwl_bss_info_changed(struct ieee80211_hw *hw,
 			  struct ieee80211_vif *vif,
 			  struct ieee80211_bss_conf *bss_conf,
@@ -1988,14 +1987,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
 
 			iwl_led_associate(priv);
 
-			/*
-			 * We have just associated, don't start scan too early
-			 * leave time for EAPOL exchange to complete.
-			 *
-			 * XXX: do this in mac80211
-			 */
-			priv->next_scan_jiffies = jiffies +
-					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
 			if (!iwl_is_rfkill(priv))
 				priv->cfg->ops->lib->post_associate(priv);
 		} else
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index ee4cb02..f2d4ca5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1049,7 +1049,6 @@ struct iwl_priv {
 	struct iwl_calib_result calib_results[IWL_CALIB_MAX];
 
 	/* Scan related variables */
-	unsigned long next_scan_jiffies;
 	unsigned long scan_start;
 	unsigned long scan_pass_start;
 	unsigned long scan_start_tsf;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 7982b19..e45b49a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -199,9 +199,6 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
 		       le32_to_cpu(notif->statistics[0]),
 		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
 #endif
-
-	if (!priv->is_internal_short_scan)
-		priv->next_scan_jiffies = 0;
 }
 
 /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
@@ -234,9 +231,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 	if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status))
 		IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");
 
-	if (!priv->is_internal_short_scan)
-		priv->next_scan_jiffies = 0;
-
 	IWL_DEBUG_INFO(priv, "Setting scan to off\n");
 
 	clear_bit(STATUS_SCANNING, &priv->status);
@@ -462,8 +456,6 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
 	return 0;
 }
 
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
-
 int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 		     struct cfg80211_scan_request *req)
 {
@@ -497,18 +489,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 		goto out_unlock;
 	}
 
-	/* We don't schedule scan within next_scan_jiffies period.
-	 * Avoid scanning during possible EAPOL exchange, return
-	 * success immediately.
-	 */
-	if (priv->next_scan_jiffies &&
-	    time_after(priv->next_scan_jiffies, jiffies)) {
-		IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n");
-		queue_work(priv->workqueue, &priv->scan_completed);
-		ret = 0;
-		goto out_unlock;
-	}
-
 	/* mac80211 will only ask for one band at a time */
 	priv->scan_band = req->channels[0]->band;
 	priv->scan_request = req;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index e266695..af32359 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3048,8 +3048,6 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
 	mutex_unlock(&priv->mutex);
 }
 
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
-
 void iwl3945_post_associate(struct iwl_priv *priv)
 {
 	int rc = 0;
@@ -3134,9 +3132,6 @@ void iwl3945_post_associate(struct iwl_priv *priv)
 			   __func__, priv->iw_mode);
 		break;
 	}
-
-	/* we have just associated, don't start scan too early */
-	priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
 }
 
 /*****************************************************************************
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 06/21] iwlwifi: rename priv->scan to priv->scan_cmd
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

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

I keep checking what "priv->scan" is, so rename
it to "priv->scan_cmd" which more clearly tells
us what it is.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c      |    2 +-
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    2 +-
 drivers/net/wireless/iwlwifi/iwl-scan.c     |   10 +++++-----
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   12 ++++++------
 4 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 955315b..3199818 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3400,7 +3400,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
 	iwl_calib_free_results(priv);
 	iwlcore_free_geos(priv);
 	iwl_free_channel_map(priv);
-	kfree(priv->scan);
+	kfree(priv->scan_cmd);
 }
 
 static struct attribute *iwl_sysfs_entries[] = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index a7ffb4f..4007b57 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1051,7 +1051,7 @@ struct iwl_priv {
 	/* Scan related variables */
 	unsigned long scan_start;
 	unsigned long scan_start_tsf;
-	void *scan;
+	void *scan_cmd;
 	enum ieee80211_band scan_band;
 	struct cfg80211_scan_request *scan_request;
 	bool is_internal_short_scan;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index cb3601d..18b89d3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -680,16 +680,16 @@ static void iwl_bg_request_scan(struct work_struct *data)
 		goto done;
 	}
 
-	if (!priv->scan) {
-		priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
-				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-		if (!priv->scan) {
+	if (!priv->scan_cmd) {
+		priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
+					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+		if (!priv->scan_cmd) {
 			IWL_DEBUG_SCAN(priv,
 				       "fail to allocate memory for scan\n");
 			goto done;
 		}
 	}
-	scan = priv->scan;
+	scan = priv->scan_cmd;
 	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
 
 	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index af32359..0f77397 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2852,15 +2852,15 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 		goto done;
 	}
 
-	if (!priv->scan) {
-		priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) +
-				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-		if (!priv->scan) {
+	if (!priv->scan_cmd) {
+		priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
+					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+		if (!priv->scan_cmd) {
 			IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
 			goto done;
 		}
 	}
-	scan = priv->scan;
+	scan = priv->scan_cmd;
 	memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
 
 	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
@@ -4245,7 +4245,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
 	iwl_free_channel_map(priv);
 	iwlcore_free_geos(priv);
-	kfree(priv->scan);
+	kfree(priv->scan_cmd);
 	if (priv->ibss_beacon)
 		dev_kfree_skb(priv->ibss_beacon);
 
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 08/21] iwlwifi: more generic eeprom defines
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

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

Some definition for eeprom apply to more than 5000 series device, change
the name to reflect it for easy reading.

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-lib.c   |   14 +++++-----
 drivers/net/wireless/iwlwifi/iwl-agn-ucode.c |    2 +-
 drivers/net/wireless/iwlwifi/iwl-eeprom.h    |   32 +++++++++++++-------------
 3 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 048c615..2d00e83 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -331,7 +331,7 @@ u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
 	} *hdr;
 
 	hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
-							EEPROM_5000_CALIB_ALL);
+							EEPROM_CALIB_ALL);
 	return hdr->version;
 
 }
@@ -348,22 +348,22 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
 
 	switch (address & INDIRECT_TYPE_MSK) {
 	case INDIRECT_HOST:
-		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST);
+		offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST);
 		break;
 	case INDIRECT_GENERAL:
-		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL);
+		offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL);
 		break;
 	case INDIRECT_REGULATORY:
-		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY);
+		offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY);
 		break;
 	case INDIRECT_CALIBRATION:
-		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION);
+		offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION);
 		break;
 	case INDIRECT_PROCESS_ADJST:
-		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST);
+		offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST);
 		break;
 	case INDIRECT_OTHERS:
-		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS);
+		offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS);
 		break;
 	default:
 		IWL_ERR(priv, "illegal indirect type: 0x%X\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 52ae157..059b70e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -207,7 +207,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)
 {
 	struct iwl_calib_xtal_freq_cmd cmd;
 	__le16 *xtal_calib =
-		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
+		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);
 
 	cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
 	cmd.hdr.first_group = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index ef0e325..9977d5e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -172,22 +172,22 @@ struct iwl_eeprom_enhanced_txpwr {
 #define EEPROM_5000_TX_POWER_VERSION    (4)
 #define EEPROM_5000_EEPROM_VERSION	(0x11A)
 
-/*5000 calibrations */
-#define EEPROM_5000_CALIB_ALL	(INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
-#define EEPROM_5000_XTAL	((2*0x128) | EEPROM_5000_CALIB_ALL)
-#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_5000_CALIB_ALL)
-
-/* 5000 links */
-#define EEPROM_5000_LINK_HOST             (2*0x64)
-#define EEPROM_5000_LINK_GENERAL          (2*0x65)
-#define EEPROM_5000_LINK_REGULATORY       (2*0x66)
-#define EEPROM_5000_LINK_CALIBRATION      (2*0x67)
-#define EEPROM_5000_LINK_PROCESS_ADJST    (2*0x68)
-#define EEPROM_5000_LINK_OTHERS           (2*0x69)
-
-/* 5000 regulatory - indirect access */
-#define EEPROM_5000_REG_SKU_ID ((0x02)\
-		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 4  bytes */
+/* 5000 and up calibration */
+#define EEPROM_CALIB_ALL	(INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
+#define EEPROM_XTAL		((2*0x128) | EEPROM_CALIB_ALL)
+
+/* 5000 temperature */
+#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
+
+/* agn links */
+#define EEPROM_LINK_HOST             (2*0x64)
+#define EEPROM_LINK_GENERAL          (2*0x65)
+#define EEPROM_LINK_REGULATORY       (2*0x66)
+#define EEPROM_LINK_CALIBRATION      (2*0x67)
+#define EEPROM_LINK_PROCESS_ADJST    (2*0x68)
+#define EEPROM_LINK_OTHERS           (2*0x69)
+
+/* agn regulatory - indirect access */
 #define EEPROM_REG_BAND_1_CHANNELS       ((0x08)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 28 bytes */
 #define EEPROM_REG_BAND_2_CHANNELS       ((0x26)\
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 05/21] iwlwifi: remove scan_pass_start
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

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

Since we no longer do a multi-pass scan,
keeping track of how long each pass took
is pointless since there will only be one.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-dev.h  |    1 -
 drivers/net/wireless/iwlwifi/iwl-scan.c |    8 ++------
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index f2d4ca5..a7ffb4f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1050,7 +1050,6 @@ struct iwl_priv {
 
 	/* Scan related variables */
 	unsigned long scan_start;
-	unsigned long scan_pass_start;
 	unsigned long scan_start_tsf;
 	void *scan;
 	enum ieee80211_band scan_band;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index e45b49a..cb3601d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -218,10 +218,10 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 	/* The HW is no longer scanning */
 	clear_bit(STATUS_SCAN_HW, &priv->status);
 
-	IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n",
+	IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n",
 		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
 		       jiffies_to_msecs(elapsed_jiffies
-					(priv->scan_pass_start, jiffies)));
+					(priv->scan_start, jiffies)));
 
 	/*
 	 * If a request to abort was given, or the scan did not succeed
@@ -235,9 +235,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 
 	clear_bit(STATUS_SCANNING, &priv->status);
 
-	IWL_DEBUG_INFO(priv, "Scan took %dms\n",
-		jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));
-
 	queue_work(priv->workqueue, &priv->scan_completed);
 }
 
@@ -449,7 +446,6 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
 	set_bit(STATUS_SCANNING, &priv->status);
 	priv->is_internal_short_scan = false;
 	priv->scan_start = jiffies;
-	priv->scan_pass_start = priv->scan_start;
 
 	queue_work(priv->workqueue, &priv->request_scan);
 
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 10/21] iwlwifi: remove duplicated debug functions
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

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

Use the show uCode statistics function for uCode debugging purposes only; it
is being duplicated in both debugfs and sysfs. remove the one from sysfs.

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.c      |   39 ---------------------------
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   39 ---------------------------
 2 files changed, 0 insertions(+), 78 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index e788722..8ac1546 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3177,44 +3177,6 @@ static ssize_t store_tx_power(struct device *d,
 
 static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
 
-static ssize_t show_statistics(struct device *d,
-			       struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	u32 size = sizeof(struct iwl_notif_statistics);
-	u32 len = 0, ofs = 0;
-	u8 *data = (u8 *)&priv->statistics;
-	int rc = 0;
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	mutex_lock(&priv->mutex);
-	rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
-	mutex_unlock(&priv->mutex);
-
-	if (rc) {
-		len = sprintf(buf,
-			      "Error sending statistics request: 0x%08X\n", rc);
-		return len;
-	}
-
-	while (size && (PAGE_SIZE - len)) {
-		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
-				   PAGE_SIZE - len, 1);
-		len = strlen(buf);
-		if (PAGE_SIZE - len)
-			buf[len++] = '\n';
-
-		ofs += 16;
-		size -= min(size, 16U);
-	}
-
-	return len;
-}
-
-static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
-
 static ssize_t show_rts_ht_protection(struct device *d,
 			     struct device_attribute *attr, char *buf)
 {
@@ -3404,7 +3366,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
 }
 
 static struct attribute *iwl_sysfs_entries[] = {
-	&dev_attr_statistics.attr,
 	&dev_attr_temperature.attr,
 	&dev_attr_tx_power.attr,
 	&dev_attr_rts_ht_protection.attr,
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 06004d0..8da3375 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3657,44 +3657,6 @@ static ssize_t show_channels(struct device *d,
 
 static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
 
-static ssize_t show_statistics(struct device *d,
-			       struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	u32 size = sizeof(struct iwl3945_notif_statistics);
-	u32 len = 0, ofs = 0;
-	u8 *data = (u8 *)&priv->_3945.statistics;
-	int rc = 0;
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	mutex_lock(&priv->mutex);
-	rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
-	mutex_unlock(&priv->mutex);
-
-	if (rc) {
-		len = sprintf(buf,
-			      "Error sending statistics request: 0x%08X\n", rc);
-		return len;
-	}
-
-	while (size && (PAGE_SIZE - len)) {
-		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
-				   PAGE_SIZE - len, 1);
-		len = strlen(buf);
-		if (PAGE_SIZE - len)
-			buf[len++] = '\n';
-
-		ofs += 16;
-		size -= min(size, 16U);
-	}
-
-	return len;
-}
-
-static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
-
 static ssize_t show_antenna(struct device *d,
 			    struct device_attribute *attr, char *buf)
 {
@@ -3814,7 +3776,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
 	&dev_attr_filter_flags.attr,
 	&dev_attr_measurement.attr,
 	&dev_attr_retry_rate.attr,
-	&dev_attr_statistics.attr,
 	&dev_attr_status.attr,
 	&dev_attr_temperature.attr,
 	&dev_attr_tx_power.attr,
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 07/21] iwlwifi: trigger scan synchronously
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

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

Scan requesting doesn't need to be asynchronous
since all code paths leading up to it can sleep.
Make the scan request a new util operation that
is hw-specific (to account for 3945 vs. agn)
and call it right in place.

This patch moves a lot of code into iwlagn as
it need not be in iwlcore.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-3945.c     |    1 +
 drivers/net/wireless/iwlwifi/iwl-3945.h     |    3 +
 drivers/net/wireless/iwlwifi/iwl-4965.c     |    1 +
 drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c |    1 +
 drivers/net/wireless/iwlwifi/iwl-agn-lib.c  |  395 +++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-agn.h      |    3 +
 drivers/net/wireless/iwlwifi/iwl-core.h     |    2 +
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    1 -
 drivers/net/wireless/iwlwifi/iwl-scan.c     |  418 +--------------------------
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   10 +-
 10 files changed, 416 insertions(+), 419 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 15de649..51f1895 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2740,6 +2740,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
 	.get_hcmd_size = iwl3945_get_hcmd_size,
 	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
 	.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
+	.request_scan = iwl3945_request_scan,
 };
 
 static const struct iwl_ops iwl3945_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index b892195..e9674f0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -294,6 +294,9 @@ extern const struct iwl_channel_info *iwl3945_get_channel_info(
 
 extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
 
+/* scanning */
+void iwl3945_request_scan(struct iwl_priv *priv);
+
 /* Requires full declaration of iwl_priv before including */
 #include "iwl-io.h"
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 2e3cda7..0a5f21e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2162,6 +2162,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
 	.gain_computation = iwl4965_gain_computation,
 	.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
 	.calc_rssi = iwl4965_calc_rssi,
+	.request_scan = iwlagn_request_scan,
 };
 
 static struct iwl_lib_ops iwl4965_lib = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index 28bc8f8..231d0e6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -271,4 +271,5 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
 	.chain_noise_reset = iwlagn_chain_noise_reset,
 	.rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag,
 	.calc_rssi = iwlagn_calc_rssi,
+	.request_scan = iwlagn_request_scan,
 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index c465c85..048c615 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -1111,3 +1111,398 @@ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
 	memcpy(&priv->_agn.last_phy_res, pkt->u.raw,
 	       sizeof(struct iwl_rx_phy_res));
 }
+
+static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
+				     enum ieee80211_band band,
+				     struct iwl_scan_channel *scan_ch)
+{
+	const struct ieee80211_supported_band *sband;
+	const struct iwl_channel_info *ch_info;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int i, added = 0;
+	u16 channel = 0;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband) {
+		IWL_ERR(priv, "invalid band\n");
+		return added;
+	}
+
+	active_dwell = iwl_get_active_dwell_time(priv, band, 0);
+	passive_dwell = iwl_get_passive_dwell_time(priv, band);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+	/* only scan single channel, good enough to reset the RF */
+	/* pick the first valid not in-use channel */
+	if (band == IEEE80211_BAND_5GHZ) {
+		for (i = 14; i < priv->channel_count; i++) {
+			if (priv->channel_info[i].channel !=
+			    le16_to_cpu(priv->staging_rxon.channel)) {
+				channel = priv->channel_info[i].channel;
+				ch_info = iwl_get_channel_info(priv,
+					band, channel);
+				if (is_channel_valid(ch_info))
+					break;
+			}
+		}
+	} else {
+		for (i = 0; i < 14; i++) {
+			if (priv->channel_info[i].channel !=
+			    le16_to_cpu(priv->staging_rxon.channel)) {
+					channel =
+						priv->channel_info[i].channel;
+					ch_info = iwl_get_channel_info(priv,
+						band, channel);
+					if (is_channel_valid(ch_info))
+						break;
+			}
+		}
+	}
+	if (channel) {
+		scan_ch->channel = cpu_to_le16(channel);
+		scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+		/* Set txpower levels to defaults */
+		scan_ch->dsp_atten = 110;
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+		added++;
+	} else
+		IWL_ERR(priv, "no valid channel found\n");
+	return added;
+}
+
+static int iwl_get_channels_for_scan(struct iwl_priv *priv,
+				     enum ieee80211_band band,
+				     u8 is_active, u8 n_probes,
+				     struct iwl_scan_channel *scan_ch)
+{
+	struct ieee80211_channel *chan;
+	const struct ieee80211_supported_band *sband;
+	const struct iwl_channel_info *ch_info;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int added, i;
+	u16 channel;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband)
+		return 0;
+
+	active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
+	passive_dwell = iwl_get_passive_dwell_time(priv, band);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+		chan = priv->scan_request->channels[i];
+
+		if (chan->band != band)
+			continue;
+
+		channel = ieee80211_frequency_to_channel(chan->center_freq);
+		scan_ch->channel = cpu_to_le16(channel);
+
+		ch_info = iwl_get_channel_info(priv, band, channel);
+		if (!is_channel_valid(ch_info)) {
+			IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
+					channel);
+			continue;
+		}
+
+		if (!is_active || is_channel_passive(ch_info) ||
+		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
+			scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+		else
+			scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
+
+		if (n_probes)
+			scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+
+		/* Set txpower levels to defaults */
+		scan_ch->dsp_atten = 110;
+
+		/* NOTE: if we were doing 6Mb OFDM for scans we'd use
+		 * power level:
+		 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+		 */
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+
+		IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
+			       channel, le32_to_cpu(scan_ch->type),
+			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+				"ACTIVE" : "PASSIVE",
+			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+			       active_dwell : passive_dwell);
+
+		scan_ch++;
+		added++;
+	}
+
+	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
+	return added;
+}
+
+void iwlagn_request_scan(struct iwl_priv *priv)
+{
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_SCAN_CMD,
+		.len = sizeof(struct iwl_scan_cmd),
+		.flags = CMD_SIZE_HUGE,
+	};
+	struct iwl_scan_cmd *scan;
+	struct ieee80211_conf *conf = NULL;
+	u32 rate_flags = 0;
+	u16 cmd_len;
+	u16 rx_chain = 0;
+	enum ieee80211_band band;
+	u8 n_probes = 0;
+	u8 rx_ant = priv->hw_params.valid_rx_ant;
+	u8 rate;
+	bool is_active = false;
+	int  chan_mod;
+	u8 active_chains;
+
+	conf = ieee80211_get_hw_conf(priv->hw);
+
+	cancel_delayed_work(&priv->scan_check);
+
+	if (!iwl_is_ready(priv)) {
+		IWL_WARN(priv, "request scan called when driver not ready.\n");
+		goto done;
+	}
+
+	/* Make sure the scan wasn't canceled before this queued work
+	 * was given the chance to run... */
+	if (!test_bit(STATUS_SCANNING, &priv->status))
+		goto done;
+
+	/* This should never be called or scheduled if there is currently
+	 * a scan active in the hardware. */
+	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+		IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. "
+			       "Ignoring second request.\n");
+		goto done;
+	}
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
+		goto done;
+	}
+
+	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+		IWL_DEBUG_HC(priv, "Scan request while abort pending.  Queuing.\n");
+		goto done;
+	}
+
+	if (iwl_is_rfkill(priv)) {
+		IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
+		goto done;
+	}
+
+	if (!test_bit(STATUS_READY, &priv->status)) {
+		IWL_DEBUG_HC(priv, "Scan request while uninitialized.  Queuing.\n");
+		goto done;
+	}
+
+	if (!priv->scan_cmd) {
+		priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
+					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+		if (!priv->scan_cmd) {
+			IWL_DEBUG_SCAN(priv,
+				       "fail to allocate memory for scan\n");
+			goto done;
+		}
+	}
+	scan = priv->scan_cmd;
+	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
+
+	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
+	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
+
+	if (iwl_is_associated(priv)) {
+		u16 interval = 0;
+		u32 extra;
+		u32 suspend_time = 100;
+		u32 scan_suspend_time = 100;
+		unsigned long flags;
+
+		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
+		spin_lock_irqsave(&priv->lock, flags);
+		interval = priv->beacon_int;
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		scan->suspend_time = 0;
+		scan->max_out_time = cpu_to_le32(200 * 1024);
+		if (!interval)
+			interval = suspend_time;
+
+		extra = (suspend_time / interval) << 22;
+		scan_suspend_time = (extra |
+		    ((suspend_time % interval) * 1024));
+		scan->suspend_time = cpu_to_le32(scan_suspend_time);
+		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
+			       scan_suspend_time, interval);
+	}
+
+	if (priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+	} else if (priv->scan_request->n_ssids) {
+		int i, p = 0;
+		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+		for (i = 0; i < priv->scan_request->n_ssids; i++) {
+			/* always does wildcard anyway */
+			if (!priv->scan_request->ssids[i].ssid_len)
+				continue;
+			scan->direct_scan[p].id = WLAN_EID_SSID;
+			scan->direct_scan[p].len =
+				priv->scan_request->ssids[i].ssid_len;
+			memcpy(scan->direct_scan[p].ssid,
+			       priv->scan_request->ssids[i].ssid,
+			       priv->scan_request->ssids[i].ssid_len);
+			n_probes++;
+			p++;
+		}
+		is_active = true;
+	} else
+		IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
+
+	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
+	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+	switch (priv->scan_band) {
+	case IEEE80211_BAND_2GHZ:
+		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+		chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
+				       >> RXON_FLG_CHANNEL_MODE_POS;
+		if (chan_mod == CHANNEL_MODE_PURE_40) {
+			rate = IWL_RATE_6M_PLCP;
+		} else {
+			rate = IWL_RATE_1M_PLCP;
+			rate_flags = RATE_MCS_CCK_MSK;
+		}
+		scan->good_CRC_th = 0;
+		break;
+	case IEEE80211_BAND_5GHZ:
+		rate = IWL_RATE_6M_PLCP;
+		/*
+		 * If active scaning is requested but a certain channel
+		 * is marked passive, we can do active scanning if we
+		 * detect transmissions.
+		 */
+		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
+
+		/* Force use of chains B and C (0x6) for scan Rx
+		 * Avoid A (0x1) for the device has off-channel reception
+		 * on A-band.
+		 */
+		if (priv->cfg->off_channel_workaround)
+			rx_ant = ANT_BC;
+		break;
+	default:
+		IWL_WARN(priv, "Invalid scan band count\n");
+		goto done;
+	}
+
+	band = priv->scan_band;
+
+	priv->scan_tx_ant[band] =
+			iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
+	rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
+	scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
+
+	/* In power save mode use one chain, otherwise use all chains */
+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+		/* rx_ant has been set to all valid chains previously */
+		active_chains = rx_ant &
+				((u8)(priv->chain_noise_data.active_chains));
+		if (!active_chains)
+			active_chains = rx_ant;
+
+		IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
+				priv->chain_noise_data.active_chains);
+
+		rx_ant = first_antenna(active_chains);
+	}
+	/* MIMO is not used here, but value is required */
+	rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
+	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
+	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
+	scan->rx_chain = cpu_to_le16(rx_chain);
+	if (!priv->is_internal_short_scan) {
+		cmd_len = iwl_fill_probe_req(priv,
+					(struct ieee80211_mgmt *)scan->data,
+					priv->scan_request->ie,
+					priv->scan_request->ie_len,
+					IWL_MAX_SCAN_SIZE - sizeof(*scan));
+	} else {
+		cmd_len = iwl_fill_probe_req(priv,
+					(struct ieee80211_mgmt *)scan->data,
+					NULL, 0,
+					IWL_MAX_SCAN_SIZE - sizeof(*scan));
+
+	}
+	scan->tx_cmd.len = cpu_to_le16(cmd_len);
+	if (iwl_is_monitor_mode(priv))
+		scan->filter_flags = RXON_FILTER_PROMISC_MSK;
+
+	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
+			       RXON_FILTER_BCON_AWARE_MSK);
+
+	if (priv->is_internal_short_scan) {
+		scan->channel_count =
+			iwl_get_single_channel_for_scan(priv, band,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)]);
+	} else {
+		scan->channel_count =
+			iwl_get_channels_for_scan(priv, band,
+				is_active, n_probes,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)]);
+	}
+	if (scan->channel_count == 0) {
+		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
+		goto done;
+	}
+
+	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+	    scan->channel_count * sizeof(struct iwl_scan_channel);
+	cmd.data = scan;
+	scan->len = cpu_to_le16(cmd.len);
+
+	set_bit(STATUS_SCAN_HW, &priv->status);
+	if (iwl_send_cmd_sync(priv, &cmd))
+		goto done;
+
+	queue_delayed_work(priv->workqueue, &priv->scan_check,
+			   IWL_SCAN_CHECK_WATCHDOG);
+
+	return;
+
+ done:
+	/* Cannot perform scan. Make sure we clear scanning
+	* bits from status so next scan request can be performed.
+	* If we don't clear scanning status bit here all next scan
+	* will fail
+	*/
+	clear_bit(STATUS_SCAN_HW, &priv->status);
+	clear_bit(STATUS_SCANNING, &priv->status);
+	/* inform mac80211 scan aborted */
+	queue_work(priv->workqueue, &priv->scan_completed);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 5d31422..cfee999 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -171,4 +171,7 @@ static inline bool iwl_is_tx_success(u32 status)
 	       (status == TX_STATUS_DIRECT_DONE);
 }
 
+/* scan */
+void iwlagn_request_scan(struct iwl_priv *priv);
+
 #endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 6c3f012..1d91ffd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -105,6 +105,7 @@ struct iwl_hcmd_utils_ops {
 			__le32 *tx_flags);
 	int  (*calc_rssi)(struct iwl_priv *priv,
 			  struct iwl_rx_phy_res *rx_resp);
+	void (*request_scan)(struct iwl_priv *priv);
 };
 
 struct iwl_apm_ops {
@@ -526,6 +527,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
 #define IWL_ACTIVE_QUIET_TIME       cpu_to_le16(10)  /* msec */
 #define IWL_PLCP_QUIET_THRESH       cpu_to_le16(1)  /* packets */
 
+#define IWL_SCAN_CHECK_WATCHDOG		(HZ * 7)
 
 /*******************************************************************************
  * Calibrations - implemented in iwl-calib.c
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 4007b57..dc9d8ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1257,7 +1257,6 @@ struct iwl_priv {
 	struct work_struct scan_completed;
 	struct work_struct rx_replenish;
 	struct work_struct abort_scan;
-	struct work_struct request_scan;
 	struct work_struct beacon_update;
 	struct work_struct tt_work;
 	struct work_struct ct_enter;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 18b89d3..92115f5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -284,150 +284,6 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_get_passive_dwell_time);
 
-static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
-				     enum ieee80211_band band,
-				     struct iwl_scan_channel *scan_ch)
-{
-	const struct ieee80211_supported_band *sband;
-	const struct iwl_channel_info *ch_info;
-	u16 passive_dwell = 0;
-	u16 active_dwell = 0;
-	int i, added = 0;
-	u16 channel = 0;
-
-	sband = iwl_get_hw_mode(priv, band);
-	if (!sband) {
-		IWL_ERR(priv, "invalid band\n");
-		return added;
-	}
-
-	active_dwell = iwl_get_active_dwell_time(priv, band, 0);
-	passive_dwell = iwl_get_passive_dwell_time(priv, band);
-
-	if (passive_dwell <= active_dwell)
-		passive_dwell = active_dwell + 1;
-
-	/* only scan single channel, good enough to reset the RF */
-	/* pick the first valid not in-use channel */
-	if (band == IEEE80211_BAND_5GHZ) {
-		for (i = 14; i < priv->channel_count; i++) {
-			if (priv->channel_info[i].channel !=
-			    le16_to_cpu(priv->staging_rxon.channel)) {
-				channel = priv->channel_info[i].channel;
-				ch_info = iwl_get_channel_info(priv,
-					band, channel);
-				if (is_channel_valid(ch_info))
-					break;
-			}
-		}
-	} else {
-		for (i = 0; i < 14; i++) {
-			if (priv->channel_info[i].channel !=
-			    le16_to_cpu(priv->staging_rxon.channel)) {
-					channel =
-						priv->channel_info[i].channel;
-					ch_info = iwl_get_channel_info(priv,
-						band, channel);
-					if (is_channel_valid(ch_info))
-						break;
-			}
-		}
-	}
-	if (channel) {
-		scan_ch->channel = cpu_to_le16(channel);
-		scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-		scan_ch->active_dwell = cpu_to_le16(active_dwell);
-		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-		/* Set txpower levels to defaults */
-		scan_ch->dsp_atten = 110;
-		if (band == IEEE80211_BAND_5GHZ)
-			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-		else
-			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-		added++;
-	} else
-		IWL_ERR(priv, "no valid channel found\n");
-	return added;
-}
-
-static int iwl_get_channels_for_scan(struct iwl_priv *priv,
-				     enum ieee80211_band band,
-				     u8 is_active, u8 n_probes,
-				     struct iwl_scan_channel *scan_ch)
-{
-	struct ieee80211_channel *chan;
-	const struct ieee80211_supported_band *sband;
-	const struct iwl_channel_info *ch_info;
-	u16 passive_dwell = 0;
-	u16 active_dwell = 0;
-	int added, i;
-	u16 channel;
-
-	sband = iwl_get_hw_mode(priv, band);
-	if (!sband)
-		return 0;
-
-	active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
-	passive_dwell = iwl_get_passive_dwell_time(priv, band);
-
-	if (passive_dwell <= active_dwell)
-		passive_dwell = active_dwell + 1;
-
-	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
-		chan = priv->scan_request->channels[i];
-
-		if (chan->band != band)
-			continue;
-
-		channel = ieee80211_frequency_to_channel(chan->center_freq);
-		scan_ch->channel = cpu_to_le16(channel);
-
-		ch_info = iwl_get_channel_info(priv, band, channel);
-		if (!is_channel_valid(ch_info)) {
-			IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
-					channel);
-			continue;
-		}
-
-		if (!is_active || is_channel_passive(ch_info) ||
-		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
-			scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-		else
-			scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
-
-		if (n_probes)
-			scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
-
-		scan_ch->active_dwell = cpu_to_le16(active_dwell);
-		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-
-		/* Set txpower levels to defaults */
-		scan_ch->dsp_atten = 110;
-
-		/* NOTE: if we were doing 6Mb OFDM for scans we'd use
-		 * power level:
-		 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
-		 */
-		if (band == IEEE80211_BAND_5GHZ)
-			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-		else
-			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-
-		IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
-			       channel, le32_to_cpu(scan_ch->type),
-			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
-				"ACTIVE" : "PASSIVE",
-			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
-			       active_dwell : passive_dwell);
-
-		scan_ch++;
-		added++;
-	}
-
-	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
-	return added;
-}
-
 void iwl_init_scan_params(struct iwl_priv *priv)
 {
 	u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
@@ -447,7 +303,10 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
 	priv->is_internal_short_scan = false;
 	priv->scan_start = jiffies;
 
-	queue_work(priv->workqueue, &priv->request_scan);
+	if (WARN_ON(!priv->cfg->ops->utils->request_scan))
+		return -EOPNOTSUPP;
+
+	priv->cfg->ops->utils->request_scan(priv);
 
 	return 0;
 }
@@ -455,7 +314,6 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
 int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 		     struct cfg80211_scan_request *req)
 {
-	unsigned long flags;
 	struct iwl_priv *priv = hw->priv;
 	int ret;
 
@@ -465,7 +323,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 		return -EINVAL;
 
 	mutex_lock(&priv->mutex);
-	spin_lock_irqsave(&priv->lock, flags);
 
 	if (!iwl_is_ready_rf(priv)) {
 		ret = -EIO;
@@ -494,7 +351,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 out_unlock:
-	spin_unlock_irqrestore(&priv->lock, flags);
 	mutex_unlock(&priv->mutex);
 
 	return ret;
@@ -537,13 +393,15 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
 	IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
 	set_bit(STATUS_SCANNING, &priv->status);
 	priv->is_internal_short_scan = true;
-	queue_work(priv->workqueue, &priv->request_scan);
+
+	if (WARN_ON(!priv->cfg->ops->utils->request_scan))
+		goto unlock;
+
+	priv->cfg->ops->utils->request_scan(priv);
  unlock:
 	mutex_unlock(&priv->mutex);
 }
 
-#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
-
 void iwl_bg_scan_check(struct work_struct *data)
 {
 	struct iwl_priv *priv =
@@ -614,263 +472,6 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
 }
 EXPORT_SYMBOL(iwl_fill_probe_req);
 
-static void iwl_bg_request_scan(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, request_scan);
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_SCAN_CMD,
-		.len = sizeof(struct iwl_scan_cmd),
-		.flags = CMD_SIZE_HUGE,
-	};
-	struct iwl_scan_cmd *scan;
-	struct ieee80211_conf *conf = NULL;
-	u32 rate_flags = 0;
-	u16 cmd_len;
-	u16 rx_chain = 0;
-	enum ieee80211_band band;
-	u8 n_probes = 0;
-	u8 rx_ant = priv->hw_params.valid_rx_ant;
-	u8 rate;
-	bool is_active = false;
-	int  chan_mod;
-	u8 active_chains;
-
-	conf = ieee80211_get_hw_conf(priv->hw);
-
-	mutex_lock(&priv->mutex);
-
-	cancel_delayed_work(&priv->scan_check);
-
-	if (!iwl_is_ready(priv)) {
-		IWL_WARN(priv, "request scan called when driver not ready.\n");
-		goto done;
-	}
-
-	/* Make sure the scan wasn't canceled before this queued work
-	 * was given the chance to run... */
-	if (!test_bit(STATUS_SCANNING, &priv->status))
-		goto done;
-
-	/* This should never be called or scheduled if there is currently
-	 * a scan active in the hardware. */
-	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-		IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. "
-			       "Ignoring second request.\n");
-		goto done;
-	}
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
-		goto done;
-	}
-
-	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-		IWL_DEBUG_HC(priv, "Scan request while abort pending.  Queuing.\n");
-		goto done;
-	}
-
-	if (iwl_is_rfkill(priv)) {
-		IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
-		goto done;
-	}
-
-	if (!test_bit(STATUS_READY, &priv->status)) {
-		IWL_DEBUG_HC(priv, "Scan request while uninitialized.  Queuing.\n");
-		goto done;
-	}
-
-	if (!priv->scan_cmd) {
-		priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
-					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-		if (!priv->scan_cmd) {
-			IWL_DEBUG_SCAN(priv,
-				       "fail to allocate memory for scan\n");
-			goto done;
-		}
-	}
-	scan = priv->scan_cmd;
-	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
-
-	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
-	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
-
-	if (iwl_is_associated(priv)) {
-		u16 interval = 0;
-		u32 extra;
-		u32 suspend_time = 100;
-		u32 scan_suspend_time = 100;
-		unsigned long flags;
-
-		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-		spin_lock_irqsave(&priv->lock, flags);
-		interval = priv->beacon_int;
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		scan->suspend_time = 0;
-		scan->max_out_time = cpu_to_le32(200 * 1024);
-		if (!interval)
-			interval = suspend_time;
-
-		extra = (suspend_time / interval) << 22;
-		scan_suspend_time = (extra |
-		    ((suspend_time % interval) * 1024));
-		scan->suspend_time = cpu_to_le32(scan_suspend_time);
-		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
-			       scan_suspend_time, interval);
-	}
-
-	if (priv->is_internal_short_scan) {
-		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-	} else if (priv->scan_request->n_ssids) {
-		int i, p = 0;
-		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
-		for (i = 0; i < priv->scan_request->n_ssids; i++) {
-			/* always does wildcard anyway */
-			if (!priv->scan_request->ssids[i].ssid_len)
-				continue;
-			scan->direct_scan[p].id = WLAN_EID_SSID;
-			scan->direct_scan[p].len =
-				priv->scan_request->ssids[i].ssid_len;
-			memcpy(scan->direct_scan[p].ssid,
-			       priv->scan_request->ssids[i].ssid,
-			       priv->scan_request->ssids[i].ssid_len);
-			n_probes++;
-			p++;
-		}
-		is_active = true;
-	} else
-		IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
-
-	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
-	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
-	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-	switch (priv->scan_band) {
-	case IEEE80211_BAND_2GHZ:
-		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-		chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
-				       >> RXON_FLG_CHANNEL_MODE_POS;
-		if (chan_mod == CHANNEL_MODE_PURE_40) {
-			rate = IWL_RATE_6M_PLCP;
-		} else {
-			rate = IWL_RATE_1M_PLCP;
-			rate_flags = RATE_MCS_CCK_MSK;
-		}
-		scan->good_CRC_th = 0;
-		break;
-	case IEEE80211_BAND_5GHZ:
-		rate = IWL_RATE_6M_PLCP;
-		/*
-		 * If active scaning is requested but a certain channel
-		 * is marked passive, we can do active scanning if we
-		 * detect transmissions.
-		 */
-		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
-
-		/* Force use of chains B and C (0x6) for scan Rx
-		 * Avoid A (0x1) for the device has off-channel reception
-		 * on A-band.
-		 */
-		if (priv->cfg->off_channel_workaround)
-			rx_ant = ANT_BC;
-		break;
-	default:
-		IWL_WARN(priv, "Invalid scan band count\n");
-		goto done;
-	}
-
-	band = priv->scan_band;
-
-	priv->scan_tx_ant[band] =
-			iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
-	rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
-	scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
-
-	/* In power save mode use one chain, otherwise use all chains */
-	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-		/* rx_ant has been set to all valid chains previously */
-		active_chains = rx_ant &
-				((u8)(priv->chain_noise_data.active_chains));
-		if (!active_chains)
-			active_chains = rx_ant;
-
-		IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
-				priv->chain_noise_data.active_chains);
-
-		rx_ant = first_antenna(active_chains);
-	}
-	/* MIMO is not used here, but value is required */
-	rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
-	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
-	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
-	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
-	scan->rx_chain = cpu_to_le16(rx_chain);
-	if (!priv->is_internal_short_scan) {
-		cmd_len = iwl_fill_probe_req(priv,
-					(struct ieee80211_mgmt *)scan->data,
-					priv->scan_request->ie,
-					priv->scan_request->ie_len,
-					IWL_MAX_SCAN_SIZE - sizeof(*scan));
-	} else {
-		cmd_len = iwl_fill_probe_req(priv,
-					(struct ieee80211_mgmt *)scan->data,
-					NULL, 0,
-					IWL_MAX_SCAN_SIZE - sizeof(*scan));
-
-	}
-	scan->tx_cmd.len = cpu_to_le16(cmd_len);
-	if (iwl_is_monitor_mode(priv))
-		scan->filter_flags = RXON_FILTER_PROMISC_MSK;
-
-	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
-			       RXON_FILTER_BCON_AWARE_MSK);
-
-	if (priv->is_internal_short_scan) {
-		scan->channel_count =
-			iwl_get_single_channel_for_scan(priv, band,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
-	} else {
-		scan->channel_count =
-			iwl_get_channels_for_scan(priv, band,
-				is_active, n_probes,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
-	}
-	if (scan->channel_count == 0) {
-		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
-		goto done;
-	}
-
-	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
-	    scan->channel_count * sizeof(struct iwl_scan_channel);
-	cmd.data = scan;
-	scan->len = cpu_to_le16(cmd.len);
-
-	set_bit(STATUS_SCAN_HW, &priv->status);
-	if (iwl_send_cmd_sync(priv, &cmd))
-		goto done;
-
-	queue_delayed_work(priv->workqueue, &priv->scan_check,
-			   IWL_SCAN_CHECK_WATCHDOG);
-
-	mutex_unlock(&priv->mutex);
-	return;
-
- done:
-	/* Cannot perform scan. Make sure we clear scanning
-	* bits from status so next scan request can be performed.
-	* If we don't clear scanning status bit here all next scan
-	* will fail
-	*/
-	clear_bit(STATUS_SCAN_HW, &priv->status);
-	clear_bit(STATUS_SCANNING, &priv->status);
-	/* inform mac80211 scan aborted */
-	queue_work(priv->workqueue, &priv->scan_completed);
-	mutex_unlock(&priv->mutex);
-}
-
 void iwl_bg_abort_scan(struct work_struct *work)
 {
 	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
@@ -918,7 +519,6 @@ EXPORT_SYMBOL(iwl_bg_scan_completed);
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
 {
 	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
-	INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
 	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
 	INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
 	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 0f77397..06004d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2790,11 +2790,8 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
 
 }
 
-#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
-static void iwl3945_bg_request_scan(struct work_struct *data)
+void iwl3945_request_scan(struct iwl_priv *priv)
 {
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, request_scan);
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_SCAN_CMD,
 		.len = sizeof(struct iwl3945_scan_cmd),
@@ -2808,8 +2805,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
-	mutex_lock(&priv->mutex);
-
 	cancel_delayed_work(&priv->scan_check);
 
 	if (!iwl_is_ready(priv)) {
@@ -2992,7 +2987,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 	queue_delayed_work(priv->workqueue, &priv->scan_check,
 			   IWL_SCAN_CHECK_WATCHDOG);
 
-	mutex_unlock(&priv->mutex);
 	return;
 
  done:
@@ -3006,7 +3000,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
 	/* inform mac80211 scan aborted */
 	queue_work(priv->workqueue, &priv->scan_completed);
-	mutex_unlock(&priv->mutex);
 }
 
 static void iwl3945_bg_restart(struct work_struct *data)
@@ -3785,7 +3778,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
 	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
 	INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
 	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
-	INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
 	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
 	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
 
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 09/21] iwlwifi: bring up 6000 Series 2x2 AGN Gen2 adapters
From: Reinette Chatre @ 2010-04-16 21:52 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ipw3945-devel, Shanyu Zhao, Wey-Yi Guy,
	Reinette Chatre
In-Reply-To: <1271454758-14351-1-git-send-email-reinette.chatre@intel.com>

From: Shanyu Zhao <shanyu.zhao@intel.com>

This patch is to bring up 6000 Series 2x2 AGN Gen2 adapters.
Seperate various version numbers from 6000 Series definitions;
Add module firmware declaration for the new adapters;
Add additional device IDs and subsystem IDs;

Signed-off-by: Shanyu Zhao <shanyu.zhao@intel.com>
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-6000.c   |   20 +++++++++++++-------
 drivers/net/wireless/iwlwifi/iwl-agn.c    |    7 ++++++-
 drivers/net/wireless/iwlwifi/iwl-dev.h    |    2 +-
 drivers/net/wireless/iwlwifi/iwl-eeprom.h |    4 ++++
 4 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index f5d0665..63d27e3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -51,13 +51,14 @@
 /* Highest firmware API version supported */
 #define IWL6000_UCODE_API_MAX 4
 #define IWL6050_UCODE_API_MAX 4
+#define IWL6000G2_UCODE_API_MAX 4
 
 /* Lowest firmware API version supported */
 #define IWL6000_UCODE_API_MIN 4
 #define IWL6050_UCODE_API_MIN 4
+#define IWL6000G2_UCODE_API_MIN 4
 
 #define IWL6000_FW_PRE "iwlwifi-6000-"
-#define IWL6000_G2_FW_PRE "iwlwifi-6005-"
 #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
 #define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api)
 
@@ -65,6 +66,10 @@
 #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
 #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
 
+#define IWL6000G2_FW_PRE "iwlwifi-6005-"
+#define _IWL6000G2_MODULE_FIRMWARE(api) IWL6000G2_FW_PRE #api ".ucode"
+#define IWL6000G2_MODULE_FIRMWARE(api) _IWL6000G2_MODULE_FIRMWARE(api)
+
 static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 {
 	/* want Celsius */
@@ -363,16 +368,16 @@ static const struct iwl_ops iwl6050_ops = {
 /*
  * "i": Internal configuration, use internal Power Amplifier
  */
-struct iwl_cfg iwl6000i_g2_2agn_cfg = {
+struct iwl_cfg iwl6000g2i_2agn_cfg = {
 	.name = "6000 Series 2x2 AGN Gen2",
-	.fw_name_pre = IWL6000_G2_FW_PRE,
-	.ucode_api_max = IWL6000_UCODE_API_MAX,
-	.ucode_api_min = IWL6000_UCODE_API_MIN,
+	.fw_name_pre = IWL6000G2_FW_PRE,
+	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
+	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
 	.mod_params = &iwlagn_mod_params,
@@ -600,3 +605,4 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 
 MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL6000G2_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 3199818..e788722 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3835,7 +3835,12 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 	{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000i_g2_2agn_cfg)},
+
+/* 6x00 Series Gen2 */
+	{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2i_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2i_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2i_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2i_2agn_cfg)},
 
 /* 6x50 WiFi/WiMax Series */
 	{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index dc9d8ae..ff4b47c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -58,7 +58,7 @@ extern struct iwl_cfg iwl5100_abg_cfg;
 extern struct iwl_cfg iwl5150_agn_cfg;
 extern struct iwl_cfg iwl5150_abg_cfg;
 extern struct iwl_cfg iwl6000i_2agn_cfg;
-extern struct iwl_cfg iwl6000i_g2_2agn_cfg;
+extern struct iwl_cfg iwl6000g2i_2agn_cfg;
 extern struct iwl_cfg iwl6000i_2abg_cfg;
 extern struct iwl_cfg iwl6000i_2bg_cfg;
 extern struct iwl_cfg iwl6000_3agn_cfg;
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 9977d5e..95aa202 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -276,6 +276,10 @@ struct iwl_eeprom_enhanced_txpwr {
 #define EEPROM_6050_TX_POWER_VERSION    (4)
 #define EEPROM_6050_EEPROM_VERSION	(0x532)
 
+/* 6x00g2 Specific */
+#define EEPROM_6000G2_TX_POWER_VERSION    (6)
+#define EEPROM_6000G2_EEPROM_VERSION	(0x709)
+
 /* OTP */
 /* lower blocks contain EEPROM image and calibration data */
 #define OTP_LOW_IMAGE_SIZE		(2 * 512 * sizeof(u16)) /* 2 KB */
-- 
1.6.3.3


^ 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