Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: Ath5k/mac80211 triggers WARN_ON in kernel/softirq.c
From: Philip A. Prindeville @ 2009-08-06  1:58 UTC (permalink / raw)
  To: Bob Copeland
  Cc: Michael Buesch, Johannes Berg, jirislaby, mickflemm, lrodriguez,
	wireless
In-Reply-To: <4A73745F.6040709@redfish-solutions.com>

Philip A. Prindeville wrote:
> Bob Copeland wrote:
>   
>> On Thu, Jul 30, 2009 at 10:31 AM, Michael Buesch<mb@bu3sch.de> wrote:
>>   
>>     
>>> Ath5k from today's compat-wireless triggers the following WARNing
>>> on hostapd startup.
>>> [ 1669.799870] ------------[ cut here ]------------
>>> [ 1669.799934] WARNING: at kernel/softirq.c:141 local_bh_enable_ip+0x8b/0xb0()
>>>     
>>>       
>> because ath5k calls ieee80211_beacon_get inside a spin_lock_irqsave()
>> and this is WARN_ON_ONCE(in_irq() || irqs_disabled).
>>
>>   
>>     
>>> [ 1669.799982] Hardware name:
>>> [ 1669.800023] Modules linked in: ath5k mac80211 ath cfg80211
>>> [ 1669.800192] Pid: 24862, comm: hostapd Not tainted 2.6.30.2 #3
>>> [ 1669.800238] Call Trace:
>>> [ 1669.800287]  [<ffffffff80248e3b>] ? local_bh_enable_ip+0x8b/0xb0
>>> [ 1669.800340]  [<ffffffff802432f8>] warn_slowpath_common+0x78/0xd0
>>> [ 1669.800391]  [<ffffffff8024335f>] warn_slowpath_null+0xf/0x20
>>> [ 1669.800441]  [<ffffffff80248e3b>] local_bh_enable_ip+0x8b/0xb0
>>> [ 1669.800493]  [<ffffffff807e0fef>] _spin_unlock_bh+0xf/0x20
>>> [ 1669.800564]  [<ffffffffa0040b92>] ieee80211_beacon_get+0x2c2/0x2d0 [mac80211]
>>>     
>>>       
>> I guess this is the first victim of spin_lock_bh conversion?
>>
>>   
>>     
>
> I just booted with compat-wireless-2009-07-30 built against 2.6.27.26
> and am also seeing:
>
> ------------[ cut here ]------------
> WARNING: at kernel/softirq.c:136 _local_bh_enable_ip+0x2f/0x7c()
> Modules linked in: lm90 hwmon scx200_acb i2c_core bridge stp llc dummy ath5k mac80211 ath cfg80211 rfkill_backport dahdi_dummy dahdi sha512_generic sha256_generic deflate zlib_deflate arc4 ecb sha1_generic blowfish des_generic cbc cryptosoft cryptodev(P) ocf(P) geodewdt geode_rng geode_aes crypto_blkcipher via_rhine rtc
> Pid: 1615, comm: hostapd Tainted: P          2.6.27.26-astlinux #1
>  [<c0116739>] warn_on_slowpath+0x40/0x63
>  [<c0127c01>] hrtimer_forward+0xe2/0xfe
>  [<c01ccf78>] rb_insert_color+0x8c/0xad
>  [<c0127d69>] enqueue_hrtimer+0xc8/0xd3
>  [<c0112014>] calc_delta_fair+0x16/0x24
>  [<c0249cd1>] __alloc_skb+0x4b/0x108
>  [<d0920dfb>] ieee80211_beacon_add_tim+0x4f/0x111 [mac80211]
>  [<c011a194>] _local_bh_enable_ip+0x2f/0x7c
>  [<d0921167>] ieee80211_beacon_get+0xe9/0x262 [mac80211]
>  [<d08ed5f5>] ath5k_beacon_update+0x2b/0x1a5 [ath5k]
>  [<c02a2cfb>] schedule_timeout+0x13/0x8f
>  [<d08ef81a>] ath5k_bss_info_changed+0x118/0x16e [ath5k]
>  [<d08ef702>] ath5k_bss_info_changed+0x0/0x16e [ath5k]
>  [<d091060d>] ieee80211_bss_info_change_notify+0x141/0x151 [mac80211]
>  [<d091bc2e>] ieee80211_config_beacon+0x142/0x153 [mac80211]
>  [<d091c0b3>] ieee80211_add_beacon+0x0/0x1c [mac80211]
>  [<d08ce6ee>] nl80211_addset_beacon+0x13f/0x171 [cfg80211]
>  [<c0262915>] genl_rcv_msg+0x13a/0x154
>  [<c02627db>] genl_rcv_msg+0x0/0x154
>  [<c026073d>] netlink_rcv_skb+0x2d/0x72
>  [<c02621c7>] genl_rcv+0x14/0x17
>  [<c0260605>] netlink_unicast+0xd1/0x125
>  [<c02613fb>] netlink_sendmsg+0x1ee/0x1fb
>  [<c02445ec>] __sock_sendmsg+0x20/0x24
>  [<c0245331>] sock_sendmsg+0x95/0xad
>  [<c0125714>] autoremove_wake_function+0x0/0x2b
>  [<c0112014>] calc_delta_fair+0x16/0x24
>  [<c0112266>] __dequeue_entity+0x1f/0x71
>  [<c013ab79>] page_count+0x8/0x14
>  [<c013aca6>] get_pageblock_flags_group+0xf/0x50
>  [<c024b551>] verify_iovec+0x3e/0x6d
>  [<c02454d6>] sys_sendmsg+0x18d/0x1ed
>  [<c0113a7b>] __wake_up+0x1d/0x45
>  [<c0113a93>] __wake_up+0x35/0x45
>  [<c0113a7b>] __wake_up+0x1d/0x45
>  [<c0113a93>] __wake_up+0x35/0x45
>  [<c024dc8e>] dev_name_hash+0x13/0x42
>  [<c024dc8e>] dev_name_hash+0x13/0x42
>  [<c024dcec>] __dev_get_by_name+0x2f/0x39
>  [<c02484a4>] sk_alloc+0x30/0x36
>  [<c011a1d7>] _local_bh_enable_ip+0x72/0x7c
>  [<c0246dd0>] lock_sock_nested+0xb1/0xb8
>  [<c011a1d7>] _local_bh_enable_ip+0x72/0x7c
>  [<c0246377>] sys_socketcall+0x15b/0x193
>  [<c0152703>] sys_close+0x75/0xc5
>  [<c01038b6>] syscall_call+0x7/0xb
>  [<c02a0000>] pci_read_bridge_bases+0x273/0x298
>  =======================
> ---[ end trace 5a73e54cdc253a36 ]---
>
>
> I'll try again after an update fixing this (backing it out?) gets posted.
>
> BTW:  Where does scripts/markup_oops.pl live?
>
> -Philip
>
>
>   

Seeing similar issues with 2009-08-04, an AR5413 card, and 2.6.27.26:

------------[ cut here ]------------
WARNING: at kernel/softirq.c:136 _local_bh_enable_ip+0x2f/0x7c()
Modules linked in: lm90 hwmon scx200_acb i2c_core bridge stp llc br2684 solos_pci atm dummy ipv6 dahdi_dummy dahdi sha512_generic sha256_generic deflate zlib_deflate sha1_generic blowfish des_generic cbc cryptosoft cryptodev(P) ocf(P) geodewdt rtc arc4 ecb ath5k mac80211 ath usblp cfg80211 rfkill_backport cs5535_gpio geode_aes crypto_blkcipher via_rhine geode_rng
Pid: 3170, comm: hostapd Tainted: P          2.6.27.26-astlinux #1
 [<c0116739>] warn_on_slowpath+0x40/0x63
 [<c013b951>] __alloc_pages_internal+0x65/0x324
 [<c0112014>] calc_delta_fair+0x16/0x24
 [<c0249cd1>] __alloc_skb+0x4b/0x108
 [<d08b9dfb>] ieee80211_beacon_add_tim+0x4f/0x111 [mac80211]
 [<c011a194>] _local_bh_enable_ip+0x2f/0x7c
 [<d08ba167>] ieee80211_beacon_get+0xe9/0x262 [mac80211]
 [<d08865f5>] ath5k_beacon_update+0x2b/0x1a5 [ath5k]
 [<c02a2cfb>] schedule_timeout+0x13/0x8f
 [<d088881a>] ath5k_bss_info_changed+0x118/0x16e [ath5k]
 [<d0888702>] ath5k_bss_info_changed+0x0/0x16e [ath5k]
 [<d08a960d>] ieee80211_bss_info_change_notify+0x141/0x151 [mac80211]
 [<d08b4c2e>] ieee80211_config_beacon+0x142/0x153 [mac80211]
 [<d08b50b3>] ieee80211_add_beacon+0x0/0x1c [mac80211]
 [<d08676fa>] nl80211_addset_beacon+0x13f/0x171 [cfg80211]
 [<c0262915>] genl_rcv_msg+0x13a/0x154
 [<c02627db>] genl_rcv_msg+0x0/0x154
 [<c026073d>] netlink_rcv_skb+0x2d/0x72
 [<c02621c7>] genl_rcv+0x14/0x17
 [<c0260605>] netlink_unicast+0xd1/0x125
 [<c02613fb>] netlink_sendmsg+0x1ee/0x1fb
 [<c02445ec>] __sock_sendmsg+0x20/0x24
 [<c0245331>] sock_sendmsg+0x95/0xad
 [<c0125714>] autoremove_wake_function+0x0/0x2b
 [<c0125714>] autoremove_wake_function+0x0/0x2b
 [<c0113a7b>] __wake_up+0x1d/0x45
 [<c0113a93>] __wake_up+0x35/0x45
 [<c025f957>] netlink_unlock_table+0x23/0x25
 [<c024b551>] verify_iovec+0x3e/0x6d
 [<c02454d6>] sys_sendmsg+0x18d/0x1ed
 [<c013dbeb>] mark_page_accessed+0x35/0x45
 [<c014e6ff>] shmem_fault+0x62/0x6e
 [<c01b5f80>] unionfs_fault+0x48/0x50
 [<c024dc8e>] dev_name_hash+0x13/0x42
 [<c024dc8e>] dev_name_hash+0x13/0x42
 [<c024dcec>] __dev_get_by_name+0x2f/0x39
 [<c011a1d7>] _local_bh_enable_ip+0x72/0x7c
 [<c0246dd0>] lock_sock_nested+0xb1/0xb8
 [<c011a1d7>] _local_bh_enable_ip+0x72/0x7c
 [<c0246377>] sys_socketcall+0x15b/0x193
 [<c0152703>] sys_close+0x75/0xc5
 [<c01038b6>] syscall_call+0x7/0xb
 [<c02a0000>] pci_read_bridge_bases+0x273/0x298
 =======================
---[ end trace c32282ee6886491c ]---



Who's working on the beaconing interrupts (vs. tasklet) stuff?

-Philip



^ permalink raw reply

* Re: [PATCH] nl80211: fix attrtype and value for NL80211_ATTR_SUPPORTED_COMMANDS
From: Zhu Yi @ 2009-08-06  1:46 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <1249486901.6902.6.camel@johannes.local>

On Wed, 2009-08-05 at 23:41 +0800, Johannes Berg wrote: 
> On Wed, 2009-08-05 at 17:28 +0800, Zhu Yi wrote:
> > The patch fixes the misuse between attrtype and value for the
> > CMD list nested in NL80211_ATTR_SUPPORTED_COMMANDS attribute.
> 
> No? It was this way intentionally.
> 
> > --- a/net/wireless/nl80211.c
> > +++ b/net/wireless/nl80211.c
> > @@ -520,7 +520,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
> >  	 do {							\
> >  		if (dev->ops->op) {				\
> >  			i++;					\
> > -			NLA_PUT_U32(msg, i, NL80211_CMD_ ## n);	\
> > +			NLA_PUT_U32(msg, NL80211_CMD_ ## n, i);	\
> 
> This is an array, the index doesn't matter, and the value is the
> supported command. You parse it with nla_for_each_nested()

I'm trying to find if a command (i.e. NL80211_CMD_CONNECT) is supported
or not. I think I can use nla_find_nested() if the command is an
attribute. But I can also do the find myself if it is an array like now.
So, never mind.

Thanks,
-yi


^ permalink raw reply

* Re: [PATCH 2.6.30] iwl3945: fix rfkill switch
From: reinette chatre @ 2009-08-05 22:51 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: linux-wireless@vger.kernel.org, Zhu, Yi, John W. Linville,
	stable@kernel.org
In-Reply-To: <1249389350-4158-1-git-send-email-sgruszka@redhat.com>

Hi Stanislaw,

On Tue, 2009-08-04 at 05:35 -0700, Stanislaw Gruszka wrote:
> Due to rfkill and iwlwifi mishmash of SW / HW killswitch representation,
> we have race conditions which make unable turn wifi radio on, after enable
> and disable again killswitch. I can observe this problem on my laptop
> with iwl3945 device.
> 
> In rfkill core HW switch and SW switch are separate 'states'. Device can
> be only in one of 3 states: RFKILL_STATE_SOFT_BLOCKED, RFKILL_STATE_UNBLOCKED,
> RFKILL_STATE_HARD_BLOCKED. Whereas in iwlwifi driver we have separate bits
> STATUS_RF_KILL_HW and STATUS_RF_KILL_SW for HW and SW switches - radio can be
> turned on, only if both bits are cleared.
> 
> In this particular race conditions, radio can not be turned on if in driver
> STATUS_RF_KILL_SW bit is set, and rfkill core is in state
> RFKILL_STATE_HARD_BLOCKED, because rfkill core is unable to call
> rfkill->toggle_radio(). This situation can be entered in case:
> 

I am trying to understand this race condition ...

> - killswitch is turned on
> - rfkill core 'see' button change first and move to RFKILL_STATE_SOFT_BLOCKED
>   also call ->toggle_radio() and STATE_RF_KILL_SW in driver is set
> - iwl3945 get info about button from hardware to set STATUS_RF_KILL_HW bit and
>   force rfkill to move to RFKILL_STATE_HARD_BLOCKED

ok - so at this point we have rfkill == RFKILL_STATE_HARD_BLOCKED, and
driver == STATE_RF_KILL_SW | STATE_RF_KILL_HW

> - killsiwtch is turend off
> - driver clear STATUS_RF_KILL_HW

at this point the driver should clear STATE_RF_KILL_HW and then call
iwl_rfkill_set_hw_state(). From what I can tell, in
iwl_rfkill_set_hw_state() the test for iwl_is_rfkill_sw() will cause the
driver to call rfkill_force_state for RFKILL_STATE_SOFT_BLOCKED

So, from what I understand after the above the status will be

rfkill == RFKILL_STATE_SOFT_BLOCKED, and driver == STATE_RF_KILL_SW 

> - rfkill core is unable to clear STATUS_RF_KILL_SW in driver

I do not understand why this is a problem here. Could you please
highlight what I am missing?

> 
> Additionally call to rfkill_epo() when STATUS_RF_KILL_HW in driver is set
> cause move to the same situation.
> 
> In 2.6.31 this problem is fixed due to _total_ rewrite of rfkill subsystem.
> This is a quite small fix for 2.6.30.x in iwl3945 driver. We disable
> STATUS_RF_KILL_SW bit regardless of HW bit state. Also report to rfkill
> subsystem SW switch bit before HW switch bit to move rfkill subsystem
> to SOFT_BLOCK rather than HARD_BLOCK.
> 
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> ---
> I'm not sure if this is good candidate for stable as this is not backport
> of upstream commit. Also I did not test this patch with other iwlwifi devices,
> only with iwl3945.
> 
>  drivers/net/wireless/iwlwifi/iwl-rfkill.c |   24 ++++++++++++++----------
>  1 files changed, 14 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
> index 2ad9faf..d6b6098 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
> @@ -54,21 +54,28 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
>  	case RFKILL_STATE_UNBLOCKED:
>  		if (iwl_is_rfkill_hw(priv)) {
>  			err = -EBUSY;
> -			goto out_unlock;
> +			/* pass error to rfkill core to make it state HARD
> +			 * BLOCKED and disable software kill switch */
>  		}
>  		iwl_radio_kill_sw_enable_radio(priv);
>  		break;
>  	case RFKILL_STATE_SOFT_BLOCKED:
>  		iwl_radio_kill_sw_disable_radio(priv);
> +		/* rfkill->mutex lock is taken */
> +		if (priv->rfkill->state == RFKILL_STATE_HARD_BLOCKED) {
> +			/* force rfkill core state to be SOFT BLOCKED,
> +			 * otherwise core will be unable to disable software
> +			 * kill switch */
> +			priv->rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
> +		}

I understand that you are directly changing the rfkill internals because
the mutex is taken ... but this really does not seem right to directly
modify the rfkill state in this way.

>  		break;
>  	default:
>  		IWL_WARN(priv, "we received unexpected RFKILL state %d\n",
>  			state);
>  		break;
>  	}
> -out_unlock:
> -	mutex_unlock(&priv->mutex);
>  
> +	mutex_unlock(&priv->mutex);
>  	return err;
>  }
>  
> @@ -132,14 +139,11 @@ void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
>  	if (!priv->rfkill)
>  		return;
>  
> -	if (iwl_is_rfkill_hw(priv)) {
> +	if (iwl_is_rfkill_sw(priv))
> +		rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
> +	else if (iwl_is_rfkill_hw(priv))
>  		rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
> -		return;
> -	}
> -
> -	if (!iwl_is_rfkill_sw(priv))
> -		rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
>  	else
> -		rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
> +		rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
>  }
>  EXPORT_SYMBOL(iwl_rfkill_set_hw_state);


Reinette



^ permalink raw reply

* Best (ath9k) miniPCI card for testing overall AP functionality
From: Philip A. Prindeville @ 2009-08-05 22:36 UTC (permalink / raw)
  To: linux-wireless

I'm trying to get Astlinux ready for the 0.7 release, but we've been
hamstrung in testing because of issues with the ath5k drivers on our
test platform...  so I've been considering getting different hardware
for testing.  We've not been able to shake-down our transition from
wireless-tools to iw, or from hostapd 0.6.8 to 0.6.9.

I'm guessing that the ath9k tends to be further along in functionality,
and more stable, than the ath5k?

If that's the case, one of our partners that gives discounted pricing on
F/OSS development hardware has the following NICs:

Ubiquiti SR71-A  = Atheros AR9160 with DFS SUPPORT
Ubiquiti SR71-12 = Atheros AR9220 with DFS SUPPORT
Ubiquiti SR71-15 = Atheros AR9220 with DFS SUPPORT



I'm looking for b/g or n hardware, and the more power, the better.

The 'A' doesn't seem to work with x86 based systems, as far as I can tell.

The '12' is b/g/n, 27dBm and uses MMCX connectors, and is type III-A format.

The '15' is a/n only, also 27dBm and uses MMCX connectors... also type
III-A format.

I'm leaning towards a '12', but they're not cheap.

According to:

http://linuxwireless.org/en/users/Drivers/ath9k

and:

http://linuxwireless.org/en/users/Drivers/ath9k/products/external

none of the above cards are supported...  but that assumes that the Wiki
is up to date.  Also the AR9220 isn't shown on the list of supported
chipsets.

Can anyone confirm or deny that it's unsupported?

Thanks,

-Philip


^ permalink raw reply

* Re: [stable] [PATCH 2.6.30] iwl3945: fix rfkill switch
From: Greg KH @ 2009-08-05 21:07 UTC (permalink / raw)
  To: John W. Linville
  Cc: Stanislaw Gruszka, Zhu Yi, Reinette Chatre, linux-wireless,
	stable
In-Reply-To: <20090804124951.GA3988@tuxdriver.com>

On Tue, Aug 04, 2009 at 08:49:51AM -0400, John W. Linville wrote:
> On Tue, Aug 04, 2009 at 02:35:50PM +0200, Stanislaw Gruszka wrote:
> > Due to rfkill and iwlwifi mishmash of SW / HW killswitch representation,
> > we have race conditions which make unable turn wifi radio on, after enable
> > and disable again killswitch. I can observe this problem on my laptop
> > with iwl3945 device.
> > 
> > In rfkill core HW switch and SW switch are separate 'states'. Device can
> > be only in one of 3 states: RFKILL_STATE_SOFT_BLOCKED, RFKILL_STATE_UNBLOCKED,
> > RFKILL_STATE_HARD_BLOCKED. Whereas in iwlwifi driver we have separate bits
> > STATUS_RF_KILL_HW and STATUS_RF_KILL_SW for HW and SW switches - radio can be
> > turned on, only if both bits are cleared.
> > 
> > In this particular race conditions, radio can not be turned on if in driver
> > STATUS_RF_KILL_SW bit is set, and rfkill core is in state
> > RFKILL_STATE_HARD_BLOCKED, because rfkill core is unable to call
> > rfkill->toggle_radio(). This situation can be entered in case:
> > 
> > - killswitch is turned on
> > - rfkill core 'see' button change first and move to RFKILL_STATE_SOFT_BLOCKED
> >   also call ->toggle_radio() and STATE_RF_KILL_SW in driver is set
> > - iwl3945 get info about button from hardware to set STATUS_RF_KILL_HW bit and
> >   force rfkill to move to RFKILL_STATE_HARD_BLOCKED
> > - killsiwtch is turend off
> > - driver clear STATUS_RF_KILL_HW
> > - rfkill core is unable to clear STATUS_RF_KILL_SW in driver
> > 
> > Additionally call to rfkill_epo() when STATUS_RF_KILL_HW in driver is set
> > cause move to the same situation.
> > 
> > In 2.6.31 this problem is fixed due to _total_ rewrite of rfkill subsystem.
> > This is a quite small fix for 2.6.30.x in iwl3945 driver. We disable
> > STATUS_RF_KILL_SW bit regardless of HW bit state. Also report to rfkill
> > subsystem SW switch bit before HW switch bit to move rfkill subsystem
> > to SOFT_BLOCK rather than HARD_BLOCK.
> > 
> > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> > ---
> > I'm not sure if this is good candidate for stable as this is not backport
> > of upstream commit. Also I did not test this patch with other iwlwifi devices,
> > only with iwl3945.
> 
> stable is about the only place it can go, since it fixes a problem
> that doesn't exist in 2.6.31...

Do you ack this for inclusion in 2.6.30-stable?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH] wl12xx: make irq handling interface specific
From: Kalle Valo @ 2009-08-05 21:00 UTC (permalink / raw)
  To: Bob Copeland, luciano.coelho; +Cc: linux-wireless
In-Reply-To: <20090805135618.GA7468@hash.localnet>

Bob Copeland <me@bobcopeland.com> writes:

> In SDIO, the host driver requests the IRQ and invokes a callback to the
> card driver.  This differs from SPI, so the relevant code needs to be
> interface-specific.  This patch pushes the irq code down into _spi.c
> and _sdio.c, and adds enable/disable callbacks.

[...]

> v2: make sdio irq functions void to match wl1251.h

Thanks, I applied this version to my local tree now.

All pending wl1251 patches are now here:

http://www.valot.fi/kalle/wl1251/patches/wl1251-add-sdio/2009-08-05-20:50/

It includes your sdio patches, quite a few patches from our internal
tree and a workaround to make association work again. With these patches
dhcp and ping works with wep on wl1251 using spi. So things look good
again.

I haven't checked the patches at all, there might be some stupidity in
them. I'll do that tomorrow and try to send them to John ASAP.

Luca, I'm pretty sure that the workaround helps with wl1271 also. Just
take the wl->channel fix and the filter hack and it should work.

-- 
Kalle Valo

^ permalink raw reply

* [RFC 4/4] orinoco: do WE via cfg80211
From: David Kilroy @ 2009-08-05 20:32 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249504372-17063-1-git-send-email-kilroyd@googlemail.com>

Now that the driver supports both station and ad-hoc modes in cfg80211,
we can point the WE handlers at the cfg80211 versions.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/wext.c |  726 +----------------------------------
 1 files changed, 11 insertions(+), 715 deletions(-)

diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index 3e56f76..e72b6b1 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -22,67 +22,6 @@
 
 #define MAX_RID_LEN 1024
 
-/* Helper routine to record keys
- * Do not call from interrupt context */
-static int orinoco_set_key(struct orinoco_private *priv, int index,
-			   enum orinoco_alg alg, const u8 *key, int key_len,
-			   const u8 *seq, int seq_len)
-{
-	kzfree(priv->keys[index].key);
-	kzfree(priv->keys[index].seq);
-
-	if (key_len) {
-		priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
-		if (!priv->keys[index].key)
-			goto nomem;
-	} else
-		priv->keys[index].key = NULL;
-
-	if (seq_len) {
-		priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
-		if (!priv->keys[index].seq)
-			goto free_key;
-	} else
-		priv->keys[index].seq = NULL;
-
-	priv->keys[index].key_len = key_len;
-	priv->keys[index].seq_len = seq_len;
-
-	if (key_len)
-		memcpy(priv->keys[index].key, key, key_len);
-	if (seq_len)
-		memcpy(priv->keys[index].seq, seq, seq_len);
-
-	switch (alg) {
-	case ORINOCO_ALG_TKIP:
-		priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
-		break;
-
-	case ORINOCO_ALG_WEP:
-		priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
-			WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
-		break;
-
-	case ORINOCO_ALG_NONE:
-	default:
-		priv->keys[index].cipher = 0;
-		break;
-	}
-
-	return 0;
-
-free_key:
-	kfree(priv->keys[index].key);
-	priv->keys[index].key = NULL;
-
-nomem:
-	priv->keys[index].key_len = 0;
-	priv->keys[index].seq_len = 0;
-	priv->keys[index].cipher = 0;
-
-	return -ENOMEM;
-}
-
 static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
@@ -149,274 +88,6 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
 /* Wireless extensions                                              */
 /********************************************************************/
 
-static int orinoco_ioctl_setwap(struct net_device *dev,
-				struct iw_request_info *info,
-				struct sockaddr *ap_addr,
-				char *extra)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	int err = -EINPROGRESS;		/* Call commit handler */
-	unsigned long flags;
-	static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-	static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	/* Enable automatic roaming - no sanity checks are needed */
-	if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
-	    memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
-		priv->bssid_fixed = 0;
-		memset(priv->desired_bssid, 0, ETH_ALEN);
-
-		/* "off" means keep existing connection */
-		if (ap_addr->sa_data[0] == 0) {
-			__orinoco_hw_set_wap(priv);
-			err = 0;
-		}
-		goto out;
-	}
-
-	if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
-		printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
-		       "support manual roaming\n",
-		       dev->name);
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (priv->iw_mode != NL80211_IFTYPE_STATION) {
-		printk(KERN_WARNING "%s: Manual roaming supported only in "
-		       "managed mode\n", dev->name);
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	/* Intersil firmware hangs without Desired ESSID */
-	if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
-	    strlen(priv->desired_essid) == 0) {
-		printk(KERN_WARNING "%s: Desired ESSID must be set for "
-		       "manual roaming\n", dev->name);
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	/* Finally, enable manual roaming */
-	priv->bssid_fixed = 1;
-	memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
-
- out:
-	orinoco_unlock(priv, &flags);
-	return err;
-}
-
-static int orinoco_ioctl_getwap(struct net_device *dev,
-				struct iw_request_info *info,
-				struct sockaddr *ap_addr,
-				char *extra)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-
-	int err = 0;
-	unsigned long flags;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	ap_addr->sa_family = ARPHRD_ETHER;
-	err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
-
-	orinoco_unlock(priv, &flags);
-
-	return err;
-}
-
-static int orinoco_ioctl_setiwencode(struct net_device *dev,
-				     struct iw_request_info *info,
-				     struct iw_point *erq,
-				     char *keybuf)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
-	int setindex = priv->tx_key;
-	enum orinoco_alg encode_alg = priv->encode_alg;
-	int restricted = priv->wep_restrict;
-	int err = -EINPROGRESS;		/* Call commit handler */
-	unsigned long flags;
-
-	if (!priv->has_wep)
-		return -EOPNOTSUPP;
-
-	if (erq->pointer) {
-		/* We actually have a key to set - check its length */
-		if (erq->length > LARGE_KEY_SIZE)
-			return -E2BIG;
-
-		if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep)
-			return -E2BIG;
-	}
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	/* Clear any TKIP key we have */
-	if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
-		(void) orinoco_clear_tkip_key(priv, setindex);
-
-	if (erq->length > 0) {
-		if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
-			index = priv->tx_key;
-
-		/* Switch on WEP if off */
-		if (encode_alg != ORINOCO_ALG_WEP) {
-			setindex = index;
-			encode_alg = ORINOCO_ALG_WEP;
-		}
-	} else {
-		/* Important note : if the user do "iwconfig eth0 enc off",
-		 * we will arrive there with an index of -1. This is valid
-		 * but need to be taken care off... Jean II */
-		if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
-			if ((index != -1) || (erq->flags == 0)) {
-				err = -EINVAL;
-				goto out;
-			}
-		} else {
-			/* Set the index : Check that the key is valid */
-			if (priv->keys[index].key_len == 0) {
-				err = -EINVAL;
-				goto out;
-			}
-			setindex = index;
-		}
-	}
-
-	if (erq->flags & IW_ENCODE_DISABLED)
-		encode_alg = ORINOCO_ALG_NONE;
-	if (erq->flags & IW_ENCODE_OPEN)
-		restricted = 0;
-	if (erq->flags & IW_ENCODE_RESTRICTED)
-		restricted = 1;
-
-	if (erq->pointer && erq->length > 0) {
-		err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
-				      erq->length, NULL, 0);
-	}
-	priv->tx_key = setindex;
-
-	/* Try fast key change if connected and only keys are changed */
-	if ((priv->encode_alg == encode_alg) &&
-	    (priv->wep_restrict == restricted) &&
-	    netif_carrier_ok(dev)) {
-		err = __orinoco_hw_setup_wepkeys(priv);
-		/* No need to commit if successful */
-		goto out;
-	}
-
-	priv->encode_alg = encode_alg;
-	priv->wep_restrict = restricted;
-
- out:
-	orinoco_unlock(priv, &flags);
-
-	return err;
-}
-
-static int orinoco_ioctl_getiwencode(struct net_device *dev,
-				     struct iw_request_info *info,
-				     struct iw_point *erq,
-				     char *keybuf)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
-	unsigned long flags;
-
-	if (!priv->has_wep)
-		return -EOPNOTSUPP;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
-		index = priv->tx_key;
-
-	erq->flags = 0;
-	if (!priv->encode_alg)
-		erq->flags |= IW_ENCODE_DISABLED;
-	erq->flags |= index + 1;
-
-	if (priv->wep_restrict)
-		erq->flags |= IW_ENCODE_RESTRICTED;
-	else
-		erq->flags |= IW_ENCODE_OPEN;
-
-	erq->length = priv->keys[index].key_len;
-
-	memcpy(keybuf, priv->keys[index].key, erq->length);
-
-	orinoco_unlock(priv, &flags);
-	return 0;
-}
-
-static int orinoco_ioctl_setessid(struct net_device *dev,
-				  struct iw_request_info *info,
-				  struct iw_point *erq,
-				  char *essidbuf)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	unsigned long flags;
-
-	/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
-	 * anyway... - Jean II */
-
-	/* Hum... Should not use Wireless Extension constant (may change),
-	 * should use our own... - Jean II */
-	if (erq->length > IW_ESSID_MAX_SIZE)
-		return -E2BIG;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	/* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
-	memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
-
-	/* If not ANY, get the new ESSID */
-	if (erq->flags)
-		memcpy(priv->desired_essid, essidbuf, erq->length);
-
-	orinoco_unlock(priv, &flags);
-
-	return -EINPROGRESS;		/* Call commit handler */
-}
-
-static int orinoco_ioctl_getessid(struct net_device *dev,
-				  struct iw_request_info *info,
-				  struct iw_point *erq,
-				  char *essidbuf)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	int active;
-	int err = 0;
-	unsigned long flags;
-
-	if (netif_running(dev)) {
-		err = orinoco_hw_get_essid(priv, &active, essidbuf);
-		if (err < 0)
-			return err;
-		erq->length = err;
-	} else {
-		if (orinoco_lock(priv, &flags) != 0)
-			return -EBUSY;
-		memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
-		erq->length = strlen(priv->desired_essid);
-		orinoco_unlock(priv, &flags);
-	}
-
-	erq->flags = 1;
-
-	return 0;
-}
-
 static int orinoco_ioctl_setfreq(struct net_device *dev,
 				 struct iw_request_info *info,
 				 struct iw_freq *frq,
@@ -827,379 +498,6 @@ static int orinoco_ioctl_getpower(struct net_device *dev,
 	return err;
 }
 
-static int orinoco_ioctl_set_encodeext(struct net_device *dev,
-				       struct iw_request_info *info,
-				       union iwreq_data *wrqu,
-				       char *extra)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	struct iw_point *encoding = &wrqu->encoding;
-	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-	int idx, alg = ext->alg, set_key = 1;
-	unsigned long flags;
-	int err = -EINVAL;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	/* Determine and validate the key index */
-	idx = encoding->flags & IW_ENCODE_INDEX;
-	if (idx) {
-		if ((idx < 1) || (idx > 4))
-			goto out;
-		idx--;
-	} else
-		idx = priv->tx_key;
-
-	if (encoding->flags & IW_ENCODE_DISABLED)
-		alg = IW_ENCODE_ALG_NONE;
-
-	if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) {
-		/* Clear any TKIP TX key we had */
-		(void) orinoco_clear_tkip_key(priv, priv->tx_key);
-	}
-
-	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
-		priv->tx_key = idx;
-		set_key = ((alg == IW_ENCODE_ALG_TKIP) ||
-			   (ext->key_len > 0)) ? 1 : 0;
-	}
-
-	if (set_key) {
-		/* Set the requested key first */
-		switch (alg) {
-		case IW_ENCODE_ALG_NONE:
-			priv->encode_alg = ORINOCO_ALG_NONE;
-			err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
-					      NULL, 0, NULL, 0);
-			break;
-
-		case IW_ENCODE_ALG_WEP:
-			if (ext->key_len <= 0)
-				goto out;
-
-			priv->encode_alg = ORINOCO_ALG_WEP;
-			err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
-					      ext->key, ext->key_len, NULL, 0);
-			break;
-
-		case IW_ENCODE_ALG_TKIP:
-		{
-			u8 *tkip_iv = NULL;
-
-			if (!priv->has_wpa ||
-			    (ext->key_len > sizeof(struct orinoco_tkip_key)))
-				goto out;
-
-			priv->encode_alg = ORINOCO_ALG_TKIP;
-
-			if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
-				tkip_iv = &ext->rx_seq[0];
-
-			err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
-					      ext->key, ext->key_len, tkip_iv,
-					      ORINOCO_SEQ_LEN);
-
-			err = __orinoco_hw_set_tkip_key(priv, idx,
-				 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
-				 priv->keys[idx].key,
-				 tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
-			if (err)
-				printk(KERN_ERR "%s: Error %d setting TKIP key"
-				       "\n", dev->name, err);
-
-			goto out;
-		}
-		default:
-			goto out;
-		}
-	}
-	err = -EINPROGRESS;
- out:
-	orinoco_unlock(priv, &flags);
-
-	return err;
-}
-
-static int orinoco_ioctl_get_encodeext(struct net_device *dev,
-				       struct iw_request_info *info,
-				       union iwreq_data *wrqu,
-				       char *extra)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	struct iw_point *encoding = &wrqu->encoding;
-	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-	int idx, max_key_len;
-	unsigned long flags;
-	int err;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	err = -EINVAL;
-	max_key_len = encoding->length - sizeof(*ext);
-	if (max_key_len < 0)
-		goto out;
-
-	idx = encoding->flags & IW_ENCODE_INDEX;
-	if (idx) {
-		if ((idx < 1) || (idx > 4))
-			goto out;
-		idx--;
-	} else
-		idx = priv->tx_key;
-
-	encoding->flags = idx + 1;
-	memset(ext, 0, sizeof(*ext));
-
-	switch (priv->encode_alg) {
-	case ORINOCO_ALG_NONE:
-		ext->alg = IW_ENCODE_ALG_NONE;
-		ext->key_len = 0;
-		encoding->flags |= IW_ENCODE_DISABLED;
-		break;
-	case ORINOCO_ALG_WEP:
-		ext->alg = IW_ENCODE_ALG_WEP;
-		ext->key_len = min(priv->keys[idx].key_len, max_key_len);
-		memcpy(ext->key, priv->keys[idx].key, ext->key_len);
-		encoding->flags |= IW_ENCODE_ENABLED;
-		break;
-	case ORINOCO_ALG_TKIP:
-		ext->alg = IW_ENCODE_ALG_TKIP;
-		ext->key_len = min(priv->keys[idx].key_len, max_key_len);
-		memcpy(ext->key, priv->keys[idx].key, ext->key_len);
-		encoding->flags |= IW_ENCODE_ENABLED;
-		break;
-	}
-
-	err = 0;
- out:
-	orinoco_unlock(priv, &flags);
-
-	return err;
-}
-
-static int orinoco_ioctl_set_auth(struct net_device *dev,
-				  struct iw_request_info *info,
-				  union iwreq_data *wrqu, char *extra)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	hermes_t *hw = &priv->hw;
-	struct iw_param *param = &wrqu->param;
-	unsigned long flags;
-	int ret = -EINPROGRESS;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	switch (param->flags & IW_AUTH_INDEX) {
-	case IW_AUTH_WPA_VERSION:
-	case IW_AUTH_CIPHER_PAIRWISE:
-	case IW_AUTH_CIPHER_GROUP:
-	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-	case IW_AUTH_PRIVACY_INVOKED:
-	case IW_AUTH_DROP_UNENCRYPTED:
-		/*
-		 * orinoco does not use these parameters
-		 */
-		break;
-
-	case IW_AUTH_KEY_MGMT:
-		/* wl_lkm implies value 2 == PSK for Hermes I
-		 * which ties in with WEXT
-		 * no other hints tho :(
-		 */
-		priv->key_mgmt = param->value;
-		break;
-
-	case IW_AUTH_TKIP_COUNTERMEASURES:
-		/* When countermeasures are enabled, shut down the
-		 * card; when disabled, re-enable the card. This must
-		 * take effect immediately.
-		 *
-		 * TODO: Make sure that the EAPOL message is getting
-		 *       out before card disabled
-		 */
-		if (param->value) {
-			priv->tkip_cm_active = 1;
-			ret = hermes_enable_port(hw, 0);
-		} else {
-			priv->tkip_cm_active = 0;
-			ret = hermes_disable_port(hw, 0);
-		}
-		break;
-
-	case IW_AUTH_80211_AUTH_ALG:
-		if (param->value & IW_AUTH_ALG_SHARED_KEY)
-			priv->wep_restrict = 1;
-		else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
-			priv->wep_restrict = 0;
-		else
-			ret = -EINVAL;
-		break;
-
-	case IW_AUTH_WPA_ENABLED:
-		if (priv->has_wpa) {
-			priv->wpa_enabled = param->value ? 1 : 0;
-		} else {
-			if (param->value)
-				ret = -EOPNOTSUPP;
-			/* else silently accept disable of WPA */
-			priv->wpa_enabled = 0;
-		}
-		break;
-
-	default:
-		ret = -EOPNOTSUPP;
-	}
-
-	orinoco_unlock(priv, &flags);
-	return ret;
-}
-
-static int orinoco_ioctl_get_auth(struct net_device *dev,
-				  struct iw_request_info *info,
-				  union iwreq_data *wrqu, char *extra)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	struct iw_param *param = &wrqu->param;
-	unsigned long flags;
-	int ret = 0;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	switch (param->flags & IW_AUTH_INDEX) {
-	case IW_AUTH_KEY_MGMT:
-		param->value = priv->key_mgmt;
-		break;
-
-	case IW_AUTH_TKIP_COUNTERMEASURES:
-		param->value = priv->tkip_cm_active;
-		break;
-
-	case IW_AUTH_80211_AUTH_ALG:
-		if (priv->wep_restrict)
-			param->value = IW_AUTH_ALG_SHARED_KEY;
-		else
-			param->value = IW_AUTH_ALG_OPEN_SYSTEM;
-		break;
-
-	case IW_AUTH_WPA_ENABLED:
-		param->value = priv->wpa_enabled;
-		break;
-
-	default:
-		ret = -EOPNOTSUPP;
-	}
-
-	orinoco_unlock(priv, &flags);
-	return ret;
-}
-
-static int orinoco_ioctl_set_genie(struct net_device *dev,
-				   struct iw_request_info *info,
-				   union iwreq_data *wrqu, char *extra)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	u8 *buf;
-	unsigned long flags;
-
-	/* cut off at IEEE80211_MAX_DATA_LEN */
-	if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
-	    (wrqu->data.length && (extra == NULL)))
-		return -EINVAL;
-
-	if (wrqu->data.length) {
-		buf = kmalloc(wrqu->data.length, GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
-
-		memcpy(buf, extra, wrqu->data.length);
-	} else
-		buf = NULL;
-
-	if (orinoco_lock(priv, &flags) != 0) {
-		kfree(buf);
-		return -EBUSY;
-	}
-
-	kfree(priv->wpa_ie);
-	priv->wpa_ie = buf;
-	priv->wpa_ie_len = wrqu->data.length;
-
-	if (priv->wpa_ie) {
-		/* Looks like wl_lkm wants to check the auth alg, and
-		 * somehow pass it to the firmware.
-		 * Instead it just calls the key mgmt rid
-		 *   - we do this in set auth.
-		 */
-	}
-
-	orinoco_unlock(priv, &flags);
-	return 0;
-}
-
-static int orinoco_ioctl_get_genie(struct net_device *dev,
-				   struct iw_request_info *info,
-				   union iwreq_data *wrqu, char *extra)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	unsigned long flags;
-	int err = 0;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) {
-		wrqu->data.length = 0;
-		goto out;
-	}
-
-	if (wrqu->data.length < priv->wpa_ie_len) {
-		err = -E2BIG;
-		goto out;
-	}
-
-	wrqu->data.length = priv->wpa_ie_len;
-	memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
-
-out:
-	orinoco_unlock(priv, &flags);
-	return err;
-}
-
-static int orinoco_ioctl_set_mlme(struct net_device *dev,
-				  struct iw_request_info *info,
-				  union iwreq_data *wrqu, char *extra)
-{
-	struct orinoco_private *priv = ndev_priv(dev);
-	struct iw_mlme *mlme = (struct iw_mlme *)extra;
-	unsigned long flags;
-	int ret = 0;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	switch (mlme->cmd) {
-	case IW_MLME_DEAUTH:
-		/* silently ignore */
-		break;
-
-	case IW_MLME_DISASSOC:
-
-		ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
-					      mlme->reason_code);
-		break;
-
-	default:
-		ret = -EOPNOTSUPP;
-	}
-
-	orinoco_unlock(priv, &flags);
-	return ret;
-}
-
 static int orinoco_ioctl_getretry(struct net_device *dev,
 				  struct iw_request_info *info,
 				  struct iw_param *rrq,
@@ -1521,12 +819,12 @@ static const iw_handler	orinoco_handler[] = {
 	STD_IW_HANDLER(SIOCGIWSPY,	iw_handler_get_spy),
 	STD_IW_HANDLER(SIOCSIWTHRSPY,	iw_handler_set_thrspy),
 	STD_IW_HANDLER(SIOCGIWTHRSPY,	iw_handler_get_thrspy),
-	STD_IW_HANDLER(SIOCSIWAP,	orinoco_ioctl_setwap),
-	STD_IW_HANDLER(SIOCGIWAP,	orinoco_ioctl_getwap),
+	STD_IW_HANDLER(SIOCSIWAP,	cfg80211_wext_siwap),
+	STD_IW_HANDLER(SIOCGIWAP,	cfg80211_wext_giwap),
 	STD_IW_HANDLER(SIOCSIWSCAN,	cfg80211_wext_siwscan),
 	STD_IW_HANDLER(SIOCGIWSCAN,	cfg80211_wext_giwscan),
-	STD_IW_HANDLER(SIOCSIWESSID,	orinoco_ioctl_setessid),
-	STD_IW_HANDLER(SIOCGIWESSID,	orinoco_ioctl_getessid),
+	STD_IW_HANDLER(SIOCSIWESSID,	cfg80211_wext_siwessid),
+	STD_IW_HANDLER(SIOCGIWESSID,	cfg80211_wext_giwessid),
 	STD_IW_HANDLER(SIOCSIWRATE,	orinoco_ioctl_setrate),
 	STD_IW_HANDLER(SIOCGIWRATE,	orinoco_ioctl_getrate),
 	STD_IW_HANDLER(SIOCSIWRTS,	orinoco_ioctl_setrts),
@@ -1534,17 +832,15 @@ static const iw_handler	orinoco_handler[] = {
 	STD_IW_HANDLER(SIOCSIWFRAG,	orinoco_ioctl_setfrag),
 	STD_IW_HANDLER(SIOCGIWFRAG,	orinoco_ioctl_getfrag),
 	STD_IW_HANDLER(SIOCGIWRETRY,	orinoco_ioctl_getretry),
-	STD_IW_HANDLER(SIOCSIWENCODE,	orinoco_ioctl_setiwencode),
-	STD_IW_HANDLER(SIOCGIWENCODE,	orinoco_ioctl_getiwencode),
+	STD_IW_HANDLER(SIOCSIWENCODE,	cfg80211_wext_siwencode),
+	STD_IW_HANDLER(SIOCGIWENCODE,	cfg80211_wext_giwencode),
 	STD_IW_HANDLER(SIOCSIWPOWER,	orinoco_ioctl_setpower),
 	STD_IW_HANDLER(SIOCGIWPOWER,	orinoco_ioctl_getpower),
-	STD_IW_HANDLER(SIOCSIWGENIE,	orinoco_ioctl_set_genie),
-	STD_IW_HANDLER(SIOCGIWGENIE,	orinoco_ioctl_get_genie),
-	STD_IW_HANDLER(SIOCSIWMLME,	orinoco_ioctl_set_mlme),
-	STD_IW_HANDLER(SIOCSIWAUTH,	orinoco_ioctl_set_auth),
-	STD_IW_HANDLER(SIOCGIWAUTH,	orinoco_ioctl_get_auth),
-	STD_IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
-	STD_IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
+	STD_IW_HANDLER(SIOCSIWGENIE,	cfg80211_wext_siwgenie),
+	STD_IW_HANDLER(SIOCSIWMLME,	cfg80211_wext_siwmlme),
+	STD_IW_HANDLER(SIOCSIWAUTH,	cfg80211_wext_siwauth),
+	STD_IW_HANDLER(SIOCGIWAUTH,	cfg80211_wext_giwauth),
+	STD_IW_HANDLER(SIOCSIWENCODEEXT, cfg80211_wext_siwencodeext),
 };
 
 
-- 
1.6.3.3


^ permalink raw reply related

* [RFC 3/4] orinoco: implement cfg80211 key manipulation functions
From: David Kilroy @ 2009-08-05 20:32 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249504372-17063-1-git-send-email-kilroyd@googlemail.com>

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/cfg.c |  199 ++++++++++++++++++++++++++++++++++++
 1 files changed, 199 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 84a7884..9ed690e 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -439,6 +439,201 @@ static int orinoco_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 	return err;
 }
 
+static int orinoco_add_key(struct wiphy *wiphy, struct net_device *dev,
+			   u8 key_index, const u8 *mac_addr,
+			   struct key_params *params)
+{
+	struct orinoco_private *priv = wiphy_priv(wiphy);
+	int err = 0;
+	unsigned long lock;
+	enum orinoco_alg alg = ORINOCO_ALG_NONE;
+	int key_len;
+
+	if (key_index >= ORINOCO_MAX_KEYS)
+		return -EINVAL;
+
+	if (orinoco_lock(priv, &lock) != 0)
+		return -EBUSY;
+
+	switch (params->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		alg = ORINOCO_ALG_WEP;
+
+		if (!priv->has_wep)
+			err = -EOPNOTSUPP;
+
+		if (params->key_len > ORINOCO_MAX_KEY_SIZE)
+			err = -E2BIG;
+		else if (params->key_len > SMALL_KEY_SIZE)
+			key_len = LARGE_KEY_SIZE;
+		else if (params->key_len > 0)
+			key_len = SMALL_KEY_SIZE;
+		else
+			err = -EINVAL;
+
+		break;
+
+	case WLAN_CIPHER_SUITE_TKIP:
+		alg = ORINOCO_ALG_TKIP;
+
+		if (!priv->has_wpa)
+			err = -EOPNOTSUPP;
+		else if (params->key_len < WLAN_KEY_LEN_TKIP)
+			err = -EINVAL;
+
+		key_len = WLAN_KEY_LEN_TKIP;
+		break;
+
+	case WLAN_CIPHER_SUITE_CCMP:
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+	default:
+		err = -EOPNOTSUPP;
+	}
+
+	if (err)
+		goto out;
+
+	/* Ensure existing keys are of the same cipher suite */
+	orinoco_set_encoding(priv, alg);
+
+	err = orinoco_set_key(priv, key_index, alg,
+			      params->key, params->key_len,
+			      params->seq, params->seq_len);
+	if (err)
+		goto out;
+
+	if (alg == ORINOCO_ALG_TKIP) {
+		/* We don't know if this is the tx key yet.
+		 * We'll reprogram it when we find out. */
+		err = __orinoco_hw_set_tkip_key(priv, key_index, 0,
+						priv->keys[key_index].key,
+						priv->keys[key_index].seq,
+						priv->keys[key_index].seq_len,
+						NULL, 0);
+
+		priv->wpa_enabled = 1;
+	}
+
+	err = __orinoco_hw_setup_enc(priv);
+
+ out:
+	orinoco_unlock(priv, &lock);
+
+	return err;
+}
+
+static int orinoco_get_key(struct wiphy *wiphy, struct net_device *dev,
+			   u8 key_index, const u8 *mac_addr, void *cookie,
+			   void (*callback)(void *cookie, struct key_params*))
+{
+	struct orinoco_private *priv = wiphy_priv(wiphy);
+	struct key_params params;
+	u8 key[WLAN_KEY_LEN_TKIP];
+	u8 tsc[ORINOCO_SEQ_LEN];
+	unsigned long lock;
+	int err = 0;
+
+	if (key_index >= ORINOCO_MAX_KEYS)
+		return -EINVAL;
+
+	if (orinoco_lock(priv, &lock) != 0)
+		return -EBUSY;
+
+	/* Take a copy of the key info */
+	memcpy(&key, priv->keys[key_index].key, priv->keys[key_index].key_len);
+
+	params.cipher = priv->keys[key_index].cipher;
+	params.key = &key[0];
+	params.key_len = priv->keys[key_index].key_len;
+
+	if (params.cipher == WLAN_CIPHER_SUITE_TKIP) {
+		/* Populate the current TSC */
+		orinoco_hw_get_tkip_iv(priv, key_index, &tsc[0]);
+		params.seq = &tsc[0];
+		params.seq_len = ORINOCO_SEQ_LEN;
+	} else {
+		params.seq = NULL;
+		params.seq_len = 0;
+	}
+
+	orinoco_unlock(priv, &lock);
+
+	callback(cookie, &params);
+
+	return err;
+}
+
+static int orinoco_del_key(struct wiphy *wiphy, struct net_device *dev,
+			   u8 key_index, const u8 *mac_addr)
+{
+	struct orinoco_private *priv = wiphy_priv(wiphy);
+	int err = 0;
+	unsigned long lock;
+
+	if (key_index >= ORINOCO_MAX_KEYS)
+		return -EINVAL;
+
+	if (orinoco_lock(priv, &lock) != 0)
+		return -EBUSY;
+
+	kzfree(priv->keys[key_index].key);
+	kzfree(priv->keys[key_index].seq);
+	priv->keys[key_index].key = NULL;
+	priv->keys[key_index].seq = NULL;
+	priv->keys[key_index].key_len = 0;
+	priv->keys[key_index].seq_len = 0;
+	priv->keys[key_index].cipher = 0;
+
+	if (priv->has_wpa &&
+	    priv->keys[key_index].cipher == WLAN_CIPHER_SUITE_TKIP) {
+		err = orinoco_clear_tkip_key(priv, key_index);
+
+		/* HACK */
+		if (key_index == priv->tx_key)
+			priv->wpa_enabled = 0;
+	}
+
+	err = __orinoco_hw_setup_enc(priv);
+
+	orinoco_unlock(priv, &lock);
+
+	return err;
+}
+
+static int orinoco_set_default_key(struct wiphy *wiphy,
+				   struct net_device *netdev,
+				   u8 key_index)
+{
+	struct orinoco_private *priv = wiphy_priv(wiphy);
+	int err = 0;
+	unsigned long lock;
+
+	if (key_index >= ORINOCO_MAX_KEYS)
+		return -EINVAL;
+
+	if (orinoco_lock(priv, &lock) != 0)
+		return -EBUSY;
+
+	priv->tx_key = key_index;
+
+	if (priv->has_wpa &&
+	    priv->keys[key_index].cipher == WLAN_CIPHER_SUITE_TKIP)
+		err = __orinoco_hw_set_tkip_key(priv, key_index, 1,
+						priv->keys[key_index].key,
+						priv->keys[key_index].seq,
+						priv->keys[key_index].seq_len,
+						NULL, 0);
+	else if (priv->encode_alg == ORINOCO_ALG_WEP)
+		err = __orinoco_hw_setup_wepkeys(priv);
+	else
+		err = -EINVAL;
+
+	orinoco_unlock(priv, &lock);
+
+	return err;
+}
+
 const struct cfg80211_ops orinoco_cfg_ops = {
 	.change_virtual_intf = orinoco_change_vif,
 	.scan = orinoco_scan,
@@ -446,4 +641,8 @@ const struct cfg80211_ops orinoco_cfg_ops = {
 	.disconnect = orinoco_disconnect,
 	.join_ibss = orinoco_join_ibss,
 	.leave_ibss = orinoco_leave_ibss,
+	.add_key = orinoco_add_key,
+	.get_key = orinoco_get_key,
+	.del_key = orinoco_del_key,
+	.set_default_key = orinoco_set_default_key,
 };
-- 
1.6.3.3


^ permalink raw reply related

* [RFC 2/4] orinoco: add cfg80211 join_ibss and leave_ibss
From: David Kilroy @ 2009-08-05 20:32 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249504372-17063-1-git-send-email-kilroyd@googlemail.com>

Basic ad-hoc support.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/cfg.c |   51 ++++++++++++++++++++++++++++++++++++
 1 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 56bd4f1..84a7884 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -390,9 +390,60 @@ static int orinoco_disconnect(struct wiphy *wiphy, struct net_device *dev,
 	return err;
 }
 
+static int orinoco_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+			     struct cfg80211_ibss_params *params)
+{
+	struct orinoco_private *priv = wiphy_priv(wiphy);
+	unsigned long lock;
+	int err;
+
+	if (orinoco_lock(priv, &lock) != 0)
+		return -EBUSY;
+
+	/* Setup the requested parameters in priv. If the card is not
+	 * capable, then the driver will just ignore the settings that
+	 * it can't do. */
+
+	err = __orinoco_connect(wiphy, params->channel, params->bssid,
+				params->ssid, params->ssid_len);
+	if (err)
+		goto out;
+
+	/* Ignore information elements and beacon interval */
+
+	err = orinoco_commit(priv);
+ out:
+	orinoco_unlock(priv, &lock);
+
+	return err;
+}
+
+static int orinoco_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+	struct orinoco_private *priv = wiphy_priv(wiphy);
+	unsigned long lock;
+	int err;
+
+	if (orinoco_lock(priv, &lock) != 0)
+		return -EBUSY;
+
+	/* Do we need to disassociate as well? */
+
+	memset(priv->desired_bssid, 0, ETH_ALEN);
+	memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
+
+	err = orinoco_commit(priv);
+
+	orinoco_unlock(priv, &lock);
+
+	return err;
+}
+
 const struct cfg80211_ops orinoco_cfg_ops = {
 	.change_virtual_intf = orinoco_change_vif,
 	.scan = orinoco_scan,
 	.connect = orinoco_connect,
 	.disconnect = orinoco_disconnect,
+	.join_ibss = orinoco_join_ibss,
+	.leave_ibss = orinoco_leave_ibss,
 };
-- 
1.6.3.3


^ permalink raw reply related

* [RFC 1/4] orinoco: add cfg80211 connect and disconnect
From: David Kilroy @ 2009-08-05 20:32 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249504372-17063-1-git-send-email-kilroyd@googlemail.com>

Basic station mode support.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/cfg.c |  236 ++++++++++++++++++++++++++++++++++++
 1 files changed, 236 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 1a87d3a..56bd4f1 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -156,7 +156,243 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
 	return err;
 }
 
+/* Helper to ensure all keys are valid for the current encoding
+   algorithm */
+static void orinoco_set_encoding(struct orinoco_private *priv,
+				 enum orinoco_alg encoding)
+{
+	if (priv->encode_alg &&
+	    priv->encode_alg != encoding) {
+		int i;
+
+		for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
+			kfree(priv->keys[i].key);
+			kfree(priv->keys[i].seq);
+			priv->keys[i].key = NULL;
+			priv->keys[i].seq = NULL;
+			priv->keys[i].key_len = 0;
+			priv->keys[i].seq_len = 0;
+			priv->keys[i].cipher = 0;
+		}
+
+		if (priv->encode_alg == ORINOCO_ALG_TKIP &&
+		    priv->has_wpa) {
+			(void) orinoco_clear_tkip_key(priv, i);
+			(void) orinoco_clear_tkip_key(priv, i);
+			(void) orinoco_clear_tkip_key(priv, i);
+			(void) orinoco_clear_tkip_key(priv, i);
+		} else if (priv->encode_alg == ORINOCO_ALG_WEP)
+			__orinoco_hw_setup_wepkeys(priv);
+	}
+	priv->encode_alg = encoding;
+}
+
+/* Helper routine to record keys
+ * Do not call from interrupt context */
+static int orinoco_set_key(struct orinoco_private *priv, int index,
+			   enum orinoco_alg alg, const u8 *key, int key_len,
+			   const u8 *seq, int seq_len)
+{
+	kzfree(priv->keys[index].key);
+	kzfree(priv->keys[index].seq);
+
+	if (key_len) {
+		priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
+		if (!priv->keys[index].key)
+			goto nomem;
+	} else
+		priv->keys[index].key = NULL;
+
+	if (seq_len) {
+		priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
+		if (!priv->keys[index].seq)
+			goto free_key;
+	} else
+		priv->keys[index].seq = NULL;
+
+	priv->keys[index].key_len = key_len;
+	priv->keys[index].seq_len = seq_len;
+
+	if (key_len)
+		memcpy(priv->keys[index].key, key, key_len);
+	if (seq_len)
+		memcpy(priv->keys[index].seq, seq, seq_len);
+
+
+	switch (alg) {
+	case ORINOCO_ALG_TKIP:
+		priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
+		break;
+
+	case ORINOCO_ALG_WEP:
+		priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
+			WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
+		break;
+
+	case ORINOCO_ALG_NONE:
+	default:
+		priv->keys[index].cipher = 0;
+		break;
+	}
+
+	return 0;
+
+free_key:
+	kfree(priv->keys[index].key);
+	priv->keys[index].key = NULL;
+
+nomem:
+	priv->keys[index].key_len = 0;
+	priv->keys[index].seq_len = 0;
+	priv->keys[index].cipher = 0;
+
+	return -ENOMEM;
+}
+
+/* Setup channel, SSID and BSSID */
+static int __orinoco_connect(struct wiphy *wiphy,
+			     struct ieee80211_channel *channel,
+			     const u8 *bssid, const u8 *ssid,
+			     u8 ssid_len)
+{
+	struct orinoco_private *priv = wiphy_priv(wiphy);
+
+	if (channel) {
+		int chan;
+
+		chan = ieee80211_freq_to_dsss_chan(channel->center_freq);
+
+		if ((chan > 0) && (chan < NUM_CHANNELS) &&
+		    (priv->channel_mask & (1 << chan)))
+			priv->channel = chan;
+	}
+
+	memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
+	if (ssid)
+		memcpy(priv->desired_essid, ssid, ssid_len);
+
+	if (bssid) {
+		memcpy(priv->desired_bssid, bssid, ETH_ALEN);
+
+		/* Intersil firmware hangs if you try to roam manually
+		 * without an ESSID set. */
+		if ((priv->firmware_type == FIRMWARE_TYPE_INTERSIL) &&
+		    (priv->desired_essid[0] == 0)) {
+			printk(KERN_WARNING "%s: Desired SSID must be set for "
+			       "manual roaming\n", wiphy_name(wiphy));
+			return -EOPNOTSUPP;
+		}
+
+		priv->bssid_fixed = 1;
+	} else {
+		memset(priv->desired_bssid, 0, ETH_ALEN);
+		priv->bssid_fixed = 0;
+	}
+
+	return 0;
+}
+
+static int orinoco_connect(struct wiphy *wiphy, struct net_device *dev,
+			   struct cfg80211_connect_params *sme)
+{
+	struct orinoco_private *priv = wiphy_priv(wiphy);
+	enum orinoco_alg encode_alg;
+	unsigned long lock;
+	int err;
+
+	if (orinoco_lock(priv, &lock) != 0)
+		return -EBUSY;
+
+	/* Setup the requested parameters in priv. If the card is not
+	 * capable, then the driver will just ignore the settings that
+	 * it can't do. */
+	err = __orinoco_connect(wiphy, sme->channel, sme->bssid,
+				sme->ssid, sme->ssid_len);
+	if (err)
+		goto out;
+
+	switch (sme->auth_type) {
+	case NL80211_AUTHTYPE_OPEN_SYSTEM:
+		priv->wep_restrict = 0;
+		break;
+	case NL80211_AUTHTYPE_SHARED_KEY:
+		priv->wep_restrict = 1;
+		break;
+	/* Ignore all other settings */
+	default:
+		break;
+	}
+
+	switch (sme->crypto.cipher_group) {
+	case WLAN_CIPHER_SUITE_TKIP:
+		encode_alg = ORINOCO_ALG_TKIP;
+		break;
+
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		encode_alg = ORINOCO_ALG_WEP;
+		break;
+
+	default:
+		encode_alg = ORINOCO_ALG_NONE;
+	}
+
+	orinoco_set_encoding(priv, encode_alg);
+
+	/* What are we supposed to do with multiple AKM suites? */
+	if (sme->crypto.n_akm_suites > 0)
+		priv->key_mgmt = sme->crypto.akm_suites[0];
+
+	/* Finally, set WEP key */
+	if (encode_alg == ORINOCO_ALG_WEP) {
+		err = orinoco_set_key(priv, sme->key_idx, encode_alg,
+				      &sme->key[0], sme->key_len, NULL, 0);
+		if (err)
+			goto out;
+
+		priv->tx_key = sme->key_idx;
+	}
+
+	err = orinoco_commit(priv);
+
+out:
+	orinoco_unlock(priv, &lock);
+
+	return err;
+}
+
+static int orinoco_disconnect(struct wiphy *wiphy, struct net_device *dev,
+			      u16 reason_code)
+{
+	struct orinoco_private *priv = wiphy_priv(wiphy);
+	unsigned long lock;
+	u8 addr[ETH_ALEN];
+	int err;
+
+	if (orinoco_lock(priv, &lock) != 0)
+		return -EBUSY;
+
+	memset(priv->desired_bssid, 0, ETH_ALEN);
+	memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
+
+	err = orinoco_hw_get_current_bssid(priv, &addr[0]);
+
+	if (!err) {
+		err = orinoco_hw_disassociate(priv, &addr[0],
+					      reason_code);
+	}
+
+	if (err)
+		err = orinoco_commit(priv);
+
+	orinoco_unlock(priv, &lock);
+
+	return err;
+}
+
 const struct cfg80211_ops orinoco_cfg_ops = {
 	.change_virtual_intf = orinoco_change_vif,
 	.scan = orinoco_scan,
+	.connect = orinoco_connect,
+	.disconnect = orinoco_disconnect,
 };
-- 
1.6.3.3


^ permalink raw reply related

* [RFC 0/4] orinoco: use cfg80211 for key manipulation
From: David Kilroy @ 2009-08-05 20:32 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy

First attempt at connect/disconnect, join_ibss/leave_ibss, and add_key
etc. These patches rely on the series I just sent, but conflict with
Holgers set_channel patch. Simple to resolve, and I'll do that in my
next update.

This doesn't work yet*, but I've a number of questions.

- The cfg80211 notification functions like cfg80211_connect_result
  are not called in this series. Does the driver need to keep track of
  each call and make sure it calls the right notifer? Right now orinoco
  arbitrarily sends SIOCGIWAP, IWEVASSOCRESPIE and IWEVASSOCREQIE on
  ?authorisation? Also not sure how this will tie in with
  cfg80211_send_rx_auth/assoc.

- In station mode, is the connect crypto struct fully filled in
  regardless of WEP/WPA? I'd like to set priv->encode_alg at this stage,
  and then only accept keys of that type via add_key. Unfortunately
  join_ibss doesn't have similar info.

- In adhoc mode, how do you set open/shared WEP? i.e. how does orinoco
  know to set priv->wep_restrict?

- Digging around cfg80211, it looks like set_default_key isn't called
  when authentication is TKIP. How does the driver tell which key to use
  for transmit? Are we supposed to assume the group key is the transmit
  key?

- TKIP pairwise keys. I think orinoco has always ignored them. The Agere
  driver installed pairwaise keys to index 0. Should I attempt anything?

- TKIP and ad-hoc. err... I plan on leaving this alone.


All hints greatly appreciated :)



Dave.

* wpa_supplicant in wext mode gets stuck in the ASSOCIATING state.
  Haven't tried nl80211 mode.

---
David Kilroy (4):
  orinoco: add cfg80211 connect and disconnect
  orinoco: add cfg80211 join_ibss and leave_ibss
  orinoco: implement cfg80211 key manipulation functions
  orinoco: do WE via cfg80211

 drivers/net/wireless/orinoco/cfg.c  |  486 +++++++++++++++++++++++
 drivers/net/wireless/orinoco/wext.c |  726 +----------------------------------
 2 files changed, 497 insertions(+), 715 deletions(-)


^ permalink raw reply

* Re: [PATCH 1/2] ar9170: cleanup of bss_info_changed and beacon config
From: Christian Lamparter @ 2009-08-05 20:25 UTC (permalink / raw)
  To: Joerg Albert; +Cc: John W. Linville, linux-wireless@vger.kernel.org
In-Reply-To: <4A79D7E5.1080604@gmx.de>

On Wednesday 05 August 2009 21:05:09 Joerg Albert wrote:
> On 08/05/2009 04:04 AM, Christian Lamparter wrote:
> > the beacon timer isn't exclusively used to notify the driver when its 
> > time for a new beacon... The STA mode uses the same _timer_
> > in reverse to wait for the next beacon form the assoc. AP.
> >
> > so, to be on the safe side: why not preserve the old behavior for the
> > STA mode as well and simply tell the hardware about dtim & beacon interval?
> 
> ar9170_set_beacon_timers() uses the beacon interval only if for AP mode,
Although pretbtt is closely related to the beacon interval.
It has a slightly different purpose: It fires _before_ the beacon is sent.
So the host is able to do some _last msec_ changes to the beacon.

> dtim is left in STA mode.
both dtim_period and beacon_int are ORed

|
| if (ar->vif) {
|	v |= ar->vif->bss_conf.beacon_int;
|	switch() [...]
|	v |= ar->vif->bss_conf.dtim_period << 16;
| }
|

into AR9170_MAC_REG_BCN_PERIOD.

It would be a BUG if this setting is omitted in STA mode,
since dtim beacons are essential.
> > The only remaining question is where to disabled the timer for STA.
> > (which is in some way relevant to: [PATCH 2/2] because previously,
> >  these timers were always disabled by remove_interface.)
> > 
> > I think the best place is in ar9170_op_bss_info_changed:
> >        if (changed & BSS_CHANGED_ASSOC) {
> > 
> > just when bss_conf->assoc gets "0".
> 
> Yes. IMHO also enable on bss_conf->assoc == 1.
yes, but not necessary for bss_conf->assoc == 1,
ieee80211_set_associated sets BSS_CHANGED_BEACON_INT.

ar9170_set_beacon_timers is executed twice unless
you throw more code at it than just the assoc check & call.
But anyway, that's fine by me.

Thanks,
	Chr

^ permalink raw reply

* [PATCH 6/6] orinoco: consolidate storage of WEP and TKIP keys
From: David Kilroy @ 2009-08-05 20:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249503812-16921-1-git-send-email-kilroyd@googlemail.com>

When TKIP support was added, we stored the keys separately to avoid
issues when both TKIP and WEP keys are sent to the driver.

We need to consolidate the storage to convert to cfg80211, so do this
first and try iron out the issues.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/hw.c      |   42 +++++++++--
 drivers/net/wireless/orinoco/main.c    |   33 ++++++---
 drivers/net/wireless/orinoco/orinoco.h |    4 +-
 drivers/net/wireless/orinoco/wext.c    |  122 +++++++++++++++++++++-----------
 4 files changed, 139 insertions(+), 62 deletions(-)

diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 5b12654..40d8dfa 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -768,12 +768,29 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
 {
 	hermes_t *hw = &priv->hw;
 	int err = 0;
+	int i;
 
 	switch (priv->firmware_type) {
 	case FIRMWARE_TYPE_AGERE:
+	{
+		struct orinoco_key keys[ORINOCO_MAX_KEYS];
+
+		memset(&keys, 0, sizeof(keys));
+		for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
+			int len = min(priv->keys[i].key_len,
+				      ORINOCO_MAX_KEY_SIZE);
+			memcpy(&keys[i].data, priv->keys[i].key, len);
+			if (len > SMALL_KEY_SIZE)
+				keys[i].len = cpu_to_le16(LARGE_KEY_SIZE);
+			else if (len > 0)
+				keys[i].len = cpu_to_le16(SMALL_KEY_SIZE);
+			else
+				keys[i].len = cpu_to_le16(0);
+		}
+
 		err = HERMES_WRITE_RECORD(hw, USER_BAP,
 					  HERMES_RID_CNFWEPKEYS_AGERE,
-					  &priv->keys);
+					  &keys);
 		if (err)
 			return err;
 		err = hermes_write_wordrec(hw, USER_BAP,
@@ -782,28 +799,38 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
 		if (err)
 			return err;
 		break;
+	}
 	case FIRMWARE_TYPE_INTERSIL:
 	case FIRMWARE_TYPE_SYMBOL:
 		{
 			int keylen;
-			int i;
 
 			/* Force uniform key length to work around
 			 * firmware bugs */
-			keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
+			keylen = priv->keys[priv->tx_key].key_len;
 
 			if (keylen > LARGE_KEY_SIZE) {
 				printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
 				       priv->ndev->name, priv->tx_key, keylen);
 				return -E2BIG;
-			}
+			} else if (keylen > SMALL_KEY_SIZE)
+				keylen = LARGE_KEY_SIZE;
+			else if (keylen > 0)
+				keylen = SMALL_KEY_SIZE;
+			else
+				keylen = 0;
 
 			/* Write all 4 keys */
 			for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
+				u8 key[LARGE_KEY_SIZE] = { 0 };
+
+				memcpy(key, priv->keys[i].key,
+				       priv->keys[i].key_len);
+
 				err = hermes_write_ltv(hw, USER_BAP,
 						HERMES_RID_CNFDEFAULTKEY0 + i,
 						HERMES_BYTES_TO_RECLEN(keylen),
-						priv->keys[i].data);
+						key);
 				if (err)
 					return err;
 			}
@@ -829,8 +856,8 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
 	int auth_flag;
 	int enc_flag;
 
-	/* Setup WEP keys for WEP and WPA */
-	if (priv->encode_alg)
+	/* Setup WEP keys */
+	if (priv->encode_alg == ORINOCO_ALG_WEP)
 		__orinoco_hw_setup_wepkeys(priv);
 
 	if (priv->wep_restrict)
@@ -976,7 +1003,6 @@ int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
 	hermes_t *hw = &priv->hw;
 	int err;
 
-	memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
 	err = hermes_write_wordrec(hw, USER_BAP,
 				   HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
 				   key_idx);
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 931f7de..2c7dc65 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -341,12 +341,14 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
+	struct orinoco_tkip_key *key;
 	hermes_t *hw = &priv->hw;
 	int err = 0;
 	u16 txfid = priv->txfid;
 	struct ethhdr *eh;
 	int tx_control;
 	unsigned long flags;
+	int do_mic;
 
 	if (!netif_running(dev)) {
 		printk(KERN_ERR "%s: Tx on stopped device!\n",
@@ -378,9 +380,14 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (skb->len < ETH_HLEN)
 		goto drop;
 
+	key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key;
+
+	do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) &&
+		  (key != NULL));
+
 	tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
 
-	if (priv->encode_alg == ORINOCO_ALG_TKIP)
+	if (do_mic)
 		tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
 			HERMES_TXCTRL_MIC;
 
@@ -462,7 +469,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	/* Calculate Michael MIC */
-	if (priv->encode_alg == ORINOCO_ALG_TKIP) {
+	if (do_mic) {
 		u8 mic_buf[MICHAEL_MIC_LEN + 1];
 		u8 *mic;
 		size_t offset;
@@ -480,8 +487,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 			len = MICHAEL_MIC_LEN;
 		}
 
-		orinoco_mic(priv->tx_tfm_mic,
-			    priv->tkip_key[priv->tx_key].tx_mic,
+		orinoco_mic(priv->tx_tfm_mic, key->tx_mic,
 			    eh->h_dest, eh->h_source, 0 /* priority */,
 			    skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
 
@@ -926,6 +932,7 @@ static void orinoco_rx(struct net_device *dev,
 
 	/* Calculate and check MIC */
 	if (status & HERMES_RXSTAT_MIC) {
+		struct orinoco_tkip_key *key;
 		int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
 			      HERMES_MIC_KEY_ID_SHIFT);
 		u8 mic[MICHAEL_MIC_LEN];
@@ -939,14 +946,18 @@ static void orinoco_rx(struct net_device *dev,
 		skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
 		length -= MICHAEL_MIC_LEN;
 
-		orinoco_mic(priv->rx_tfm_mic,
-			    priv->tkip_key[key_id].rx_mic,
-			    desc->addr1,
-			    src,
+		key = (struct orinoco_tkip_key *) priv->keys[key_id].key;
+
+		if (!key) {
+			printk(KERN_WARNING "%s: Received encrypted frame from "
+			       "%pM using key %i, but key is not installed\n",
+			       dev->name, src, key_id);
+			goto drop;
+		}
+
+		orinoco_mic(priv->rx_tfm_mic, key->rx_mic, desc->addr1, src,
 			    0, /* priority or QoS? */
-			    skb->data,
-			    skb->len,
-			    &mic[0]);
+			    skb->data, skb->len, &mic[0]);
 
 		if (memcmp(mic, rxmic,
 			   MICHAEL_MIC_LEN)) {
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index badfc56..9ac6f1d 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -120,7 +120,8 @@ struct orinoco_private {
 	enum nl80211_iftype iw_mode;
 	enum orinoco_alg encode_alg;
 	u16 wep_restrict, tx_key;
-	struct orinoco_key keys[ORINOCO_MAX_KEYS];
+	struct key_params keys[ORINOCO_MAX_KEYS];
+
 	int bitratemode;
 	char nick[IW_ESSID_MAX_SIZE+1];
 	char desired_essid[IW_ESSID_MAX_SIZE+1];
@@ -150,7 +151,6 @@ struct orinoco_private {
 	u8 *wpa_ie;
 	int wpa_ie_len;
 
-	struct orinoco_tkip_key tkip_key[ORINOCO_MAX_KEYS];
 	struct crypto_hash *rx_tfm_mic;
 	struct crypto_hash *tx_tfm_mic;
 
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index f68bbe3..3e56f76 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -22,6 +22,67 @@
 
 #define MAX_RID_LEN 1024
 
+/* Helper routine to record keys
+ * Do not call from interrupt context */
+static int orinoco_set_key(struct orinoco_private *priv, int index,
+			   enum orinoco_alg alg, const u8 *key, int key_len,
+			   const u8 *seq, int seq_len)
+{
+	kzfree(priv->keys[index].key);
+	kzfree(priv->keys[index].seq);
+
+	if (key_len) {
+		priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
+		if (!priv->keys[index].key)
+			goto nomem;
+	} else
+		priv->keys[index].key = NULL;
+
+	if (seq_len) {
+		priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
+		if (!priv->keys[index].seq)
+			goto free_key;
+	} else
+		priv->keys[index].seq = NULL;
+
+	priv->keys[index].key_len = key_len;
+	priv->keys[index].seq_len = seq_len;
+
+	if (key_len)
+		memcpy(priv->keys[index].key, key, key_len);
+	if (seq_len)
+		memcpy(priv->keys[index].seq, seq, seq_len);
+
+	switch (alg) {
+	case ORINOCO_ALG_TKIP:
+		priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
+		break;
+
+	case ORINOCO_ALG_WEP:
+		priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
+			WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
+		break;
+
+	case ORINOCO_ALG_NONE:
+	default:
+		priv->keys[index].cipher = 0;
+		break;
+	}
+
+	return 0;
+
+free_key:
+	kfree(priv->keys[index].key);
+	priv->keys[index].key = NULL;
+
+nomem:
+	priv->keys[index].key_len = 0;
+	priv->keys[index].seq_len = 0;
+	priv->keys[index].cipher = 0;
+
+	return -ENOMEM;
+}
+
 static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
@@ -180,7 +241,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
 	int setindex = priv->tx_key;
 	enum orinoco_alg encode_alg = priv->encode_alg;
 	int restricted = priv->wep_restrict;
-	u16 xlen = 0;
 	int err = -EINPROGRESS;		/* Call commit handler */
 	unsigned long flags;
 
@@ -207,12 +267,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
 		if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
 			index = priv->tx_key;
 
-		/* Adjust key length to a supported value */
-		if (erq->length > SMALL_KEY_SIZE)
-			xlen = LARGE_KEY_SIZE;
-		else /* (erq->length > 0) */
-			xlen = SMALL_KEY_SIZE;
-
 		/* Switch on WEP if off */
 		if (encode_alg != ORINOCO_ALG_WEP) {
 			setindex = index;
@@ -229,7 +283,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
 			}
 		} else {
 			/* Set the index : Check that the key is valid */
-			if (priv->keys[index].len == 0) {
+			if (priv->keys[index].key_len == 0) {
 				err = -EINVAL;
 				goto out;
 			}
@@ -245,10 +299,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
 		restricted = 1;
 
 	if (erq->pointer && erq->length > 0) {
-		priv->keys[index].len = cpu_to_le16(xlen);
-		memset(priv->keys[index].data, 0,
-		       sizeof(priv->keys[index].data));
-		memcpy(priv->keys[index].data, keybuf, erq->length);
+		err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
+				      erq->length, NULL, 0);
 	}
 	priv->tx_key = setindex;
 
@@ -277,7 +329,6 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
-	u16 xlen = 0;
 	unsigned long flags;
 
 	if (!priv->has_wep)
@@ -299,11 +350,9 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
 	else
 		erq->flags |= IW_ENCODE_OPEN;
 
-	xlen = le16_to_cpu(priv->keys[index].len);
+	erq->length = priv->keys[index].key_len;
 
-	erq->length = xlen;
-
-	memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
+	memcpy(keybuf, priv->keys[index].key, erq->length);
 
 	orinoco_unlock(priv, &flags);
 	return 0;
@@ -789,7 +838,6 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
 	int idx, alg = ext->alg, set_key = 1;
 	unsigned long flags;
 	int err = -EINVAL;
-	u16 key_len;
 
 	if (orinoco_lock(priv, &flags) != 0)
 		return -EBUSY;
@@ -822,24 +870,17 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
 		switch (alg) {
 		case IW_ENCODE_ALG_NONE:
 			priv->encode_alg = ORINOCO_ALG_NONE;
-			priv->keys[idx].len = 0;
+			err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
+					      NULL, 0, NULL, 0);
 			break;
 
 		case IW_ENCODE_ALG_WEP:
-			if (ext->key_len > SMALL_KEY_SIZE)
-				key_len = LARGE_KEY_SIZE;
-			else if (ext->key_len > 0)
-				key_len = SMALL_KEY_SIZE;
-			else
+			if (ext->key_len <= 0)
 				goto out;
 
 			priv->encode_alg = ORINOCO_ALG_WEP;
-			priv->keys[idx].len = cpu_to_le16(key_len);
-
-			key_len = min(ext->key_len, key_len);
-
-			memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE);
-			memcpy(priv->keys[idx].data, ext->key, key_len);
+			err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
+					      ext->key, ext->key_len, NULL, 0);
 			break;
 
 		case IW_ENCODE_ALG_TKIP:
@@ -847,20 +888,21 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
 			u8 *tkip_iv = NULL;
 
 			if (!priv->has_wpa ||
-			    (ext->key_len > sizeof(priv->tkip_key[0])))
+			    (ext->key_len > sizeof(struct orinoco_tkip_key)))
 				goto out;
 
 			priv->encode_alg = ORINOCO_ALG_TKIP;
-			memset(&priv->tkip_key[idx], 0,
-			       sizeof(priv->tkip_key[idx]));
-			memcpy(&priv->tkip_key[idx], ext->key, ext->key_len);
 
 			if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
 				tkip_iv = &ext->rx_seq[0];
 
+			err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
+					      ext->key, ext->key_len, tkip_iv,
+					      ORINOCO_SEQ_LEN);
+
 			err = __orinoco_hw_set_tkip_key(priv, idx,
 				 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
-				 (u8 *) &priv->tkip_key[idx],
+				 priv->keys[idx].key,
 				 tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
 			if (err)
 				printk(KERN_ERR "%s: Error %d setting TKIP key"
@@ -918,16 +960,14 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
 		break;
 	case ORINOCO_ALG_WEP:
 		ext->alg = IW_ENCODE_ALG_WEP;
-		ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len),
-				     max_key_len);
-		memcpy(ext->key, priv->keys[idx].data, ext->key_len);
+		ext->key_len = min(priv->keys[idx].key_len, max_key_len);
+		memcpy(ext->key, priv->keys[idx].key, ext->key_len);
 		encoding->flags |= IW_ENCODE_ENABLED;
 		break;
 	case ORINOCO_ALG_TKIP:
 		ext->alg = IW_ENCODE_ALG_TKIP;
-		ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key),
-				     max_key_len);
-		memcpy(ext->key, &priv->tkip_key[idx], ext->key_len);
+		ext->key_len = min(priv->keys[idx].key_len, max_key_len);
+		memcpy(ext->key, priv->keys[idx].key, ext->key_len);
 		encoding->flags |= IW_ENCODE_ENABLED;
 		break;
 	}
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 5/6] orinoco: add function to retrieve current bssid
From: David Kilroy @ 2009-08-05 20:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249503812-16921-1-git-send-email-kilroyd@googlemail.com>

We will need this from the cfg80211 disassociate call.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/hw.c   |   12 ++++++++++++
 drivers/net/wireless/orinoco/hw.h   |    2 ++
 drivers/net/wireless/orinoco/wext.c |    4 +---
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 3e9021c..5b12654 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -1272,3 +1272,15 @@ int orinoco_hw_disassociate(struct orinoco_private *priv,
 				  &buf);
 	return err;
 }
+
+int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
+				 u8 *addr)
+{
+	hermes_t *hw = &priv->hw;
+	int err;
+
+	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
+			      ETH_ALEN, NULL, addr);
+
+	return err;
+}
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index b096786..8df6e87 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -53,5 +53,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
 			    const struct cfg80211_ssid *ssid);
 int orinoco_hw_disassociate(struct orinoco_private *priv,
 			    u8 *addr, u16 reason_code);
+int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
+				 u8 *addr);
 
 #endif /* _ORINOCO_HW_H_ */
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index f324bf9..f68bbe3 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -156,7 +156,6 @@ static int orinoco_ioctl_getwap(struct net_device *dev,
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 
-	hermes_t *hw = &priv->hw;
 	int err = 0;
 	unsigned long flags;
 
@@ -164,8 +163,7 @@ static int orinoco_ioctl_getwap(struct net_device *dev,
 		return -EBUSY;
 
 	ap_addr->sa_family = ARPHRD_ETHER;
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
-			      ETH_ALEN, NULL, ap_addr->sa_data);
+	err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
 
 	orinoco_unlock(priv, &flags);
 
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 4/6] orinoco: move disassociation to hw.c
From: David Kilroy @ 2009-08-05 20:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249503812-16921-1-git-send-email-kilroyd@googlemail.com>

This allows the disassociation to be called via cfg80211.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/hw.c   |   24 ++++++++++++++++++++++++
 drivers/net/wireless/orinoco/hw.h   |    2 ++
 drivers/net/wireless/orinoco/wext.c |   17 ++++-------------
 3 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 35516a9..3e9021c 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -1248,3 +1248,27 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
 
 	return err;
 }
+
+/* Disassociate from node with BSSID addr */
+int orinoco_hw_disassociate(struct orinoco_private *priv,
+			    u8 *addr, u16 reason_code)
+{
+	hermes_t *hw = &priv->hw;
+	int err;
+
+	struct {
+		u8 addr[ETH_ALEN];
+		__le16 reason_code;
+	} __attribute__ ((packed)) buf;
+
+	/* Currently only supported by WPA enabled Agere fw */
+	if (!priv->has_wpa)
+		return -EOPNOTSUPP;
+
+	memcpy(buf.addr, addr, ETH_ALEN);
+	buf.reason_code = cpu_to_le16(reason_code);
+	err = HERMES_WRITE_RECORD(hw, USER_BAP,
+				  HERMES_RID_CNFDISASSOCIATE,
+				  &buf);
+	return err;
+}
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index 33a31fa..b096786 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -51,5 +51,7 @@ int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
 			       int *numrates, s32 *rates, int max);
 int orinoco_hw_trigger_scan(struct orinoco_private *priv,
 			    const struct cfg80211_ssid *ssid);
+int orinoco_hw_disassociate(struct orinoco_private *priv,
+			    u8 *addr, u16 reason_code);
 
 #endif /* _ORINOCO_HW_H_ */
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index 7e18bb4..f324bf9 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -1136,7 +1136,6 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
 				  union iwreq_data *wrqu, char *extra)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
-	hermes_t *hw = &priv->hw;
 	struct iw_mlme *mlme = (struct iw_mlme *)extra;
 	unsigned long flags;
 	int ret = 0;
@@ -1150,19 +1149,11 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
 		break;
 
 	case IW_MLME_DISASSOC:
-	{
-		struct {
-			u8 addr[ETH_ALEN];
-			__le16 reason_code;
-		} __attribute__ ((packed)) buf;
-
-		memcpy(buf.addr, mlme->addr.sa_data, ETH_ALEN);
-		buf.reason_code = cpu_to_le16(mlme->reason_code);
-		ret = HERMES_WRITE_RECORD(hw, USER_BAP,
-					  HERMES_RID_CNFDISASSOCIATE,
-					  &buf);
+
+		ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
+					      mlme->reason_code);
 		break;
-	}
+
 	default:
 		ret = -EOPNOTSUPP;
 	}
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 3/6] orinoco: pass orinoco_set_tkip_key the sequence lengths
From: David Kilroy @ 2009-08-05 20:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249503812-16921-1-git-send-email-kilroyd@googlemail.com>

When we store the keys for cfg80211, the sequence lengths will also be
stored. So avoid assuming the sequence lengths at this level.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/hw.c   |   30 ++++++++++++++++++------------
 drivers/net/wireless/orinoco/hw.h   |    3 ++-
 drivers/net/wireless/orinoco/wext.c |    2 +-
 3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index d069fe8..35516a9 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -905,11 +905,12 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
 }
 
 /* key must be 32 bytes, including the tx and rx MIC keys.
- * rsc must be 8 bytes
- * tsc must be 8 bytes or NULL
+ * rsc must be NULL or up to 8 bytes
+ * tsc must be NULL or up to 8 bytes
  */
 int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
-			      int set_tx, u8 *key, u8 *rsc, u8 *tsc)
+			      int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
+			      u8 *tsc, size_t tsc_len)
 {
 	struct {
 		__le16 idx;
@@ -934,17 +935,22 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
 	memcpy(buf.key, key,
 	       sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
 
-	if (rsc == NULL)
-		memset(buf.rsc, 0, sizeof(buf.rsc));
-	else
-		memcpy(buf.rsc, rsc, sizeof(buf.rsc));
+	if (rsc_len > sizeof(buf.rsc))
+		rsc_len = sizeof(buf.rsc);
+
+	if (tsc_len > sizeof(buf.tsc))
+		tsc_len = sizeof(buf.tsc);
+
+	memset(buf.rsc, 0, sizeof(buf.rsc));
+	memset(buf.tsc, 0, sizeof(buf.tsc));
+
+	if (rsc != NULL)
+		memcpy(buf.rsc, rsc, rsc_len);
 
-	if (tsc == NULL) {
-		memset(buf.tsc, 0, sizeof(buf.tsc));
+	if (tsc != NULL)
+		memcpy(buf.tsc, tsc, tsc_len);
+	else
 		buf.tsc[4] = 0x10;
-	} else {
-		memcpy(buf.tsc, tsc, sizeof(buf.tsc));
-	}
 
 	/* Wait upto 100ms for tx queue to empty */
 	for (k = 100; k > 0; k--) {
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index 27b4276..33a31fa 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -38,7 +38,8 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv);
 int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv);
 int __orinoco_hw_setup_enc(struct orinoco_private *priv);
 int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
-			      int set_tx, u8 *key, u8 *rsc, u8 *tsc);
+			      int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
+			      u8 *tsc, size_t tsc_len);
 int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx);
 int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
 				    struct dev_addr_list *mc_list,
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index 33d81b4..7e18bb4 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -863,7 +863,7 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
 			err = __orinoco_hw_set_tkip_key(priv, idx,
 				 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
 				 (u8 *) &priv->tkip_key[idx],
-				 tkip_iv, NULL);
+				 tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
 			if (err)
 				printk(KERN_ERR "%s: Error %d setting TKIP key"
 				       "\n", dev->name, err);
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 2/6] orinoco: use local types for auth alg and sequence length
From: David Kilroy @ 2009-08-05 20:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249503812-16921-1-git-send-email-kilroyd@googlemail.com>

This helps in the refactorring required to convert the driver to
cfg80211.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/hw.c      |   12 ++++++------
 drivers/net/wireless/orinoco/main.c    |    6 +++---
 drivers/net/wireless/orinoco/orinoco.h |   10 +++++++++-
 drivers/net/wireless/orinoco/wext.c    |   30 +++++++++++++++---------------
 4 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index fa508af..d069fe8 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -642,7 +642,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
 {
 	hermes_t *hw = &priv->hw;
 	int err = 0;
-	u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
+	u8 tsc_arr[4][ORINOCO_SEQ_LEN];
 
 	if ((key < 0) || (key > 4))
 		return -EINVAL;
@@ -840,14 +840,14 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
 
 	if (priv->wpa_enabled)
 		enc_flag = 2;
-	else if (priv->encode_alg == IW_ENCODE_ALG_WEP)
+	else if (priv->encode_alg == ORINOCO_ALG_WEP)
 		enc_flag = 1;
 	else
 		enc_flag = 0;
 
 	switch (priv->firmware_type) {
 	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
-		if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
+		if (priv->encode_alg == ORINOCO_ALG_WEP) {
 			/* Enable the shared-key authentication. */
 			err = hermes_write_wordrec(hw, USER_BAP,
 					HERMES_RID_CNFAUTHENTICATION_AGERE,
@@ -872,7 +872,7 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
 
 	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
 	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
-		if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
+		if (priv->encode_alg == ORINOCO_ALG_WEP) {
 			if (priv->wep_restrict ||
 			    (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
 				master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
@@ -913,11 +913,11 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
 {
 	struct {
 		__le16 idx;
-		u8 rsc[IW_ENCODE_SEQ_MAX_SIZE];
+		u8 rsc[ORINOCO_SEQ_LEN];
 		u8 key[TKIP_KEYLEN];
 		u8 tx_mic[MIC_KEYLEN];
 		u8 rx_mic[MIC_KEYLEN];
-		u8 tsc[IW_ENCODE_SEQ_MAX_SIZE];
+		u8 tsc[ORINOCO_SEQ_LEN];
 	} __attribute__ ((packed)) buf;
 	hermes_t *hw = &priv->hw;
 	int ret;
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index e8c550a..931f7de 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -380,7 +380,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
 
-	if (priv->encode_alg == IW_ENCODE_ALG_TKIP)
+	if (priv->encode_alg == ORINOCO_ALG_TKIP)
 		tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
 			HERMES_TXCTRL_MIC;
 
@@ -462,7 +462,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	/* Calculate Michael MIC */
-	if (priv->encode_alg == IW_ENCODE_ALG_TKIP) {
+	if (priv->encode_alg == ORINOCO_ALG_TKIP) {
 		u8 mic_buf[MICHAEL_MIC_LEN + 1];
 		u8 *mic;
 		size_t offset;
@@ -2040,7 +2040,7 @@ int orinoco_init(struct orinoco_private *priv)
 	priv->channel = 0; /* use firmware default */
 
 	priv->promiscuous = 0;
-	priv->encode_alg = IW_ENCODE_ALG_NONE;
+	priv->encode_alg = ORINOCO_ALG_NONE;
 	priv->tx_key = 0;
 	priv->wpa_enabled = 0;
 	priv->tkip_cm_active = 0;
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 2a4eef1..badfc56 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -25,6 +25,7 @@
 
 #define MAX_SCAN_LEN		4096
 
+#define ORINOCO_SEQ_LEN		8
 #define ORINOCO_MAX_KEY_SIZE	14
 #define ORINOCO_MAX_KEYS	4
 
@@ -42,6 +43,12 @@ struct orinoco_tkip_key {
 	u8 rx_mic[MIC_KEYLEN];
 };
 
+enum orinoco_alg {
+	ORINOCO_ALG_NONE,
+	ORINOCO_ALG_WEP,
+	ORINOCO_ALG_TKIP
+};
+
 typedef enum {
 	FIRMWARE_TYPE_AGERE,
 	FIRMWARE_TYPE_INTERSIL,
@@ -111,7 +118,8 @@ struct orinoco_private {
 
 	/* Configuration paramaters */
 	enum nl80211_iftype iw_mode;
-	u16 encode_alg, wep_restrict, tx_key;
+	enum orinoco_alg encode_alg;
+	u16 wep_restrict, tx_key;
 	struct orinoco_key keys[ORINOCO_MAX_KEYS];
 	int bitratemode;
 	char nick[IW_ESSID_MAX_SIZE+1];
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index b6ff3db..33d81b4 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -180,7 +180,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
 	struct orinoco_private *priv = ndev_priv(dev);
 	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
 	int setindex = priv->tx_key;
-	int encode_alg = priv->encode_alg;
+	enum orinoco_alg encode_alg = priv->encode_alg;
 	int restricted = priv->wep_restrict;
 	u16 xlen = 0;
 	int err = -EINPROGRESS;		/* Call commit handler */
@@ -202,7 +202,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
 		return -EBUSY;
 
 	/* Clear any TKIP key we have */
-	if ((priv->has_wpa) && (priv->encode_alg == IW_ENCODE_ALG_TKIP))
+	if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
 		(void) orinoco_clear_tkip_key(priv, setindex);
 
 	if (erq->length > 0) {
@@ -212,15 +212,13 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
 		/* Adjust key length to a supported value */
 		if (erq->length > SMALL_KEY_SIZE)
 			xlen = LARGE_KEY_SIZE;
-		else if (erq->length > 0)
+		else /* (erq->length > 0) */
 			xlen = SMALL_KEY_SIZE;
-		else
-			xlen = 0;
 
 		/* Switch on WEP if off */
-		if ((encode_alg != IW_ENCODE_ALG_WEP) && (xlen > 0)) {
+		if (encode_alg != ORINOCO_ALG_WEP) {
 			setindex = index;
-			encode_alg = IW_ENCODE_ALG_WEP;
+			encode_alg = ORINOCO_ALG_WEP;
 		}
 	} else {
 		/* Important note : if the user do "iwconfig eth0 enc off",
@@ -242,7 +240,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
 	}
 
 	if (erq->flags & IW_ENCODE_DISABLED)
-		encode_alg = IW_ENCODE_ALG_NONE;
+		encode_alg = ORINOCO_ALG_NONE;
 	if (erq->flags & IW_ENCODE_OPEN)
 		restricted = 0;
 	if (erq->flags & IW_ENCODE_RESTRICTED)
@@ -825,7 +823,7 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
 		/* Set the requested key first */
 		switch (alg) {
 		case IW_ENCODE_ALG_NONE:
-			priv->encode_alg = alg;
+			priv->encode_alg = ORINOCO_ALG_NONE;
 			priv->keys[idx].len = 0;
 			break;
 
@@ -837,7 +835,7 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
 			else
 				goto out;
 
-			priv->encode_alg = alg;
+			priv->encode_alg = ORINOCO_ALG_WEP;
 			priv->keys[idx].len = cpu_to_le16(key_len);
 
 			key_len = min(ext->key_len, key_len);
@@ -854,7 +852,7 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
 			    (ext->key_len > sizeof(priv->tkip_key[0])))
 				goto out;
 
-			priv->encode_alg = alg;
+			priv->encode_alg = ORINOCO_ALG_TKIP;
 			memset(&priv->tkip_key[idx], 0,
 			       sizeof(priv->tkip_key[idx]));
 			memcpy(&priv->tkip_key[idx], ext->key, ext->key_len);
@@ -914,19 +912,21 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
 	encoding->flags = idx + 1;
 	memset(ext, 0, sizeof(*ext));
 
-	ext->alg = priv->encode_alg;
 	switch (priv->encode_alg) {
-	case IW_ENCODE_ALG_NONE:
+	case ORINOCO_ALG_NONE:
+		ext->alg = IW_ENCODE_ALG_NONE;
 		ext->key_len = 0;
 		encoding->flags |= IW_ENCODE_DISABLED;
 		break;
-	case IW_ENCODE_ALG_WEP:
+	case ORINOCO_ALG_WEP:
+		ext->alg = IW_ENCODE_ALG_WEP;
 		ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len),
 				     max_key_len);
 		memcpy(ext->key, priv->keys[idx].data, ext->key_len);
 		encoding->flags |= IW_ENCODE_ENABLED;
 		break;
-	case IW_ENCODE_ALG_TKIP:
+	case ORINOCO_ALG_TKIP:
+		ext->alg = IW_ENCODE_ALG_TKIP;
 		ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key),
 				     max_key_len);
 		memcpy(ext->key, &priv->tkip_key[idx], ext->key_len);
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 1/6] orinoco: prefer_port3 can be a single bit
From: David Kilroy @ 2009-08-05 20:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy
In-Reply-To: <1249503812-16921-1-git-send-email-kilroyd@googlemail.com>

This is a boolean value set based on firmware capabilities, so move the
variable to the capabilities section and reduce the structure size.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>
---
 drivers/net/wireless/orinoco/orinoco.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 5f4f5c9..2a4eef1 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -107,10 +107,10 @@ struct orinoco_private {
 	unsigned int do_fw_download:1;
 	unsigned int broken_disableport:1;
 	unsigned int broken_monitor:1;
+	unsigned int prefer_port3:1;
 
 	/* Configuration paramaters */
 	enum nl80211_iftype iw_mode;
-	int prefer_port3;
 	u16 encode_alg, wep_restrict, tx_key;
 	struct orinoco_key keys[ORINOCO_MAX_KEYS];
 	int bitratemode;
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 0/6] orinoco: preliminary refactorring before cfg80211 key handling
From: David Kilroy @ 2009-08-05 20:23 UTC (permalink / raw)
  To: linux-wireless; +Cc: orinoco-devel, David Kilroy

This series does a little clean up, moves a few common routines which we
will need in the cfg80211 handlers to hw.c, and puts all our keys in one
basket.

These have been running for a while on my machine, and I haven't noticed
any breakage.

Signed-off-by: David Kilroy <kilroyd@googlemail.com>

---
David Kilroy (6):
  orinoco: prefer_port3 can be a single bit
  orinoco: use local types for auth alg and sequence length
  orinoco: pass orinoco_set_tkip_key the sequence lengths
  orinoco: move disassociation to hw.c
  orinoco: add function to retrieve current bssid
  orinoco: consolidate storage of WEP and TKIP keys

 drivers/net/wireless/orinoco/hw.c      |  120 +++++++++++++++++-----
 drivers/net/wireless/orinoco/hw.h      |    7 +-
 drivers/net/wireless/orinoco/main.c    |   35 ++++--
 drivers/net/wireless/orinoco/orinoco.h |   16 ++-
 drivers/net/wireless/orinoco/wext.c    |  173 +++++++++++++++++++-------------
 5 files changed, 236 insertions(+), 115 deletions(-)


^ permalink raw reply

* RE: kernel panic ieee80211_agg_splice_packets+0x3d/0xc0 [mac80211]
From: Jack Lau @ 2009-08-05 19:23 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1248821338.5206.12.camel@mj>


Dear all
 
As a follow-up, I have tried the latest wireless-testing.git: v2.6.31-rc5-30113-gf1aa58f and the crash still persists.
 
I have also opened a new Bugzilla bug at http://bugzilla.kernel.org/show_bug.cgi?id=13922
 
Jack
_________________________________________________________________
Windows Live Messenger: Happy 10-Year Anniversary—get free winks and emoticons.
http://clk.atdmt.com/UKM/go/157562755/direct/01/

^ permalink raw reply

* Re: [PATCH 1/2] ar9170: cleanup of bss_info_changed and beacon config
From: Joerg Albert @ 2009-08-05 19:05 UTC (permalink / raw)
  To: Christian Lamparter; +Cc: John W. Linville, linux-wireless@vger.kernel.org
In-Reply-To: <200908050404.47371.chunkeey@web.de>

On 08/05/2009 04:04 AM, Christian Lamparter wrote:

> no signed/cc here?

oops, forgot it. Seems like both patches miss some context lines at the end, too.

> > ...
> the beacon timer isn't exclusively used to notify the driver when its 
> time for a new beacon... The STA mode uses the same _timer_
> in reverse to wait for the next beacon form the assoc. AP.

> that said: It does not look like the firmware implements anything
> in this direction... But this is a clearly MAC register and there
> could be something in the silicon which does something useful with
> this information.

I wasn't aware of this usage within STA mode.

> so, to be on the safe side: why not preserve the old behavior for the
> STA mode as well and simply tell the hardware about dtim & beacon interval?

ar9170_set_beacon_timers() uses the beacon interval only if for AP mode, dtim is left in STA mode.

> The only remaining question is where to disabled the timer for STA.
> (which is in some way relevant to: [PATCH 2/2] because previously,
>  these timers were always disabled by remove_interface.)
> 
> I think the best place is in ar9170_op_bss_info_changed:
>        if (changed & BSS_CHANGED_ASSOC) {
> 
> just when bss_conf->assoc gets "0".

Yes. IMHO also enable on bss_conf->assoc == 1.

I'll look into another version of both patches after running some tests in STA mode.


Regards,
Joerg.

^ permalink raw reply

* Re: [PATCH] wireless-regdb: TH gets 5 GHz enabled as of new regulatory rules
From: Luis R. Rodriguez @ 2009-08-05 18:58 UTC (permalink / raw)
  To: John W. Linville, Michael Green, David Quan
  Cc: Phattanon Duangdara, linux-wireless
In-Reply-To: <20090805181726.GC20338@tuxdriver.com>

Note: this e-mail is on a public mailing list.

Adding Michael and David again.

On Wed, Aug 5, 2009 at 11:17 AM, John W. Linville<linville@tuxdriver.com> wrote:
> On Thu, Jul 30, 2009 at 12:46:29PM +0700, Phattanon Duangdara wrote:
>> On Wed, Jul 29, 2009 at 10:18 PM, Luis R.
>> Rodriguez<lrodriguez@atheros.com> wrote:
>> > Note: this e-mail is in a public mailing list.
>> >
>> > Adding Michael and David. Michael, I'd appreciate your review on this,
>> > if possible.
>> >
>> > Phattanon, thanks for your review of the TH document and sharing it
>> > with us. Please see my reply inline below.
>> >
>> > On Wed, Jul 29, 2009 at 3:13 AM, Phattanon Duangdara<sfalpha@gmail.com> wrote:
>> >> I corrected redgb from my knowledge.
>> >
>> > Did you see my patch? I corrected TH to be:
>> >
>> > country TH:
>> >        (2402 - 2482 @ 20), (N/A, 20)
>> >        (5170 - 5250 @ 20), (3, 17)
>> >        (5250 - 5330 @ 20), (3, 20), DFS
>> >        (5490 - 5710 @ 20), (3, 20), DFS
>> >        (5735 - 5835 @ 20), (3, 30)
>> >
>> >> For 5150-5350 is for Indoor Use Only.
>> >> Most of the regulartory
>> >
>> > What do you mean by that? Do you mean that the document refers to FCC
>> > and ETSI/ITU standard for regulatory purposes for some items?
>> >
>> >> refer _either_ FCC or ETSI/ITU standard, so I
>> >> guess that from the document 40MHz can also be used (same as US)
>> >> because TH regulatory mostly cover all bandwidth on 40MHz.
>> >
>> > Are you saying the Thailand document refers to FCC for max allowed
>> > bandwidth spacing and therefore US max bandwidth spacing should be
>> > used (ie allow 40 MHz width channels)?
>>
>> I am not sure about this. But if equipment that comply with FCC
>> standard allow to use 40MHz, I think we can because, for example
>> Translated rule for 2.4GHz says
>
> <snip>
>
> So, is the patch from Luis wrong?  If so, what is the correct patch?

Although Phattanon didn't post a patch I interpreted it as he was
suggesting we can enable 40 MHz channels on Thailand as well since he
points out that Thailand regulatory rules refer to the FCC for
bandwidth compliance.

Michael does this interpretation match yours? Can we allow 40 MHz in TH?

Phattanon also specified some differences on max EIRP but I think that
should go as a separate patch and reviewed as such.

  Luis

^ permalink raw reply

* Re: mac80211 TX frame alignment
From: Ivo van Doorn @ 2009-08-05 18:57 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1249407436.24787.6.camel@johannes.local>

Hi,

> > Do you know if for outgoing frames the header should always
> > be 4-byte aligned?
> 
> I know that there's no alignment guarantee.
>
> > I have a bugreport from users claiming that master mode
> > is failing for rt2500pci because the beacons passed to the
> > driver are not 4-byte aligned which causes the device not
> > to send out the beacons correctly.
> > 
> > I'm just wondering if this is something that should be fixed
> > in the driver or in mac80211.
> 
> I don't think we can fix that in mac80211, since we don't know whether
> or not any alignment is required. We could align beacon frames, I
> suppose, since those are created on the fly, but not data frames.

Ok, I'll look into a patch for making sure rt2x00 aligns all frames
correctly before mapping the DMA.

Thanks,

Ivo

^ permalink raw reply

* Re: [rt2x00-users] [PATCH] rt2x00: fix memory corruption in rf cache, add a sanity check
From: Ivo van Doorn @ 2009-08-05 18:55 UTC (permalink / raw)
  To: Pavel Roskin; +Cc: users, linux-wireless, John W. Linville, Michael Buesch
In-Reply-To: <1249422496.3489.2.camel@mj>

Hi,

> Change rt2x00_rf_read() and rt2x00_rf_write() to subtract 1 from the rf
> register number.  This is needed because the rf registers are enumerated
> starting with one.  The size of the rf register cache is just enough to
> hold all registers, so writing to the highest register was corrupting
> memory.  Add a check to make sure that the rf register number is valid.
> 
> Signed-off-by: Pavel Roskin <proski@gnu.org>

Good catch. Thanks!

Acked-by: Ivo van Doorn <IvDoorn@gmail.com>

> ---
> 
> That's the issue reported by Michael Buesch:
> http://marc.info/?l=linux-wireless&m=124886312314098&w=2
> 
> With this patch and the patch to stop works on unload, rt73usb seems
> rock solid now. 
>
>  drivers/net/wireless/rt2x00/rt2x00.h |    6 ++++--
>  1 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> index cbec91e..ee9afab 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00.h
> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> @@ -836,13 +836,15 @@ struct rt2x00_dev {
>  static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
>  				  const unsigned int word, u32 *data)
>  {
> -	*data = rt2x00dev->rf[word];
> +	BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
> +	*data = rt2x00dev->rf[word - 1];
>  }
>  
>  static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
>  				   const unsigned int word, u32 data)
>  {
> -	rt2x00dev->rf[word] = data;
> +	BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
> +	rt2x00dev->rf[word - 1] = data;
>  }
>  
>  /*
> 
> 
> 



^ permalink raw reply

* Re: [PATCH] compat-2.6: Makefile: fixed test expressions for target install
From: Luis R. Rodriguez @ 2009-08-05 18:32 UTC (permalink / raw)
  To: Joerg Albert; +Cc: Pavel Roskin, linux-wireless@vger.kernel.org
In-Reply-To: <4A741B7B.7070200@gmx.de>

On Sat, Aug 1, 2009 at 3:39 AM, Joerg Albert<jal2@gmx.de> wrote:
> On 08/01/2009 01:22 AM, Luis R. Rodriguez wrote:
>>
>> Actually please do keep relying on /bin/bash, all the scripts on
>> compat-wireless do depend on /bin/bash, I don't expect users of
>> dash/etc to use compat-wireless.
>>
>> If we want to make compat-wireless be shell agnostic we'd need to
>> address all the other scripts. I rather not deal with that now unless
>> we really think that is also a good idea and someone is up for the
>> task.
>
> IMHO we could make bug fixes to the Makefile/scripts shell agnostic if it's
> not much effort and
> doesn't break readability, which is neither the case here.

Applied, thanks.

  Luis

^ permalink raw reply


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