Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] ssb: Implement fast powerup delay calculation
From: Gábor Stefanik @ 2010-05-01 17:13 UTC (permalink / raw)
  To: Michael Buesch; +Cc: John W. Linville, linux-wireless, b43-dev, Larry Finger
In-Reply-To: <201005011907.05603.mb@bu3sch.de>

2010/5/1 Michael Buesch <mb@bu3sch.de>:
> On Saturday 01 May 2010 18:29:06 Gábor Stefanik wrote:
>> +     ssb_write16(cc->dev, SSB_MMIO_POWERUP_DELAY, delay);
>>   }
>>
>>   void ssb_chipco_suspend(struct ssb_chipcommon *cc)
>> Index: wireless-testing/include/linux/ssb/ssb_regs.h
>> ===================================================================
>> --- wireless-testing.orig/include/linux/ssb/ssb_regs.h
>> +++ wireless-testing/include/linux/ssb/ssb_regs.h
>> @@ -26,6 +26,7 @@
>>   #define     SSB_EUART               (SSB_EXTIF_BASE + 0x00800000)
>>   #define     SSB_LED                 (SSB_EXTIF_BASE + 0x00900000)
>>
>> +#define SSB_MMIO_POWERUP_DELAY       0x06A8
>
> I think you are really confusing something here.
> That register is a wireless core register and we already write it in b43.
>
> --
> Greetings, Michael.
>

This is what I am implementing: http://bcm-v4.sipsolutions.net/802.11/Init
Here, it clearly says MMIO offset.

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

^ permalink raw reply

* Re: ar9170-fw II
From: Christian Lamparter @ 2010-05-01 17:19 UTC (permalink / raw)
  To: David H. Lynch Jr.; +Cc: linux-wireless
In-Reply-To: <4BDC001F.9050202@dlasys.net>

On Saturday 01 May 2010 12:19:11 David H. Lynch Jr. wrote:
> I have ethernet driver experience but not wifi. I have a project to 
> add some features to the ar9170 that will require additions to the 
> firmware. I would appreciate pointers for docs etc. to get me started.

Well, for starters the ar9170 uses a ZyDas MAC (aka ZD1221)
and a AR900x PHY/Radio. Therefore the phy code and registers
are very similar to those #definitions you can find in ath9k.
And for the MAC code & registers you can look into zd1211rw,
or look into drivers/staging/otus (original vendor driver,
shares some code with their windows drivers)

AFAICT, there are no technical documents about the AR9170 
solution available w/o signing a NDA with Atheros
(probably because the devices are still produced and sold in high quantities?).

> What is available for the ar9170 itself ?
> How does the firmware and the linux driver communicate?
>   Is there an overview of the firmware - what is where ?

not really, apart from the headers of the original firmware 
and vendor drivers.

But if you really need to implement some of your 'features'
(what are they, if I may ask?) into the firmware you could
save some time by migrating to carl9170 code base:
( http://www.kernel.org/pub/linux/kernel/people/chr/carl9170/1.0.5 
  + linville's wireless-testing.git )

The advantages over the original firmware code (from a developers POV) are:
 * customizable/configurable fw
	+ driver can auto detect all selected fw features

 * userspace testbench ( carlu ) for the usb subsystem
   (allows you to run usb stress-test, dump the device's eeprom content
    to stdout and of course: you can implement your own routines
    and test & develop without crashing the kernel)

 * all hardware & firmware interface definitions are all located 
   in a single directory /include/shared/*.h

	version.h	- carl9170 API/ABI version
	eeprom.h	- eeprom layout
	phy.h		- AR900x PHY/Radio definitions
	fwcmd.h		- implemented firmware commands
	fwdesc.h	- layout of the firmware descriptor (e.g. available/activated features)
	hw.h		- ZD1221 MAC + (Faraday USB) definitions
		wlan.h	- (part of hw.h & phy.h) contains all the information about
				  tx & rx frame formats.

 * (tiny) printf + hexdump (obviously, you want those ;-) )

 * follows linux' kernel coding style :-D

Regards,
	Chr

^ permalink raw reply

* Re: [PATCH] ssb: Implement fast powerup delay calculation
From: Michael Buesch @ 2010-05-01 17:19 UTC (permalink / raw)
  To: Gábor Stefanik
  Cc: John W. Linville, linux-wireless, b43-dev, Larry Finger
In-Reply-To: <AANLkTimXBlIETHVLapuSrkI8uTIU8JPepLWvAEq6_D4T@mail.gmail.com>

On Saturday 01 May 2010 19:13:31 Gábor Stefanik wrote:
> 2010/5/1 Michael Buesch <mb@bu3sch.de>:
> > On Saturday 01 May 2010 18:29:06 Gábor Stefanik wrote:
> >> +     ssb_write16(cc->dev, SSB_MMIO_POWERUP_DELAY, delay);
> >>   }
> >>
> >>   void ssb_chipco_suspend(struct ssb_chipcommon *cc)
> >> Index: wireless-testing/include/linux/ssb/ssb_regs.h
> >> ===================================================================
> >> --- wireless-testing.orig/include/linux/ssb/ssb_regs.h
> >> +++ wireless-testing/include/linux/ssb/ssb_regs.h
> >> @@ -26,6 +26,7 @@
> >>   #define     SSB_EUART               (SSB_EXTIF_BASE + 0x00800000)
> >>   #define     SSB_LED                 (SSB_EXTIF_BASE + 0x00900000)
> >>
> >> +#define SSB_MMIO_POWERUP_DELAY       0x06A8
> >
> > I think you are really confusing something here.
> > That register is a wireless core register and we already write it in b43.
> >
> > --
> > Greetings, Michael.
> >
> 
> This is what I am implementing: http://bcm-v4.sipsolutions.net/802.11/Init
> Here, it clearly says MMIO offset. 

Yeah. Just what I said. It is an 802.11 core register.
We already write it in b43/main.c/b43_chip_init().
It is _wrong_ to write to the chipcommon at that offset.

-- 
Greetings, Michael.

^ permalink raw reply

* Re: [PATCH] ssb: Implement fast powerup delay calculation
From: Gábor Stefanik @ 2010-05-01 17:19 UTC (permalink / raw)
  To: Michael Buesch; +Cc: John W. Linville, linux-wireless, b43-dev, Larry Finger
In-Reply-To: <AANLkTimXBlIETHVLapuSrkI8uTIU8JPepLWvAEq6_D4T@mail.gmail.com>

2010/5/1 Gábor Stefanik <netrolller.3d@gmail.com>:
> 2010/5/1 Michael Buesch <mb@bu3sch.de>:
>> On Saturday 01 May 2010 18:29:06 Gábor Stefanik wrote:
>>> +     ssb_write16(cc->dev, SSB_MMIO_POWERUP_DELAY, delay);
>>>   }
>>>
>>>   void ssb_chipco_suspend(struct ssb_chipcommon *cc)
>>> Index: wireless-testing/include/linux/ssb/ssb_regs.h
>>> ===================================================================
>>> --- wireless-testing.orig/include/linux/ssb/ssb_regs.h
>>> +++ wireless-testing/include/linux/ssb/ssb_regs.h
>>> @@ -26,6 +26,7 @@
>>>   #define     SSB_EUART               (SSB_EXTIF_BASE + 0x00800000)
>>>   #define     SSB_LED                 (SSB_EXTIF_BASE + 0x00900000)
>>>
>>> +#define SSB_MMIO_POWERUP_DELAY       0x06A8
>>
>> I think you are really confusing something here.
>> That register is a wireless core register and we already write it in b43.
>>
>> --
>> Greetings, Michael.
>>
>
> This is what I am implementing: http://bcm-v4.sipsolutions.net/802.11/Init
> Here, it clearly says MMIO offset.
>
> --
> Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
>

Sorry, now I understand. The MMIO write is unnecessary.

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

^ permalink raw reply

* Re: [PATCH] ssb: Implement fast powerup delay calculation
From: Larry Finger @ 2010-05-01 17:42 UTC (permalink / raw)
  To: Michael Buesch
  Cc: Gábor Stefanik, John W. Linville, linux-wireless, b43-dev
In-Reply-To: <201005011919.42294.mb@bu3sch.de>

On 05/01/2010 12:19 PM, Michael Buesch wrote:
> On Saturday 01 May 2010 19:13:31 Gábor Stefanik wrote:
>> 2010/5/1 Michael Buesch <mb@bu3sch.de>:
>>> On Saturday 01 May 2010 18:29:06 Gábor Stefanik wrote:
>>>> +     ssb_write16(cc->dev, SSB_MMIO_POWERUP_DELAY, delay);
>>>>   }
>>>>
>>>>   void ssb_chipco_suspend(struct ssb_chipcommon *cc)
>>>> Index: wireless-testing/include/linux/ssb/ssb_regs.h
>>>> ===================================================================
>>>> --- wireless-testing.orig/include/linux/ssb/ssb_regs.h
>>>> +++ wireless-testing/include/linux/ssb/ssb_regs.h
>>>> @@ -26,6 +26,7 @@
>>>>   #define     SSB_EUART               (SSB_EXTIF_BASE + 0x00800000)
>>>>   #define     SSB_LED                 (SSB_EXTIF_BASE + 0x00900000)
>>>>
>>>> +#define SSB_MMIO_POWERUP_DELAY       0x06A8
>>>
>>> I think you are really confusing something here.
>>> That register is a wireless core register and we already write it in b43.
>>>
>>> --
>>> Greetings, Michael.
>>>
>>
>> This is what I am implementing: http://bcm-v4.sipsolutions.net/802.11/Init
>> Here, it clearly says MMIO offset. 
> 
> Yeah. Just what I said. It is an 802.11 core register.
> We already write it in b43/main.c/b43_chip_init().
> It is _wrong_ to write to the chipcommon at that offset.

I may have gotten the MMIO offset part wrong in the specs, but the
Broadcom driver definitely writes to offset 0x648 at that point.

I know that b43 writes that location; however, it is much later in the
startup sequence. Whether that is important is unknown at this point.

The previous code resulted in a value of zero being written to the
location in question, but the value for the 4315 is 7000.

Larry

^ permalink raw reply

* Re: [PATCH] ssb: Implement fast powerup delay calculation
From: Gábor Stefanik @ 2010-05-01 17:48 UTC (permalink / raw)
  To: Larry Finger; +Cc: Michael Buesch, John W. Linville, linux-wireless, b43-dev
In-Reply-To: <4BDC6803.9030805@lwfinger.net>

On Sat, May 1, 2010 at 7:42 PM, Larry Finger <Larry.Finger@lwfinger.net> wrote:
> On 05/01/2010 12:19 PM, Michael Buesch wrote:
>> On Saturday 01 May 2010 19:13:31 Gábor Stefanik wrote:
>>> 2010/5/1 Michael Buesch <mb@bu3sch.de>:
>>>> On Saturday 01 May 2010 18:29:06 Gábor Stefanik wrote:
>>>>> +     ssb_write16(cc->dev, SSB_MMIO_POWERUP_DELAY, delay);
>>>>>   }
>>>>>
>>>>>   void ssb_chipco_suspend(struct ssb_chipcommon *cc)
>>>>> Index: wireless-testing/include/linux/ssb/ssb_regs.h
>>>>> ===================================================================
>>>>> --- wireless-testing.orig/include/linux/ssb/ssb_regs.h
>>>>> +++ wireless-testing/include/linux/ssb/ssb_regs.h
>>>>> @@ -26,6 +26,7 @@
>>>>>   #define     SSB_EUART               (SSB_EXTIF_BASE + 0x00800000)
>>>>>   #define     SSB_LED                 (SSB_EXTIF_BASE + 0x00900000)
>>>>>
>>>>> +#define SSB_MMIO_POWERUP_DELAY       0x06A8
>>>>
>>>> I think you are really confusing something here.
>>>> That register is a wireless core register and we already write it in b43.
>>>>
>>>> --
>>>> Greetings, Michael.
>>>>
>>>
>>> This is what I am implementing: http://bcm-v4.sipsolutions.net/802.11/Init
>>> Here, it clearly says MMIO offset.
>>
>> Yeah. Just what I said. It is an 802.11 core register.
>> We already write it in b43/main.c/b43_chip_init().
>> It is _wrong_ to write to the chipcommon at that offset.
>
> I may have gotten the MMIO offset part wrong in the specs, but the
> Broadcom driver definitely writes to offset 0x648 at that point.
>
> I know that b43 writes that location; however, it is much later in the
> startup sequence. Whether that is important is unknown at this point.
>
> The previous code resulted in a value of zero being written to the
> location in question, but the value for the 4315 is 7000.
>
> Larry
>

According to http://bcm-v4.sipsolutions.net/802.11/Init, b43 is right
- the write should go to the 802.11 core, not ChipCommon.

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

^ permalink raw reply

* Re: [PATCH] ssb: Implement fast powerup delay calculation
From: Michael Buesch @ 2010-05-01 18:15 UTC (permalink / raw)
  To: Larry Finger
  Cc: Gábor Stefanik, John W. Linville, linux-wireless, b43-dev
In-Reply-To: <4BDC6803.9030805@lwfinger.net>

On Saturday 01 May 2010 19:42:27 Larry Finger wrote:
> I may have gotten the MMIO offset part wrong in the specs, but the
> Broadcom driver definitely writes to offset 0x648 at that point.

I do not think you are right.

First: The write has to happen to the 802.11 core and not to the chipcommon core.

Second: The code that was touched by Gábor is _very_ early in the SSB init.
Way ahead of the wireless core init. The specs state that the delay value has to be written
after the wireless core init is nearly done.
We do _exactly_ that in b43.

The only thing that needs to be done is to add the additional switch statement.
No MMIO writes have to be touched.

-- 
Greetings, Michael.

^ permalink raw reply

* Re: ar9170-fw II
From: David H. Lynch Jr. @ 2010-05-01 18:23 UTC (permalink / raw)
  To: Christian Lamparter, linux-wireless
In-Reply-To: <201005011919.32016.chunkeey@googlemail.com>

On 05/01/2010 01:19 PM, Christian Lamparter wrote:
>
> Well, for starters the ar9170 uses a ZyDas MAC (aka ZD1221)
> and a AR900x PHY/Radio. Therefore the phy code and registers
> are very similar to those #definitions you can find in ath9k.
> And for the MAC code&  registers you can look into zd1211rw,
> or look into drivers/staging/otus (original vendor driver,
> shares some code with their windows drivers)
>
> AFAICT, there are no technical documents about the AR9170
> solution available w/o signing a NDA with Atheros
> (probably because the devices are still produced and sold in high quantities?).
>    
     Thanks;
         I did just discover a reasonably good 150p spec. in what I 
received from my client.
         If I can I will share it. I am under an NDA, but the client 
also told me that they received no cooperation from atheros.
>> What is available for the ar9170 itself ?
>> How does the firmware and the linux driver communicate?
>>    Is there an overview of the firmware - what is where ?
>>      
> not really, apart from the headers of the original firmware
> and vendor drivers.
>
> But if you really need to implement some of your 'features'
> (what are they, if I may ask?)
     I think I can tell you what I am supposed add - I need to be able 
to provide userspace apps with precise timing information for each packet.
     Since i am working on GPL'd code and the results are going to be 
provided to third parties whatever I do is GPL'd too.
     Why gets into the NDA.

     Right now i have an NDA with a new client and though I am 
exercising care. But they seem fairly mellow. I am probably just being 
overly cautious.


> into the firmware you could
> save some time by migrating to carl9170 code base:
> ( http://www.kernel.org/pub/linux/kernel/people/chr/carl9170/1.0.5
>    + linville's wireless-testing.git )
>    
     The carl9170 code is the expected future of the ar9170 in Linux ?
     If so that is where I want to be working.
> The advantages over the original firmware code (from a developers POV) are:
>   * customizable/configurable fw
> 	+ driver can auto detect all selected fw features
>
>   * userspace testbench ( carlu ) for the usb subsystem
>     (allows you to run usb stress-test, dump the device's eeprom content
>      to stdout and of course: you can implement your own routines
>      and test&  develop without crashing the kernel)
>
>   * all hardware&  firmware interface definitions are all located
>     in a single directory /include/shared/*.h
>
> 	version.h	- carl9170 API/ABI version
> 	eeprom.h	- eeprom layout
> 	phy.h		- AR900x PHY/Radio definitions
> 	fwcmd.h		- implemented firmware commands
> 	fwdesc.h	- layout of the firmware descriptor (e.g. available/activated features)
> 	hw.h		- ZD1221 MAC + (Faraday USB) definitions
> 		wlan.h	- (part of hw.h&  phy.h) contains all the information about
> 				  tx&  rx frame formats.
>
>   * (tiny) printf + hexdump (obviously, you want those ;-) )
>
>   * follows linux' kernel coding style :-D
>    
     Thanks alot.
         I will look seriously at that.
         While I want to keep the scope of what I am doing small, and as 
narrowly confined as a I can,
     it would be nice if atleast some of my work was useful beyond the 
unique needs of my client.

> Regards,
> 	Chr
>    


-- 
Dave Lynch 					  	    DLA Systems
Software Development:  				         Embedded Linux
717.587.7774 	       dhlii@dlasys.net 	  http://www.dlasys.net
Over 25 years' experience in platforms, languages, and technologies too numerous to list.

"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein


^ permalink raw reply

* Re: [PATCH] ssb: Implement fast powerup delay calculation
From: Larry Finger @ 2010-05-01 18:27 UTC (permalink / raw)
  To: Michael Buesch
  Cc: Gábor Stefanik, John W. Linville, linux-wireless, b43-dev
In-Reply-To: <201005012015.50601.mb@bu3sch.de>

On 05/01/2010 01:15 PM, Michael Buesch wrote:
> On Saturday 01 May 2010 19:42:27 Larry Finger wrote:
>> I may have gotten the MMIO offset part wrong in the specs, but the
>> Broadcom driver definitely writes to offset 0x648 at that point.
> 
> I do not think you are right.
> 
> First: The write has to happen to the 802.11 core and not to the chipcommon core.
> 
> Second: The code that was touched by Gábor is _very_ early in the SSB init.
> Way ahead of the wireless core init. The specs state that the delay value has to be written
> after the wireless core init is nearly done.
> We do _exactly_ that in b43.
> 
> The only thing that needs to be done is to add the additional switch statement.
> No MMIO writes have to be touched.

OK, I changed the spec to remove the write.

Larry

^ permalink raw reply

* Re: Issues setting up a 5GHz 802.11N AP
From: Luis R. Rodriguez @ 2010-05-01 18:34 UTC (permalink / raw)
  To: Joshua Smith; +Cc: linux-wireless
In-Reply-To: <7F414AFA-E125-40AD-A745-30AEC442B1E8@kaon.com>

On Thu, Apr 29, 2010 at 10:17 AM, Joshua Smith <jesmith@kaon.com> wrote:
> Hello!  I hope this is the right mailing this for this question.  If not, please redirect me as you see fit!
>
> I am trying to put together a Linux PC that can act as a 5 GHz 802.11N Access Point.  I got a lot of conflicting info in my searches, so I figured I'd just buy some hardware and figure out what works.
>
> I am using this kernel:
>
>  Linux vosk 2.6.27.8 #1 SMP Sun Dec 7 08:30:31 i686 Intel(R) Core(TM) i7 CPU 930  @ 2.80GHz GenuineIntel GNU/Linux
>
> And I am using compat-wireless 2010-04-26 (complete build).
>
> So far, I have an Intel Wi-Fi Link 6300AGN:
>
>  iwlagn 0000:07:00.0: Detected Intel(R) Centrino(R) Ultimate-N 6300 AGN, REV=0x74
>
> An Atheros-based Belkin N1 Wireless ExpressCard:
>
>  phy1: Atheros AR5418 MAC/BB Rev:2 AR2122 RF Rev:81 mem=0xf9fa0000, irq=16
>
> And an RaLink-based Asus PCE-N13 PCI adapter:
>
>  03:00.0 Network controller: RaLink RT2860
>
> When I do 'iw list' for these three cards, I find:
>
> Intel: has 5GHz band, but does not support AP mode
> Atheros: supports AP mode, but does not show 5GHz band
> RaLink: supports AP mode, but does not show 5GHz band
>
> I think the Intel is correct.  I've found many sources that say this chipset simply does not support AP/Master mode.
>
> However, both the Atheros and RaLink claim to support 300Mbps speeds, which I believe means they should have some 5Ghz channels, right?

No, if you see no 5GHz information with 'iw list' then it means your
cards do not support 5 GHz. Its a physical limitation of the actual
hardware. To support 5 GHz your card would need a 5 GHz radio, and it
simply does not come with one. For your Atheros card specifically the
output shows a AR2122 RF, this is a 2.4 GHz radio only.

  Luis

^ permalink raw reply

* Re: [PATCH] ssb: Implement fast powerup delay calculation
From: Michael Buesch @ 2010-05-01 18:40 UTC (permalink / raw)
  To: Larry Finger
  Cc: Gábor Stefanik, John W. Linville, linux-wireless, b43-dev
In-Reply-To: <4BDC729E.5060202@lwfinger.net>

On Saturday 01 May 2010 20:27:42 Larry Finger wrote:
> OK, I changed the spec to remove the write.

Uhm, I think the spec was perfecly fine.

-- 
Greetings, Michael.

^ permalink raw reply

* Re: [PATCH] ssb: Implement fast powerup delay calculation
From: Gábor Stefanik @ 2010-05-01 18:43 UTC (permalink / raw)
  To: Michael Buesch; +Cc: Larry Finger, John W. Linville, linux-wireless, b43-dev
In-Reply-To: <201005012040.42916.mb@bu3sch.de>

On Sat, May 1, 2010 at 8:40 PM, Michael Buesch <mb@bu3sch.de> wrote:
> On Saturday 01 May 2010 20:27:42 Larry Finger wrote:
>> OK, I changed the spec to remove the write.
>
> Uhm, I think the spec was perfecly fine.
>
> --
> Greetings, Michael.
>

Yes. The specs stated "do this during 802.11 core init", the problem
was the patch doing the write during ChipCommon init, much earlier.

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

^ permalink raw reply

* Re: ar9170-fw II
From: Christian Lamparter @ 2010-05-01 20:45 UTC (permalink / raw)
  To: David H. Lynch Jr.; +Cc: linux-wireless
In-Reply-To: <4BDC719E.3060505@dlasys.net>

On Saturday 01 May 2010 20:23:26 David H. Lynch Jr. wrote:
> On 05/01/2010 01:19 PM, Christian Lamparter wrote:
> >
> > Well, for starters the ar9170 uses a ZyDas MAC (aka ZD1221)
> > and a AR900x PHY/Radio. Therefore the phy code and registers
> > are very similar to those #definitions you can find in ath9k.
> > And for the MAC code&  registers you can look into zd1211rw,
> > or look into drivers/staging/otus (original vendor driver,
> > shares some code with their windows drivers)
> >
> > AFAICT, there are no technical documents about the AR9170
> > solution available w/o signing a NDA with Atheros
> > (probably because the devices are still produced and sold in high quantities?).
> >    
> Thanks;
>
> I did just discover a reasonably good 150p spec. In what I received from 
> my client. If I can I will share it. I am under an NDA, but the client also
> told me that they received no cooperation from atheros.

hmm, only 150 pages? That's sounds a bit thin, as a matter of
fact I know that the ath5k docs (rf+mac+eeprom) are at least
around 300-400 pages.

Well, we'll see. But just in case, we already have a small
library of hardware docs (but most from different vendors):
http://wireless.kernel.org/en/developers/Documentation/specs

and we would welcome such an addition ;-)

> >> What is available for the ar9170 itself ?
> >> How does the firmware and the linux driver communicate?
> >>    Is there an overview of the firmware - what is where ?
> >>      
> > not really, apart from the headers of the original firmware
> > and vendor drivers.
> >
> > But if you really need to implement some of your 'features'
> > (what are they, if I may ask?)
>
> I think I can tell you what I am supposed add - I need to be able 
> to provide userspace apps with precise timing information for each packet.
> Since i am working on GPL'd code and the results are going to be 
> provided to third parties whatever I do is GPL'd too.

if by precise timing you mean "exact mac time in TU/usecs when frame
was received at the radio", then you might have a _problem_.
You see, the firmware already receives fully packed frames from
the MAC processor and only _forwards_ them all [as is] in
one big DMA to the USB subsystem.
(this is done in src/wlan.c handle_rx())

So, unless the HW has a _magic_ flag to enable this capability...
you are sort of screwed :-/.

> Why gets into the NDA. 
> Right now i have an NDA with a new client and though I am 
> exercising care. But they seem fairly mellow. I am probably just being 
> overly cautious.
k, understood.

^ permalink raw reply

* Re: ar9170-fw II
From: Benoit Papillault @ 2010-05-02  7:47 UTC (permalink / raw)
  To: Christian Lamparter; +Cc: David H. Lynch Jr., linux-wireless
In-Reply-To: <201005012245.36589.chunkeey@googlemail.com>

Le 01/05/2010 22:45, Christian Lamparter a écrit :
> On Saturday 01 May 2010 20:23:26 David H. Lynch Jr. wrote:
>> I think I can tell you what I am supposed add - I need to be able
>> to provide userspace apps with precise timing information for each packet.
>> Since i am working on GPL'd code and the results are going to be
>> provided to third parties whatever I do is GPL'd too.
>
> if by precise timing you mean "exact mac time in TU/usecs when frame
> was received at the radio", then you might have a _problem_.
> You see, the firmware already receives fully packed frames from
> the MAC processor and only _forwards_ them all [as is] in
> one big DMA to the USB subsystem.
> (this is done in src/wlan.c handle_rx())
>
> So, unless the HW has a _magic_ flag to enable this capability...
> you are sort of screwed :-/.

I would love this feature as well. I have a device to test if that can 
help. I share the feeling of Christian however... but maybe your 
documentation says something about a special flag.

Regards,
Benoit

^ permalink raw reply

* Re: [PATCH] rtl8180: fix tx status reporting
From: Adrian Bassett @ 2010-05-02  9:02 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1272496482-12687-1-git-send-email-linville@tuxdriver.com>

John W. Linville <linville@...> writes:

> 
> When reporting Tx status, indicate that only one rate was used.
> Otherwise, the rate is frozen at rate index 0 (i.e. 1Mb/s).
> 
> Signed-off-by: John W. Linville <linville@...>
> ---
>  drivers/net/wireless/rtl818x/rtl8180_dev.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c
b/drivers/net/wireless/rtl818x/rtl8180_dev.c
> index d84ad05..8487327 100644
> --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
> +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
> @@ -188,6 +188,7 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev,
unsigned int prio)
>  			info->flags |= IEEE80211_TX_STAT_ACK;
> 
>  		info->status.rates[0].count = (flags & 0xFF) + 1;
> +		info->status.rates[1].idx = -1;
> 
>  		ieee80211_tx_status_irqsafe(dev, skb);
>  		if (ring->entries - skb_queue_len(&ring->queue) == 2)

John,

I can confirm that this patch fixes the regression reported in the thread at
http://marc.info/?l=linux-wireless&m=123720659723688&w=2 so that the rtl8180
wireless driver and the minstrel rate controller now play together OK.  I would
endorse the suggestion that this patch is backported to stable.  Any chance of
late inclusion in 2.6.34?

Stats for info:

2.6.34-rc6-wl-00-47739-g27957c6

Rate control from /sys/kernel/debug/ieee80211/phy0/rc/name: minstrel

Stats from /sys/kernel/debug/ieee80211/phy0/stations/xx:xx:xx:xx:xx:xx/rc_stats

rate throughput  ewma prob   this prob  this succ/attempt   success    attempts
  P  1      0.9       98.1      100.0          0(  0)        137         142
     2      1.8       95.7      100.0          0(  0)         11          11
     5.5    4.8       95.7      100.0          0(  0)         11          11
    11      9.1       95.7      100.0          0(  0)         11          11
     6      5.4       95.9      100.0          0(  0)         18          20
     9      8.0       95.2      100.0          0(  0)         14          16
    12     10.5       95.3      100.0          0(  0)         13          14
    18     15.5       95.2      100.0          0(  0)         21          28
    24     20.3       95.4      100.0          0(  0)         65         110
 t  36     24.8       81.5      100.0          0(  0)        443         600
T   48     34.7       89.0      100.0          1(  1)       5348        6735
    54     17.8       41.1       25.0          0(  0)      16939       20381

Total packet count::    ideal 2794      lookaround 147


Thanks,

Adrian Bassett



^ permalink raw reply

* Re: ar9170-fw II
From: David H. Lynch Jr. @ 2010-05-02 11:14 UTC (permalink / raw)
  To: Benoit Papillault; +Cc: Christian Lamparter, linux-wireless
In-Reply-To: <4BDD2E05.40203@free.fr>

On 05/02/2010 03:47 AM, Benoit Papillault wrote:
> Le 01/05/2010 22:45, Christian Lamparter a écrit :
>> On Saturday 01 May 2010 20:23:26 David H. Lynch Jr. wrote:
>>> I think I can tell you what I am supposed add - I need to be able
>>> to provide userspace apps with precise timing information for each 
>>> packet.
>>> Since i am working on GPL'd code and the results are going to be
>>> provided to third parties whatever I do is GPL'd too.
>>
>> if by precise timing you mean "exact mac time in TU/usecs when frame
>> was received at the radio", then you might have a _problem_.
>> You see, the firmware already receives fully packed frames from
>> the MAC processor and only _forwards_ them all [as is] in
>> one big DMA to the USB subsystem.
>> (this is done in src/wlan.c handle_rx())
>>
>> So, unless the HW has a _magic_ flag to enable this capability...
>> you are sort of screwed :-/.
>
> I would love this feature as well. I have a device to test if that can 
> help. I share the feeling of Christian however... but maybe your 
> documentation says something about a special flag.
    I am interested in round trip time as measured from some fixed point 
in the sending process to some fixed point in the packet acknowledgement.
    The more accurate the better. Preferably measured by events at the 
radio rather than on the linux side. I am interested in tx packets 
rather than rx packets.
     If necessary I can measure the times myself as delta's from one 
event to another withing the SH2.

     I have not digested the docs I have thoroughly yet but a cursory 
review suggests a less than trivial project.
     I have not yet found a good high resolution clock inside the ar9170 
there are alot of clocks but they all seem to be 16bit. Probably that 
will make things harder.

     I was expecting to have to make changes to the ar9170 firmware. I 
was expecting to have to devise some means of passing that information 
to the Linux driver and to the userspace application.  I would be happy 
to do that in some fashion that conformed to an existing or future 
standard, but I was not anticipating a broad desire for what I am 
doing.  Variable latencies are highly undesirable in this application, 
but the userspace application will be aggregating large amounts of 
information, if latencies in what is measured are constrained and the 
unit of time measurement is small enough everything will work.
     If it comes to that we switch to different hardware, but my project 
is bringing a concept that was demonstrated with an expensive SDR to an 
ar9170.

      I am still coming up to speed on some aspects of Wireless - I am 
not a complete noob, I have done ethernet drivers, and other very low 
level work. I have also worked with non-802.11 wireless, and network 
communications.  But three days ago I had only cursory understanding of 
how 802.11 works.

     I already greatly appreciate your assistance.



>
> Regards,
> Benoit
> -- 
> To unsubscribe from this list: send the line "unsubscribe 
> linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


-- 
Dave Lynch 					  	    DLA Systems
Software Development:  				         Embedded Linux
717.587.7774 	       dhlii@dlasys.net 	  http://www.dlasys.net
Over 25 years' experience in platforms, languages, and technologies too numerous to list.

"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein


^ permalink raw reply

* Re: ar9170-fw II
From: Christian Lamparter @ 2010-05-02 12:52 UTC (permalink / raw)
  To: David H. Lynch Jr.; +Cc: Benoit Papillault, linux-wireless
In-Reply-To: <4BDD5EB3.7020802@dlasys.net>

On Sunday 02 May 2010 13:14:59 David H. Lynch Jr. wrote:
> On 05/02/2010 03:47 AM, Benoit Papillault wrote:
> > Le 01/05/2010 22:45, Christian Lamparter a écrit :
> >> On Saturday 01 May 2010 20:23:26 David H. Lynch Jr. wrote:
> >>> I think I can tell you what I am supposed add - I need to be able
> >>> to provide userspace apps with precise timing information for each 
> >>> packet.
> >>> Since i am working on GPL'd code and the results are going to be
> >>> provided to third parties whatever I do is GPL'd too.
> >>
> >> if by precise timing you mean "exact mac time in TU/usecs when frame
> >> was received at the radio", then you might have a _problem_.
> >> You see, the firmware already receives fully packed frames from
> >> the MAC processor and only _forwards_ them all [as is] in
> >> one big DMA to the USB subsystem.
> >> (this is done in src/wlan.c handle_rx())
> >>
> >> So, unless the HW has a _magic_ flag to enable this capability...
> >> you are sort of screwed :-/.
> >
> > I would love this feature as well. I have a device to test if that can 
> > help. I share the feeling of Christian however... but maybe your 
> > documentation says something about a special flag.
>     I am interested in round trip time as measured from some fixed point 
> in the sending process to some fixed point in the packet acknowledgement.
>     The more accurate the better. Preferably measured by events at the 
> radio rather than on the linux side.

> I am interested in tx packets rather than rx packets.
ahh, well... there goes' benoit interest ;).

>      If necessary I can measure the times myself as delta's from one 
> event to another withing the SH2.
> 
>      I have not digested the docs I have thoroughly yet but a cursory 
> review suggests a less than trivial project.
>      I have not yet found a good high resolution clock inside the ar9170 
> there are alot of clocks but they all seem to be 16bit. Probably that 
> will make things harder.
TSF timer could be used for this. (see 802.11-2007, Section 11 et seq.)
It's a 2^64 bit timer with a 1us resolution and a accuracy _better_
or equal to +/- 0.01%.

The register address are at:
 - 0x1c3514 (low, AR9170_MAC_REG_TSF_L, read only)
 - 0x1c3518 (high, AR9170_MAC_REG_TSF_H, read only)

But it comes at a small price: this timer is sometimes
update & synchronized (802.11 11.1.3.4 and 11.1.4) in
station or ad-hoc mode. The exact details are hidden
inside MAC chip, but it should be possible to disable
both by selecting the monitor mode.

>      I was expecting to have to make changes to the ar9170 firmware. I 
> was expecting to have to devise some means of passing that information 
> to the Linux driver and to the userspace application.
Well, then you have two more good reasons why to use carl9170:

 * the ar9170usb driver and ar9170 firmware don't track tx frames.
   carl9170 on the other hand does (every frame has a 8 bit "cookie").
   This feature was necessary to generate an accurate tx transmission
   feedback report for every individual frame for the driver.

 * carl9170 has the ability to store additional per-frame data.
   In fact, if you don't need to have a different retry rates
   you could realloc the 3 * 32 bit "rr" (as in retry rate)
   array in the carl9170_tx_superdesc and _carl9170_tx_superdesc
   struct (see wlan.h) for your purposes (storage for your time values).

   And if you fetched all the data, everything will be sent
   with an ordinary tx status feedback report to the application 
   (add the timer fields into carl9170_tx_status and _carl9170_tx_status
    struct - see fwcmd.h)
   
(* talked about this earlier, but you never know...

   carlu _tool_ already provides a low-level HW driver for userspace.
   This has the obvious advantage that you won't need to mess with
   the kernel driver and network stacks.

   The only work you'll have to do is: get the kernel code for
   the MAC & PHY initialization and put it into carlu.
   But the framework is already there so it's mostly copy + paste )

> I would be happy to do that in some fashion that conformed to an existing
> or future standard, but I was not anticipating a broad desire for what I am 
> doing.  Variable latencies are highly undesirable in this application, 
> but the userspace application will be aggregating large amounts of 
> information, if latencies in what is measured are constrained and the 
> unit of time measurement is small enough everything will work.
> If it comes to that we switch to different hardware, but my project 
> is bringing a concept that was demonstrated with an expensive SDR to an 
> ar9170.

It's always nice to have some "added value" for cheap and generic devices.
e.g.: Atheros AR92xx chips can be used as among other stuff as a 
      full range spectrum analyzer.

Regards,
	Chr

^ permalink raw reply

* Re: ar9170-fw II
From: David H. Lynch Jr. @ 2010-05-02 13:47 UTC (permalink / raw)
  To: Christian Lamparter, linux-wireless
In-Reply-To: <201005021452.01101.chunkeey@googlemail.com>

On 05/02/2010 08:52 AM, Christian Lamparter wrote:
>
>    
>>       If necessary I can measure the times myself as delta's from one
>> event to another withing the SH2.
>>
>>       I have not digested the docs I have thoroughly yet but a cursory
>> review suggests a less than trivial project.
>>       I have not yet found a good high resolution clock inside the ar9170
>> there are alot of clocks but they all seem to be 16bit. Probably that
>> will make things harder.
>>      
> TSF timer could be used for this. (see 802.11-2007, Section 11 et seq.)
> It's a 2^64 bit timer with a 1us resolution and a accuracy _better_
> or equal to +/- 0.01%.
>
> The register address are at:
>   - 0x1c3514 (low, AR9170_MAC_REG_TSF_L, read only)
>   - 0x1c3518 (high, AR9170_MAC_REG_TSF_H, read only)
>
> But it comes at a small price: this timer is sometimes
> update&  synchronized (802.11 11.1.3.4 and 11.1.4) in
> station or ad-hoc mode. The exact details are hidden
> inside MAC chip, but it should be possible to disable
> both by selecting the monitor mode.
>    

     I will have to look into that it might work.
     I beleive this project is in ad-hoc mode,
     but if the timer is not being altered between the transmission of a 
packet and the receipt of its ACK I am fine,
     the worst case would be that it is and delta T becomes artificially 
smaller.  One characteristic of my problem is that
     almost all the error is positive delta T overly large.
>    
>>       I was expecting to have to make changes to the ar9170 firmware. I
>> was expecting to have to devise some means of passing that information
>> to the Linux driver and to the userspace application.
>>      
> Well, then you have two more good reasons why to use carl9170:
>
>   * the ar9170usb driver and ar9170 firmware don't track tx frames.
>     carl9170 on the other hand does (every frame has a 8 bit "cookie").
>     This feature was necessary to generate an accurate tx transmission
>     feedback report for every individual frame for the driver.
>    
    That would be necescary in my application and I have started to work 
with the carl9170 driver.
     I built the toolchain compiler the firmware and I am building a 
linux kernel right now.
>   * carl9170 has the ability to store additional per-frame data.
>     In fact, if you don't need to have a different retry rates
>     you could realloc the 3 * 32 bit "rr" (as in retry rate)
>     array in the carl9170_tx_superdesc and _carl9170_tx_superdesc
>     struct (see wlan.h) for your purposes (storage for your time values).
>
>     And if you fetched all the data, everything will be sent
>     with an ordinary tx status feedback report to the application
>     (add the timer fields into carl9170_tx_status and _carl9170_tx_status
>      struct - see fwcmd.h)
>    
     I need a delta T between some fixed point during the send and some 
fixed point during the ACK.
     And the MAC address of the device I was sending to. The latter 
already is obviously already known, I just have to tie to it.
>
> (* talked about this earlier, but you never know...
>
>     carlu _tool_ already provides a low-level HW driver for userspace.
>     This has the obvious advantage that you won't need to mess with
>     the kernel driver and network stacks.
>
>     The only work you'll have to do is: get the kernel code for
>     the MAC&  PHY initialization and put it into carlu.
>     But the framework is already there so it's mostly copy + paste )
>    
     I beleive you are using DEBUGFS and that was already part of my spec.
     Regardless, I am comfortable on the Linux driver side.
     The closer I get to the Linux side the more comfortable I am.

     Further though the actual timing of each send's delta T needs to be 
as accurate and fine grained as possible,
     everything else in this project is non-critical.  Within reason it 
is unimportant how long it takes to propigate data from the AR9170 
through to userspace,
     Clean and simple will take precedence over any other technical demands.
>> I would be happy to do that in some fashion that conformed to an existing
>> or future standard, but I was not anticipating a broad desire for what I am
>> doing.  Variable latencies are highly undesirable in this application,
>> but the userspace application will be aggregating large amounts of
>> information, if latencies in what is measured are constrained and the
>> unit of time measurement is small enough everything will work.
>> If it comes to that we switch to different hardware, but my project
>> is bringing a concept that was demonstrated with an expensive SDR to an
>> ar9170.
>>      
> It's always nice to have some "added value" for cheap and generic devices.
> e.g.: Atheros AR92xx chips can be used as among other stuff as a
>        full range spectrum analyzer.
>    
     And my ability to get consulting work is strongly effected by the 
extent I can contribute to Linux.
     References, and lists of skills and qualifications on my web site 
are dwarfed by
     Dave Lynch, DLA Systems <dhlii@dlasys.net> appearing inside the 
kernel tree.

     I love this work. I love working for myself, I want to continue to 
do so.
     I would contribute as I can regardless, but self interest helps.


> Regards,
> 	Chr
>    


-- 
Dave Lynch 					  	    DLA Systems
Software Development:  				         Embedded Linux
717.587.7774 	       dhlii@dlasys.net 	  http://www.dlasys.net
Over 25 years' experience in platforms, languages, and technologies too numerous to list.

"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein


^ permalink raw reply

* [RFC] ibss: Added channel type in order to create HT IBSS
From: Benoit Papillault @ 2010-05-02 14:12 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Benoit Papillault

When joining an IBSS, the parameters can be used to create the IBSS. As
such, we need to know if the user wants to create an HT IBSS or not.
This is accomplish by passing the channel type (ie ht20, ht40- or
ht40+). Default is to create a non HT IBSS.

Signed-off-by: Benoit Papillault <benoit.papillault@free.fr>
---
It is needed for upcoming patches regarding HT IBSS
 ibss.c |   27 ++++++++++++++++++++++++++-
 1 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/ibss.c b/ibss.c
index 4715ac8..4003a38 100644
--- a/ibss.c
+++ b/ibss.c
@@ -18,6 +18,15 @@ static int join_ibss(struct nl80211_state *state,
 {
 	char *end;
 	unsigned char abssid[6];
+	int i;
+	static const struct {
+		const char *name;
+		unsigned int val;
+	} htmap[] = {
+		{ .name = "HT20", .val = NL80211_CHAN_HT20, },
+		{ .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
+		{ .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
+	};
 
 	if (argc < 2)
 		return 1;
@@ -52,6 +61,22 @@ static int join_ibss(struct nl80211_state *state,
 	if (!argc)
 		return 0;
 
+	if (argc) {
+		for (i = 0; i < ARRAY_SIZE(htmap); i++) {
+			if (strcasecmp(htmap[i].name, argv[1]) == 0) {
+				NLA_PUT_U32(msg,
+					    NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+					    htmap[i].val);
+				argv++;
+				argc--;
+				break;
+			}
+		}
+	}
+
+	if (!argc)
+		return 0;
+
 	if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0)
 		return 1;
 
@@ -73,7 +98,7 @@ static int leave_ibss(struct nl80211_state *state,
 COMMAND(ibss, leave, NULL,
 	NL80211_CMD_LEAVE_IBSS, 0, CIB_NETDEV, leave_ibss,
 	"Leave the current IBSS cell.");
-COMMAND(ibss, join, "<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>] [key d:0:abcde]",
+COMMAND(ibss, join, "<SSID> <freq in MHz> [HT20|HT40+|HT40-] [fixed-freq] [<fixed bssid>] [key d:0:abcde]",
 	NL80211_CMD_JOIN_IBSS, 0, CIB_NETDEV, join_ibss,
 	"Join the IBSS cell with the given SSID, if it doesn't exist create\n"
 	"it on the given frequency. When fixed frequency is requested, don't\n"
-- 
1.7.0.4


^ permalink raw reply related

* Re: [RFC] ibss: Added channel type in order to create HT IBSS
From: Johannes Berg @ 2010-05-02 16:32 UTC (permalink / raw)
  To: Benoit Papillault; +Cc: linux-wireless
In-Reply-To: <1272809528-11000-1-git-send-email-benoit.papillault@free.fr>

On Sun, 2010-05-02 at 16:12 +0200, Benoit Papillault wrote:
> When joining an IBSS, the parameters can be used to create the IBSS. As
> such, we need to know if the user wants to create an HT IBSS or not.
> This is accomplish by passing the channel type (ie ht20, ht40- or
> ht40+). Default is to create a non HT IBSS.
> 
> Signed-off-by: Benoit Papillault <benoit.papillault@free.fr>
> ---
> It is needed for upcoming patches regarding HT IBSS
>  ibss.c |   27 ++++++++++++++++++++++++++-
>  1 files changed, 26 insertions(+), 1 deletions(-)
> 
> diff --git a/ibss.c b/ibss.c
> index 4715ac8..4003a38 100644
> --- a/ibss.c
> +++ b/ibss.c
> @@ -18,6 +18,15 @@ static int join_ibss(struct nl80211_state *state,
>  {
>  	char *end;
>  	unsigned char abssid[6];
> +	int i;
> +	static const struct {
> +		const char *name;
> +		unsigned int val;
> +	} htmap[] = {
> +		{ .name = "HT20", .val = NL80211_CHAN_HT20, },
> +		{ .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
> +		{ .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
> +	};

There's code to do something like this already when setting the channel,
please factor it out and use it in both places.

johannes


^ permalink raw reply

* Re: [RFC] ibss: Added channel type in order to create HT IBSS
From: Benoit Papillault @ 2010-05-02 20:05 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1272817974.31265.0.camel@jlt3.sipsolutions.net>

Le 02/05/2010 18:32, Johannes Berg a écrit :
> On Sun, 2010-05-02 at 16:12 +0200, Benoit Papillault wrote:
>> When joining an IBSS, the parameters can be used to create the IBSS. As
>> such, we need to know if the user wants to create an HT IBSS or not.
>> This is accomplish by passing the channel type (ie ht20, ht40- or
>> ht40+). Default is to create a non HT IBSS.
>>
>> Signed-off-by: Benoit Papillault<benoit.papillault@free.fr>
>> ---
>> It is needed for upcoming patches regarding HT IBSS
>>   ibss.c |   27 ++++++++++++++++++++++++++-
>>   1 files changed, 26 insertions(+), 1 deletions(-)
>>
>> diff --git a/ibss.c b/ibss.c
>> index 4715ac8..4003a38 100644
>> --- a/ibss.c
>> +++ b/ibss.c
>> @@ -18,6 +18,15 @@ static int join_ibss(struct nl80211_state *state,
>>   {
>>   	char *end;
>>   	unsigned char abssid[6];
>> +	int i;
>> +	static const struct {
>> +		const char *name;
>> +		unsigned int val;
>> +	} htmap[] = {
>> +		{ .name = "HT20", .val = NL80211_CHAN_HT20, },
>> +		{ .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
>> +		{ .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
>> +	};
>
> There's code to do something like this already when setting the channel,
> please factor it out and use it in both places.
>
> johannes
>

Agreed. I did a copy/paste in the hurry, my bad.
I am going to post an update ASAP.

Regards,
Benoit

^ permalink raw reply

* [RFC v2] ibss: Added channel type in order to create HT IBSS
From: Benoit Papillault @ 2010-05-02 20:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Benoit Papillault

When joining an IBSS, the command line parameters could be used to
create the IBSS. As such, we need to know if the user wants to create an
HT IBSS or not. This is accomplish by passing the channel type (ie ht20,
ht40- or ht40+). Default is to create a non HT IBSS.

v2: Fixed parsing order of optionnal parameters. Parse argv[0] instead
  of argv[1].

v3: Added parse_channel_type to factor some common parsing code.

Signed-off-by: Benoit Papillault <benoit.papillault@free.fr>
---
 ibss.c |    9 ++++++++-
 iw.h   |    1 +
 phy.c  |   20 ++------------------
 util.c |   27 +++++++++++++++++++++++++++
 4 files changed, 38 insertions(+), 19 deletions(-)

diff --git a/ibss.c b/ibss.c
index 4715ac8..4d22157 100644
--- a/ibss.c
+++ b/ibss.c
@@ -18,6 +18,7 @@ static int join_ibss(struct nl80211_state *state,
 {
 	char *end;
 	unsigned char abssid[6];
+	unsigned int htval;
 
 	if (argc < 2)
 		return 1;
@@ -35,6 +36,12 @@ static int join_ibss(struct nl80211_state *state,
 	argv++;
 	argc--;
 
+	if (argc && parse_channel_type(argv[0], &htval)) {
+		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
+		argv++;
+		argc--;
+	}
+
 	if (argc && strcmp(argv[0], "fixed-freq") == 0) {
 		NLA_PUT_FLAG(msg, NL80211_ATTR_FREQ_FIXED);
 		argv++;
@@ -73,7 +80,7 @@ static int leave_ibss(struct nl80211_state *state,
 COMMAND(ibss, leave, NULL,
 	NL80211_CMD_LEAVE_IBSS, 0, CIB_NETDEV, leave_ibss,
 	"Leave the current IBSS cell.");
-COMMAND(ibss, join, "<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>] [key d:0:abcde]",
+COMMAND(ibss, join, "<SSID> <freq in MHz> [HT20|HT40+|HT40-] [fixed-freq] [<fixed bssid>] [key d:0:abcde]",
 	NL80211_CMD_JOIN_IBSS, 0, CIB_NETDEV, join_ibss,
 	"Join the IBSS cell with the given SSID, if it doesn't exist create\n"
 	"it on the given frequency. When fixed frequency is requested, don't\n"
diff --git a/iw.h b/iw.h
index d1608e8..2ab4b90 100644
--- a/iw.h
+++ b/iw.h
@@ -120,6 +120,7 @@ void mac_addr_n2a(char *mac_addr, unsigned char *arg);
 unsigned char *parse_hex(char *hex, size_t *outlen);
 
 int parse_keys(struct nl_msg *msg, char **argv, int argc);
+int parse_channel_type(const char *str, unsigned int *htval);
 
 void print_ht_mcs(const __u8 *mcs);
 void print_ampdu_length(__u8 exponent);
diff --git a/phy.c b/phy.c
index 8f8d757..a33c4e1 100644
--- a/phy.c
+++ b/phy.c
@@ -32,30 +32,14 @@ static int handle_freqchan(struct nl_msg *msg, bool chan,
 			   int argc, char **argv)
 {
 	char *end;
-	static const struct {
-		const char *name;
-		unsigned int val;
-	} htmap[] = {
-		{ .name = "HT20", .val = NL80211_CHAN_HT20, },
-		{ .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
-		{ .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
-	};
 	unsigned int htval = NL80211_CHAN_NO_HT;
 	unsigned int freq;
-	int i;
 
 	if (!argc || argc > 2)
 		return 1;
 
-	if (argc == 2) {
-		for (i = 0; i < ARRAY_SIZE(htmap); i++) {
-			if (strcasecmp(htmap[i].name, argv[1]) == 0) {
-				htval = htmap[i].val;
-				break;
-			}
-		}
-		if (htval == NL80211_CHAN_NO_HT)
-			return 1;
+	if (argc == 2 && !parse_channel_type(argv[1], &htval)) {
+		return 1;
 	}
 
 	if (!*argv[0])
diff --git a/util.c b/util.c
index 42c992d..9426306 100644
--- a/util.c
+++ b/util.c
@@ -338,6 +338,33 @@ int parse_keys(struct nl_msg *msg, char **argv, int argc)
 	return 2;
 }
 
+/*
+ * Convert a string "HT20", "HT40+" or "HT40-" into nl80211
+ * value. Conversion is case insensitive. Returns 1 on success, 0 on error.
+ */
+
+int parse_channel_type(const char *str, unsigned int *htval)
+{
+	static const struct {
+		const char *name;
+		unsigned int val;
+	} htmap[] = {
+		{ .name = "HT20", .val = NL80211_CHAN_HT20, },
+		{ .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
+		{ .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(htmap); i++) {
+		if (strcasecmp(htmap[i].name, str) == 0) {
+			*htval = htmap[i].val;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 static void print_mcs_index(const __u8 *mcs)
 {
 	unsigned int mcs_bit, prev_bit = -2, prev_cont = 0;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH] mac80211: improve IBSS scanning
From: Johannes Berg @ 2010-05-03  6:49 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

When IBSS is fixed to a frequency, it can still
scan to try to find the right BSSID. This makes
sense if the BSSID isn't also fixed, but it need
not scan all channels -- just one is sufficient.
Make it do that by moving the scan setup code to
ieee80211_request_internal_scan() and include
a channel variable setting.

Note that this can be further improved to start
the IBSS right away if both frequency and BSSID
are fixed.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ibss.c        |    9 ++++++---
 net/mac80211/ieee80211_i.h |    3 ++-
 net/mac80211/main.c        |   17 +----------------
 net/mac80211/scan.c        |   28 +++++++++++++++++++++++++++-
 4 files changed, 36 insertions(+), 21 deletions(-)

--- wireless-testing.orig/net/mac80211/main.c	2010-05-02 17:36:04.000000000 +0200
+++ wireless-testing/net/mac80211/main.c	2010-05-02 17:39:00.000000000 +0200
@@ -439,7 +439,7 @@ int ieee80211_register_hw(struct ieee802
 	struct ieee80211_local *local = hw_to_local(hw);
 	int result;
 	enum ieee80211_band band;
-	int channels, i, j, max_bitrates;
+	int channels, max_bitrates;
 	bool supp_ht;
 	static const u32 cipher_suites[] = {
 		WLAN_CIPHER_SUITE_WEP40,
@@ -605,21 +605,6 @@ int ieee80211_register_hw(struct ieee802
 
 	ieee80211_led_init(local);
 
-	/* alloc internal scan request */
-	i = 0;
-	local->int_scan_req->ssids = &local->scan_ssid;
-	local->int_scan_req->n_ssids = 1;
-	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-		if (!hw->wiphy->bands[band])
-			continue;
-		for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
-			local->int_scan_req->channels[i] =
-				&hw->wiphy->bands[band]->channels[j];
-			i++;
-		}
-	}
-	local->int_scan_req->n_channels = i;
-
 	local->network_latency_notifier.notifier_call =
 		ieee80211_max_network_latency;
 	result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
--- wireless-testing.orig/net/mac80211/scan.c	2010-05-02 17:34:53.000000000 +0200
+++ wireless-testing/net/mac80211/scan.c	2010-05-02 17:41:49.000000000 +0200
@@ -729,10 +729,12 @@ int ieee80211_request_scan(struct ieee80
 }
 
 int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
-				    const u8 *ssid, u8 ssid_len)
+				    const u8 *ssid, u8 ssid_len,
+				    struct ieee80211_channel *chan)
 {
 	struct ieee80211_local *local = sdata->local;
 	int ret = -EBUSY;
+	enum nl80211_band band;
 
 	mutex_lock(&local->scan_mtx);
 
@@ -740,6 +742,30 @@ int ieee80211_request_internal_scan(stru
 	if (local->scan_req)
 		goto unlock;
 
+	/* fill internal scan request */
+	if (!chan) {
+		int i, nchan = 0;
+
+		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+			if (!local->hw.wiphy->bands[band])
+				continue;
+			for (i = 0;
+			     i < local->hw.wiphy->bands[band]->n_channels;
+			     i++) {
+				local->int_scan_req->channels[nchan] =
+				    &local->hw.wiphy->bands[band]->channels[i];
+				nchan++;
+			}
+		}
+
+		local->int_scan_req->n_channels = nchan;
+	} else {
+		local->int_scan_req->channels[0] = chan;
+		local->int_scan_req->n_channels = 1;
+	}
+
+	local->int_scan_req->ssids = &local->scan_ssid;
+	local->int_scan_req->n_ssids = 1;
 	memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
 	local->int_scan_req->ssids[0].ssid_len = ssid_len;
 
--- wireless-testing.orig/net/mac80211/ibss.c	2010-05-02 17:34:41.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c	2010-05-02 17:43:34.000000000 +0200
@@ -489,7 +489,9 @@ static void ieee80211_sta_merge_ibss(str
 	printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
 	       "IBSS networks with same SSID (merge)\n", sdata->name);
 
-	ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len);
+	ieee80211_request_internal_scan(sdata,
+			ifibss->ssid, ifibss->ssid_len,
+			ifibss->fixed_channel ? ifibss->channel : NULL);
 }
 
 static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -596,8 +598,9 @@ static void ieee80211_sta_find_ibss(stru
 		printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
 		       "join\n", sdata->name);
 
-		ieee80211_request_internal_scan(sdata, ifibss->ssid,
-						ifibss->ssid_len);
+		ieee80211_request_internal_scan(sdata,
+				ifibss->ssid, ifibss->ssid_len,
+				ifibss->fixed_channel ? ifibss->channel : NULL);
 	} else {
 		int interval = IEEE80211_SCAN_INTERVAL;
 
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2010-05-02 17:39:13.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h	2010-05-02 17:39:38.000000000 +0200
@@ -1020,7 +1020,8 @@ void ieee80211_ibss_restart(struct ieee8
 /* scan/BSS handling */
 void ieee80211_scan_work(struct work_struct *work);
 int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
-				    const u8 *ssid, u8 ssid_len);
+				    const u8 *ssid, u8 ssid_len,
+				    struct ieee80211_channel *chan);
 int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
 			   struct cfg80211_scan_request *req);
 void ieee80211_scan_cancel(struct ieee80211_local *local);



^ permalink raw reply

* [RFC/RFT] cfg80211/mac80211: better channel handling
From: Johannes Berg @ 2010-05-03  7:12 UTC (permalink / raw)
  To: linux-wireless

Currently (all tested with hwsim) you can do stupid
things like setting up an AP on a certain channel,
then adding another virtual interface and making
that associate on another channel -- this will make
the beaconing to move channel but obviously without
the necessary IEs data update.

In order to improve this situation, first make the
configuration APIs (cfg80211 and nl80211) aware of
multi-channel operation -- we'll eventually need
that in the future anyway. There's one userland API
change and one API addition. The API change is that
now SET_WIPHY must be called with virtual interface
index rather than only wiphy index in order to take
effect for that interface -- luckily all current
users (hostapd) do that. For monitor interfaces, the
old setting is preserved, but monitors are always
slaved to other devices anyway so no guarantees.

The second userland API change is the introduction
of a per virtual interface SET_CHANNEL command, that
hostapd should use going forward to make it easier
to understand what's going on (it can automatically
detect a kernel with this command).

Other than mac80211, no existing cfg80211 drivers
are affected by this change because they only allow
a single virtual interface.

mac80211, however, now needs to be aware that the
channel settings are per interface now, and needs
to disallow (for now) real multi-channel operation,
which is another important part of this patch.

One of the immediate benefits is that you can now
start hostapd to operate on a hardware that already
has a connection on another virtual interface, as
long as you specify the same channel.

Note that two things are left unhandled (this is an
improvement -- not a complete fix):
 * different HT/no-HT modes

   currently you could start an HT AP and then
   connect to a non-HT network on the same channel
   which would configure the hardware for no HT;
   that can be fixed fairly easily

 * CSA

   An AP we're connected to on a virtual interface
   might indicate switching channels, and in that
   case we would follow it, regardless of how many
   other interfaces are operating; this requires
   more effort to fix but is pretty rare after all

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
PLEASE test, especially all the monitoring people. I've done various
tests and it feels like a great improvement, and certainly shouldn't
really change anything in the typical 'single-interface' mode.

I'm going to subject this to some more testing, and post it for
inclusion in the next couple of days if all goes well, so there's your
chance :)

 drivers/net/wireless/libertas/cfg.c |    1 
 drivers/net/wireless/orinoco/cfg.c  |    1 
 drivers/net/wireless/rndis_wlan.c   |    4 
 include/linux/nl80211.h             |   13 ++
 include/net/cfg80211.h              |   11 +-
 net/mac80211/Makefile               |    3 
 net/mac80211/cfg.c                  |   41 +++++++++
 net/mac80211/chan.c                 |   57 ++++++++++++
 net/mac80211/ieee80211_i.h          |   11 ++
 net/wireless/chan.c                 |   56 +++---------
 net/wireless/core.h                 |   12 --
 net/wireless/ibss.c                 |    5 -
 net/wireless/nl80211.c              |  163 +++++++++++++++++++++++++++---------
 net/wireless/sme.c                  |    5 -
 net/wireless/wext-compat.c          |   15 ++-
 net/wireless/wext-sme.c             |    2 
 16 files changed, 291 insertions(+), 109 deletions(-)

--- wireless-testing.orig/include/linux/nl80211.h	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/include/linux/nl80211.h	2010-05-02 17:47:51.000000000 +0200
@@ -52,6 +52,8 @@
  *	%NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
  *	%NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
  *	and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
+ *	However, for setting the channel, see %NL80211_CMD_SET_CHANNEL
+ *	instead, the support here is for backward compatibility only.
  * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
  *	or rename notification. Has attributes %NL80211_ATTR_WIPHY and
  *	%NL80211_ATTR_WIPHY_NAME.
@@ -329,6 +331,15 @@
  * @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This
  *	command is used as an event to indicate the that a trigger level was
  *	reached.
+ * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
+ *	and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed
+ *	by %NL80211_ATTR_IFINDEX) shall operate on.
+ *	In case multiple channels are supported by the device, the mechanism
+ *	with which it switches channels is implementation-defined.
+ *	When a monitor interface is given, it can only switch channel while
+ *	no other interfaces are operating to avoid disturbing the operation
+ *	of any other interfaces, and other interfaces will again take
+ *	precedence when they are used.
  *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
@@ -428,6 +439,8 @@ enum nl80211_commands {
 	NL80211_CMD_SET_CQM,
 	NL80211_CMD_NOTIFY_CQM,
 
+	NL80211_CMD_SET_CHANNEL,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
--- wireless-testing.orig/net/wireless/nl80211.c	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c	2010-05-02 17:47:51.000000000 +0200
@@ -689,10 +689,90 @@ static int parse_txq_params(struct nlatt
 	return 0;
 }
 
+static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
+{
+	/*
+	 * You can only set the channel explicitly for AP, mesh
+	 * and WDS type interfaces; all others have their channel
+	 * managed via their respective "establish a connection"
+	 * command (connect, join, ...)
+	 *
+	 * Monitors are special as they are normally slaved to
+	 * whatever else is going on, so they behave as though
+	 * you tried setting the wiphy channel itself.
+	 */
+	return !wdev ||
+		wdev->iftype == NL80211_IFTYPE_AP ||
+		wdev->iftype == NL80211_IFTYPE_WDS ||
+		wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
+		wdev->iftype == NL80211_IFTYPE_MONITOR;
+}
+
+static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
+				 struct wireless_dev *wdev,
+				 struct genl_info *info)
+{
+	enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
+	u32 freq;
+	int result;
+
+	if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
+		return -EINVAL;
+
+	if (!nl80211_can_set_dev_channel(wdev))
+		return -EOPNOTSUPP;
+
+	if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
+		channel_type = nla_get_u32(info->attrs[
+				   NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+		if (channel_type != NL80211_CHAN_NO_HT &&
+		    channel_type != NL80211_CHAN_HT20 &&
+		    channel_type != NL80211_CHAN_HT40PLUS &&
+		    channel_type != NL80211_CHAN_HT40MINUS)
+			return -EINVAL;
+	}
+
+	freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
+
+	mutex_lock(&rdev->devlist_mtx);
+	if (wdev) {
+		wdev_lock(wdev);
+		result = cfg80211_set_freq(rdev, wdev, freq, channel_type);
+		wdev_unlock(wdev);
+	} else {
+		result = cfg80211_set_freq(rdev, NULL, freq, channel_type);
+	}
+	mutex_unlock(&rdev->devlist_mtx);
+
+	return result;
+}
+
+static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev;
+	struct net_device *netdev;
+	int result;
+
+	rtnl_lock();
+
+	result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev);
+	if (result)
+		goto unlock;
+
+	result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
+
+ unlock:
+	rtnl_unlock();
+
+	return result;
+}
+
 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev;
-	int result = 0, rem_txq_params = 0;
+	struct net_device *netdev;
+	struct wireless_dev *wdev;
+	int result, rem_txq_params = 0;
 	struct nlattr *nl_txq_params;
 	u32 changed;
 	u8 retry_short = 0, retry_long = 0;
@@ -701,16 +781,41 @@ static int nl80211_set_wiphy(struct sk_b
 
 	rtnl_lock();
 
+	/*
+	 * Try to find the wiphy and netdev. Normally this
+	 * function shouldn't need the netdev, but this is
+	 * done for backward compatibility -- previously
+	 * setting the channel was done per wiphy, but now
+	 * it is per netdev. Previous userland like hostapd
+	 * also passed a netdev to set_wiphy, so that it is
+	 * possible to let that go to the right netdev!
+	 */
+	result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev);
+
 	mutex_lock(&cfg80211_mutex);
+	if (result) {
+		rdev = __cfg80211_rdev_from_info(info);
+		if (IS_ERR(rdev)) {
+			mutex_unlock(&cfg80211_mutex);
+			result = PTR_ERR(rdev);
+			goto unlock;
+		}
+		wdev = NULL;
+		netdev = NULL;
+		result = 0;
+
+		mutex_lock(&rdev->mtx);
+	} else if (netif_running(netdev) &&
+		   nl80211_can_set_dev_channel(netdev->ieee80211_ptr))
+		wdev = netdev->ieee80211_ptr;
+	else
+		wdev = NULL;
 
-	rdev = __cfg80211_rdev_from_info(info);
-	if (IS_ERR(rdev)) {
-		mutex_unlock(&cfg80211_mutex);
-		result = PTR_ERR(rdev);
-		goto unlock;
-	}
+	/*
+	 * end workaround code, by now the rdev is available
+	 * and locked, and wdev may or may not be NULL
+	 */
 
-	mutex_lock(&rdev->mtx);
 
 	if (info->attrs[NL80211_ATTR_WIPHY_NAME])
 		result = cfg80211_dev_rename(
@@ -749,26 +854,7 @@ static int nl80211_set_wiphy(struct sk_b
 	}
 
 	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
-		enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
-		u32 freq;
-
-		result = -EINVAL;
-
-		if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
-			channel_type = nla_get_u32(info->attrs[
-					   NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
-			if (channel_type != NL80211_CHAN_NO_HT &&
-			    channel_type != NL80211_CHAN_HT20 &&
-			    channel_type != NL80211_CHAN_HT40PLUS &&
-			    channel_type != NL80211_CHAN_HT40MINUS)
-				goto bad_res;
-		}
-
-		freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
-
-		mutex_lock(&rdev->devlist_mtx);
-		result = rdev_set_freq(rdev, NULL, freq, channel_type);
-		mutex_unlock(&rdev->devlist_mtx);
+		result = __nl80211_set_channel(rdev, wdev, info);
 		if (result)
 			goto bad_res;
 	}
@@ -865,6 +951,8 @@ static int nl80211_set_wiphy(struct sk_b
 
  bad_res:
 	mutex_unlock(&rdev->mtx);
+	if (netdev)
+		dev_put(netdev);
  unlock:
 	rtnl_unlock();
 	return result;
@@ -3562,9 +3650,8 @@ static int nl80211_associate(struct sk_b
 {
 	struct cfg80211_registered_device *rdev;
 	struct net_device *dev;
-	struct wireless_dev *wdev;
 	struct cfg80211_crypto_settings crypto;
-	struct ieee80211_channel *chan, *fixedchan;
+	struct ieee80211_channel *chan;
 	const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
 	int err, ssid_len, ie_len = 0;
 	bool use_mfp = false;
@@ -3607,16 +3694,6 @@ static int nl80211_associate(struct sk_b
 		goto out;
 	}
 
-	mutex_lock(&rdev->devlist_mtx);
-	wdev = dev->ieee80211_ptr;
-	fixedchan = rdev_fixed_channel(rdev, wdev);
-	if (fixedchan && chan != fixedchan) {
-		err = -EBUSY;
-		mutex_unlock(&rdev->devlist_mtx);
-		goto out;
-	}
-	mutex_unlock(&rdev->devlist_mtx);
-
 	ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
 	ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
 
@@ -5186,6 +5263,12 @@ static struct genl_ops nl80211_ops[] = {
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 	},
+	{
+		.cmd = NL80211_CMD_SET_CHANNEL,
+		.doit = nl80211_set_channel,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
 };
 
 static struct genl_multicast_group nl80211_mlme_mcgrp = {
--- wireless-testing.orig/include/net/cfg80211.h	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h	2010-05-02 17:47:51.000000000 +0200
@@ -966,7 +966,11 @@ struct cfg80211_pmksa {
  *
  * @set_txq_params: Set TX queue parameters
  *
- * @set_channel: Set channel
+ * @set_channel: Set channel for a given wireless interface. Some devices
+ *	may support multi-channel operation (by channel hopping) so cfg80211
+ *	doesn't verify much. Note, however, that the passed netdev may be
+ *	%NULL as well if the user requested changing the channel for the
+ *	device itself, or for a monitor interface.
  *
  * @scan: Request to do a scan. If returning zero, the scan request is given
  *	the driver, and will be valid until passed to cfg80211_scan_done().
@@ -1095,7 +1099,7 @@ struct cfg80211_ops {
 	int	(*set_txq_params)(struct wiphy *wiphy,
 				  struct ieee80211_txq_params *params);
 
-	int	(*set_channel)(struct wiphy *wiphy,
+	int	(*set_channel)(struct wiphy *wiphy, struct net_device *dev,
 			       struct ieee80211_channel *chan,
 			       enum nl80211_channel_type channel_type);
 
@@ -1461,6 +1465,8 @@ struct cfg80211_cached_keys;
  * @list: (private) Used to collect the interfaces
  * @netdev: (private) Used to reference back to the netdev
  * @current_bss: (private) Used by the internal configuration code
+ * @channel: (private) Used by the internal configuration code to track
+ *	user-set AP, monitor and WDS channels for wireless extensions
  * @bssid: (private) Used by the internal configuration code
  * @ssid: (private) Used by the internal configuration code
  * @ssid_len: (private) Used by the internal configuration code
@@ -1507,6 +1513,7 @@ struct wireless_dev {
 	struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES];
 	struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
 	struct cfg80211_internal_bss *current_bss; /* associated / joined */
+	struct ieee80211_channel *channel;
 
 	bool ps;
 	int ps_timeout;
--- wireless-testing.orig/net/wireless/chan.c	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/chan.c	2010-05-02 17:47:51.000000000 +0200
@@ -10,38 +10,6 @@
 #include "core.h"
 
 struct ieee80211_channel *
-rdev_fixed_channel(struct cfg80211_registered_device *rdev,
-		   struct wireless_dev *for_wdev)
-{
-	struct wireless_dev *wdev;
-	struct ieee80211_channel *result = NULL;
-
-	WARN_ON(!mutex_is_locked(&rdev->devlist_mtx));
-
-	list_for_each_entry(wdev, &rdev->netdev_list, list) {
-		if (wdev == for_wdev)
-			continue;
-
-		/*
-		 * Lock manually to tell lockdep about allowed
-		 * nesting here if for_wdev->mtx is held already.
-		 * This is ok as it's all under the rdev devlist
-		 * mutex and as such can only be done once at any
-		 * given time.
-		 */
-		mutex_lock_nested(&wdev->mtx, SINGLE_DEPTH_NESTING);
-		if (wdev->current_bss)
-			result = wdev->current_bss->pub.channel;
-		wdev_unlock(wdev);
-
-		if (result)
-			break;
-	}
-
-	return result;
-}
-
-struct ieee80211_channel *
 rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
 		  int freq, enum nl80211_channel_type channel_type)
 {
@@ -75,15 +43,22 @@ rdev_freq_to_chan(struct cfg80211_regist
 	return chan;
 }
 
-int rdev_set_freq(struct cfg80211_registered_device *rdev,
-		  struct wireless_dev *for_wdev,
-		  int freq, enum nl80211_channel_type channel_type)
+int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+		      struct wireless_dev *wdev, int freq,
+		      enum nl80211_channel_type channel_type)
 {
 	struct ieee80211_channel *chan;
 	int result;
 
-	if (rdev_fixed_channel(rdev, for_wdev))
-		return -EBUSY;
+	if (wdev->iftype == NL80211_IFTYPE_MONITOR)
+		wdev = NULL;
+
+	if (wdev) {
+		ASSERT_WDEV_LOCK(wdev);
+
+		if (!netif_running(wdev->netdev))
+			return -ENETDOWN;
+	}
 
 	if (!rdev->ops->set_channel)
 		return -EOPNOTSUPP;
@@ -92,11 +67,14 @@ int rdev_set_freq(struct cfg80211_regist
 	if (!chan)
 		return -EINVAL;
 
-	result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
+	result = rdev->ops->set_channel(&rdev->wiphy,
+					wdev ? wdev->netdev : NULL,
+					chan, channel_type);
 	if (result)
 		return result;
 
-	rdev->channel = chan;
+	if (wdev)
+		wdev->channel = chan;
 
 	return 0;
 }
--- wireless-testing.orig/net/wireless/core.h	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/core.h	2010-05-02 17:47:51.000000000 +0200
@@ -70,9 +70,6 @@ struct cfg80211_registered_device {
 	struct work_struct conn_work;
 	struct work_struct event_work;
 
-	/* current channel */
-	struct ieee80211_channel *channel;
-
 	/* must be last because of the way we do wiphy_priv(),
 	 * and it should at least be aligned to NETDEV_ALIGN */
 	struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
@@ -388,14 +385,11 @@ int cfg80211_change_iface(struct cfg8021
 void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
 
 struct ieee80211_channel *
-rdev_fixed_channel(struct cfg80211_registered_device *rdev,
-		   struct wireless_dev *for_wdev);
-struct ieee80211_channel *
 rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
 		  int freq, enum nl80211_channel_type channel_type);
-int rdev_set_freq(struct cfg80211_registered_device *rdev,
-		  struct wireless_dev *for_wdev,
-		  int freq, enum nl80211_channel_type channel_type);
+int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+		      struct wireless_dev *wdev, int freq,
+		      enum nl80211_channel_type channel_type);
 
 u16 cfg80211_calculate_bitrate(struct rate_info *rate);
 
--- wireless-testing.orig/net/wireless/wext-compat.c	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c	2010-05-02 17:47:51.000000000 +0200
@@ -782,16 +782,22 @@ int cfg80211_wext_siwfreq(struct net_dev
 		return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
 	case NL80211_IFTYPE_ADHOC:
 		return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
-	default:
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_WDS:
+	case NL80211_IFTYPE_MESH_POINT:
 		freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
 		if (freq < 0)
 			return freq;
 		if (freq == 0)
 			return -EINVAL;
+		wdev_lock(wdev);
 		mutex_lock(&rdev->devlist_mtx);
-		err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
+		err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
 		mutex_unlock(&rdev->devlist_mtx);
+		wdev_unlock(wdev);
 		return err;
+	default:
+		return -EOPNOTSUPP;
 	}
 }
 EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
@@ -801,7 +807,6 @@ int cfg80211_wext_giwfreq(struct net_dev
 			  struct iw_freq *freq, char *extra)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_STATION:
@@ -809,9 +814,9 @@ int cfg80211_wext_giwfreq(struct net_dev
 	case NL80211_IFTYPE_ADHOC:
 		return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
 	default:
-		if (!rdev->channel)
+		if (!wdev->channel)
 			return -EINVAL;
-		freq->m = rdev->channel->center_freq;
+		freq->m = wdev->channel->center_freq;
 		freq->e = 6;
 		return 0;
 	}
--- wireless-testing.orig/net/wireless/wext-sme.c	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/wext-sme.c	2010-05-02 17:47:51.000000000 +0200
@@ -108,7 +108,7 @@ int cfg80211_mgd_wext_siwfreq(struct net
 
 	/* SSID is not set, we just want to switch channel */
 	if (chan && !wdev->wext.connect.ssid_len) {
-		err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
+		err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
 		goto out;
 	}
 
--- wireless-testing.orig/net/wireless/ibss.c	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/ibss.c	2010-05-02 17:47:51.000000000 +0200
@@ -81,15 +81,10 @@ int __cfg80211_join_ibss(struct cfg80211
 			 struct cfg80211_cached_keys *connkeys)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct ieee80211_channel *chan;
 	int err;
 
 	ASSERT_WDEV_LOCK(wdev);
 
-	chan = rdev_fixed_channel(rdev, wdev);
-	if (chan && chan != params->channel)
-		return -EBUSY;
-
 	if (wdev->ssid_len)
 		return -EALREADY;
 
--- wireless-testing.orig/net/wireless/sme.c	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/sme.c	2010-05-02 17:47:51.000000000 +0200
@@ -741,7 +741,6 @@ int __cfg80211_connect(struct cfg80211_r
 		       const u8 *prev_bssid)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct ieee80211_channel *chan;
 	struct cfg80211_bss *bss = NULL;
 	int err;
 
@@ -750,10 +749,6 @@ int __cfg80211_connect(struct cfg80211_r
 	if (wdev->sme_state != CFG80211_SME_IDLE)
 		return -EALREADY;
 
-	chan = rdev_fixed_channel(rdev, wdev);
-	if (chan && chan != connect->channel)
-		return -EBUSY;
-
 	if (WARN_ON(wdev->connect_keys)) {
 		kfree(wdev->connect_keys);
 		wdev->connect_keys = NULL;
--- wireless-testing.orig/drivers/net/wireless/libertas/cfg.c	2010-05-02 17:47:48.000000000 +0200
+++ wireless-testing/drivers/net/wireless/libertas/cfg.c	2010-05-02 17:47:51.000000000 +0200
@@ -79,6 +79,7 @@ static const u32 cipher_suites[] = {
 
 
 static int lbs_cfg_set_channel(struct wiphy *wiphy,
+	struct net_device *netdev,
 	struct ieee80211_channel *chan,
 	enum nl80211_channel_type channel_type)
 {
--- wireless-testing.orig/drivers/net/wireless/orinoco/cfg.c	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/drivers/net/wireless/orinoco/cfg.c	2010-05-02 17:47:51.000000000 +0200
@@ -159,6 +159,7 @@ static int orinoco_scan(struct wiphy *wi
 }
 
 static int orinoco_set_channel(struct wiphy *wiphy,
+			struct net_device *netdev,
 			struct ieee80211_channel *chan,
 			enum nl80211_channel_type channel_type)
 {
--- wireless-testing.orig/drivers/net/wireless/rndis_wlan.c	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/drivers/net/wireless/rndis_wlan.c	2010-05-02 17:47:51.000000000 +0200
@@ -535,7 +535,7 @@ static int rndis_join_ibss(struct wiphy
 
 static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
 
-static int rndis_set_channel(struct wiphy *wiphy,
+static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev,
 	struct ieee80211_channel *chan, enum nl80211_channel_type channel_type);
 
 static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
@@ -2291,7 +2291,7 @@ static int rndis_leave_ibss(struct wiphy
 	return deauthenticate(usbdev);
 }
 
-static int rndis_set_channel(struct wiphy *wiphy,
+static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev,
 	struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)
 {
 	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
--- wireless-testing.orig/net/mac80211/cfg.c	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c	2010-05-02 17:47:51.000000000 +0200
@@ -1162,11 +1162,24 @@ static int ieee80211_set_txq_params(stru
 }
 
 static int ieee80211_set_channel(struct wiphy *wiphy,
+				 struct net_device *netdev,
 				 struct ieee80211_channel *chan,
 				 enum nl80211_channel_type channel_type)
 {
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 
+	switch (ieee80211_get_channel_mode(local, NULL)) {
+	case CHAN_MODE_HOPPING:
+		return -EBUSY;
+	case CHAN_MODE_FIXED:
+		if (local->oper_channel == chan &&
+		    local->oper_channel_type == channel_type)
+			return 0;
+		return -EBUSY;
+	case CHAN_MODE_UNDEFINED:
+		break;
+	}
+
 	local->oper_channel = chan;
 	local->oper_channel_type = channel_type;
 
@@ -1214,6 +1227,20 @@ static int ieee80211_auth(struct wiphy *
 static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
 			   struct cfg80211_assoc_request *req)
 {
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	switch (ieee80211_get_channel_mode(local, sdata)) {
+	case CHAN_MODE_HOPPING:
+		return -EBUSY;
+	case CHAN_MODE_FIXED:
+		if (local->oper_channel == req->bss->channel)
+			break;
+		return -EBUSY;
+	case CHAN_MODE_UNDEFINED:
+		break;
+	}
+
 	return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
 }
 
@@ -1236,8 +1263,22 @@ static int ieee80211_disassoc(struct wip
 static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 			       struct cfg80211_ibss_params *params)
 {
+	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
+	switch (ieee80211_get_channel_mode(local, sdata)) {
+	case CHAN_MODE_HOPPING:
+		return -EBUSY;
+	case CHAN_MODE_FIXED:
+		if (!params->channel_fixed)
+			return -EBUSY;
+		if (local->oper_channel == params->channel)
+			break;
+		return -EBUSY;
+	case CHAN_MODE_UNDEFINED:
+		break;
+	}
+
 	return ieee80211_ibss_join(sdata, params);
 }
 
--- wireless-testing.orig/net/mac80211/Makefile	2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/mac80211/Makefile	2010-05-02 17:47:51.000000000 +0200
@@ -23,7 +23,8 @@ mac80211-y := \
 	key.o \
 	util.o \
 	wme.o \
-	event.o
+	event.o \
+	chan.o
 
 mac80211-$(CONFIG_MAC80211_LEDS) += led.o
 mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ wireless-testing/net/mac80211/chan.c	2010-05-02 17:47:51.000000000 +0200
@@ -0,0 +1,57 @@
+/*
+ * mac80211 - channel management
+ */
+
+#include "ieee80211_i.h"
+
+enum ieee80211_chan_mode
+__ieee80211_get_channel_mode(struct ieee80211_local *local,
+			     struct ieee80211_sub_if_data *ignore)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	WARN_ON(!mutex_is_locked(&local->iflist_mtx));
+
+	list_for_each_entry(sdata, &local->interfaces, list) {
+		if (sdata == ignore)
+			continue;
+
+		if (!ieee80211_sdata_running(sdata))
+			continue;
+
+		if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+			continue;
+
+		if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+		    !sdata->u.mgd.associated)
+			continue;
+
+		if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+			if (!sdata->u.ibss.ssid_len)
+				continue;
+			if (!sdata->u.ibss.fixed_channel)
+				return CHAN_MODE_HOPPING;
+		}
+
+		if (sdata->vif.type == NL80211_IFTYPE_AP &&
+		    !sdata->u.ap.beacon)
+			continue;
+
+		return CHAN_MODE_FIXED;
+	}
+
+	return CHAN_MODE_UNDEFINED;
+}
+
+enum ieee80211_chan_mode
+ieee80211_get_channel_mode(struct ieee80211_local *local,
+			   struct ieee80211_sub_if_data *ignore)
+{
+	enum ieee80211_chan_mode mode;
+
+	mutex_lock(&local->iflist_mtx);
+	mode = __ieee80211_get_channel_mode(local, ignore);
+	mutex_unlock(&local->iflist_mtx);
+
+	return mode;
+}
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2010-05-02 17:47:50.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h	2010-05-02 17:47:51.000000000 +0200
@@ -1229,6 +1229,17 @@ int ieee80211_wk_remain_on_channel(struc
 int ieee80211_wk_cancel_remain_on_channel(
 	struct ieee80211_sub_if_data *sdata, u64 cookie);
 
+/* channel management */
+enum ieee80211_chan_mode {
+	CHAN_MODE_UNDEFINED,
+	CHAN_MODE_HOPPING,
+	CHAN_MODE_FIXED,
+};
+
+enum ieee80211_chan_mode
+ieee80211_get_channel_mode(struct ieee80211_local *local,
+			   struct ieee80211_sub_if_data *ignore);
+
 #ifdef CONFIG_MAC80211_NOINLINE
 #define debug_noinline noinline
 #else



^ permalink raw reply

* [PATCH] mac80211_hwsim: fix double-scan detection
From: Johannes Berg @ 2010-05-03  7:21 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Luis R. Rodriguez

Currently, hwsim will always detect a double scan
after the first one has finished ...

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 drivers/net/wireless/mac80211_hwsim.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- wireless-testing.orig/drivers/net/wireless/mac80211_hwsim.c	2010-05-03 09:19:54.000000000 +0200
+++ wireless-testing/drivers/net/wireless/mac80211_hwsim.c	2010-05-03 09:20:01.000000000 +0200
@@ -1021,7 +1021,7 @@ static void mac80211_hwsim_sw_scan_compl
 	mutex_lock(&hwsim->mutex);
 
 	printk(KERN_DEBUG "hwsim sw_scan_complete\n");
-	hwsim->scanning = true;
+	hwsim->scanning = false;
 
 	mutex_unlock(&hwsim->mutex);
 }



^ 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