Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] mac80211: use beacons for connection monitoring
From: Johannes Berg @ 2009-07-30  9:54 UTC (permalink / raw)
  To: Helmut Schaa; +Cc: Reinette Chatre, linville, linux-wireless
In-Reply-To: <200907301136.40274.helmut.schaa@googlemail.com>

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

On Thu, 2009-07-30 at 11:36 +0200, Helmut Schaa wrote:
> Am Mittwoch, 29. Juli 2009 schrieb Johannes Berg:
> > On Wed, 2009-07-29 at 14:32 -0700, Reinette Chatre wrote:
> > > From: Reinette Chatre <reinette.chatre@intel.com>
> > > 
> > > The connection monitor currently relies on probe requests paired
> > > with probe responses to ensure that a connection is alive. This is
> > > fragile in some environments where probe responses can get lost.
> > > When we receive beacons we can also consider the connection to be
> > > alive, so cancel connection poll instance when we receive a beacon.
> > > 
> > > The debug message "cancelling probereq poll due to a received beacon"
> > > is removed as part of this change as this case is hit very often after
> > > the above change and debug log receives significant number of these messages.
> > 
> > Not doing that was actually intentional -- we want to know whether or
> > not the connection is working both ways, not just whether we can receive
> > frames. This can certainly be improved, but I'm not sure this is the
> > best approach.
> 
> Just out of curiosity, do direct probe requests get ACKed?

Yes, they are normal directed management frames.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: [wireless] rt2870sta BUGs on shutdown, 2.6.30.2->git.today+git.wireless.today
From: Mike Galbraith @ 2009-07-30  9:44 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, LKML, John W. Linville
In-Reply-To: <1248946195.8925.9.camel@johannes.local>

On Thu, 2009-07-30 at 11:29 +0200, Johannes Berg wrote:
> On Thu, 2009-07-30 at 11:22 +0200, Mike Galbraith wrote:
> 
> > drivers/staging/rt2870/../rt2860/sta_ioctl.c
> 
> Sorry, but that '/staging/' thing in there means we cannot support this.
> If you must, take your query to the staging list,
> devel@driverdev.osuosl.org (according to MAINTAINERS).

Forwarded, thanks.

....hm.  Does "If you must" mean reports aren't welcome?

	-Mike


^ permalink raw reply

* Re: [PATCH] mac80211: use beacons for connection monitoring
From: Helmut Schaa @ 2009-07-30  9:36 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Reinette Chatre, linville, linux-wireless
In-Reply-To: <1248903902.8925.1.camel@johannes.local>

Am Mittwoch, 29. Juli 2009 schrieb Johannes Berg:
> On Wed, 2009-07-29 at 14:32 -0700, Reinette Chatre wrote:
> > From: Reinette Chatre <reinette.chatre@intel.com>
> > 
> > The connection monitor currently relies on probe requests paired
> > with probe responses to ensure that a connection is alive. This is
> > fragile in some environments where probe responses can get lost.
> > When we receive beacons we can also consider the connection to be
> > alive, so cancel connection poll instance when we receive a beacon.
> > 
> > The debug message "cancelling probereq poll due to a received beacon"
> > is removed as part of this change as this case is hit very often after
> > the above change and debug log receives significant number of these messages.
> 
> Not doing that was actually intentional -- we want to know whether or
> not the connection is working both ways, not just whether we can receive
> frames. This can certainly be improved, but I'm not sure this is the
> best approach.

Just out of curiosity, do direct probe requests get ACKed?

If not, the hardware wouldn't have a possibility to retry the frame and the
probability of loosing a probe request frame would be much higher then of
a data frame.

Helmut

^ permalink raw reply

* Re: [wireless] rt2870sta BUGs on shutdown, 2.6.30.2->git.today+git.wireless.today
From: Johannes Berg @ 2009-07-30  9:29 UTC (permalink / raw)
  To: Mike Galbraith; +Cc: linux-wireless, LKML, John W. Linville
In-Reply-To: <1248945770.7910.24.camel@marge.simson.net>

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

On Thu, 2009-07-30 at 11:22 +0200, Mike Galbraith wrote:

> drivers/staging/rt2870/../rt2860/sta_ioctl.c

Sorry, but that '/staging/' thing in there means we cannot support this.
If you must, take your query to the staging list,
devel@driverdev.osuosl.org (according to MAINTAINERS).

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* [wireless] rt2870sta BUGs on shutdown, 2.6.30.2->git.today+git.wireless.today
From: Mike Galbraith @ 2009-07-30  9:22 UTC (permalink / raw)
  To: linux-wireless; +Cc: LKML, John W. Linville

Greetings,

$subject appears (at glance) to happen because threads have already
exited when we get to BUG_ON(), I haven't pursued it though.  Using
rt3070sta instead of rt2870sta works a treat with same box/adapter.

(the 2009_0521_RT2870_Linux_STA_V2.1.2.0 tree patches and rpm'd up for
opensuse-11.1 with kernels 27->29 doesn't BUG.. for 30 onward, I'm using
the in kernel staging drivers)

Box is el-cheapo (Aldi supermarket:) Q6600
lsusb: Bus 001 Device 003: ID 13d3:3247 IMC Networks 802.11 n/g/b Wireless LAN Adapter

Other than the BUG on shutdown, the thing works fine.

[  962.934582] Terminate the TimerQThr pid=4557!
[  962.934586] Terminate the MLMEThr pid=4554!
[  962.934588] Terminate the RTUSBCmdThr pid=4556!
[  962.940928] ---> RTMPFreeTxRxRingMemory
[  962.944807] <--- ReleaseAdapter

drivers/staging/rt2870/../rt2860/sta_ioctl.c
1079                 RT28XX_MLME_HANDLER(pAdapter);

drivers/staging/rt2870/rt2870.h
499 #define RT28XX_MLME_HANDLER(pAd)                        RTUSBMlmeUp(pAd)
586 #ifndef RT30xx
587 #define RTUSBMlmeUp(pAd)                \
588 {                                                                   \
589         POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;  \
590         BUG_ON(pObj->MLMEThr_task == NULL);                 \
591         CHECK_PID_LEGALITY(task_pid(pObj->MLMEThr_task))                    \
592         up(&(pAd->mlme_semaphore)); \
593 }

[  962.962117] ------------[ cut here ]------------
[  962.966079] kernel BUG at drivers/staging/rt2870/../rt2860/sta_ioctl.c:1079!
[  962.968800] invalid opcode: 0000 [#1] SMP 
[  962.968800] last sysfs file: /sys/devices/pci0000:00/0000:00:1a.7/usb1/1-5/net/wlan0/type
[  962.985994] CPU 0 
[  962.985994] Modules linked in: xt_tcpudp xt_pkttype xt_limit snd_pcm_oss snd_mixer_oss snd_seq snd_seq_device nfsd lockd nfs_acl auth_rpcgss sunrpc exportfs ip6t_REJECT nf_conntrack_ipv6 ip6table_raw xt_NOTRACK ipt_REJECT xt_state iptable_raw iptable_filter ip6table_mangle nf_conntrack_netbios_ns nf_conntrack_ipv4 nf_conntrack nf_defrag_ipv4 ip_tables ip6table_filter cpufreq_conservative ip6_tables cpufreq_ondemand cpufreq_userspace x_tables cpufreq_powersave acpi_cpufreq ipv6 microcode fuse loop dm_mod snd_hda_codec_realtek snd_hda_intel firewire_ohci snd_hda_codec firewire_core snd_hwdep crc_itu_t snd_pcm snd_timer snd usb_storage ohci1394 soundcore rtc_cmos i2c_i801 rt2870sta(C) sr_mod usb_libusual rtc_core snd_page_alloc ieee1394 i2c_core thermal e1000e cdrom intel_agp button processor rtc_lib sg usbhid hid ehci_hcd uhci_hcd sd_mod usbcore edd fan ext3 mbcache jbd ahci libata scsi_mod
[  963.064503] Pid: 4752, comm: wpa_supplicant Tainted: G         C 2.6.31-wireless-smp #78 MS-7502
[  963.076503] RIP: 0010:[<ffffffffa0227043>]  [<ffffffffa0227043>] rt_ioctl_siwscan+0x1ad/0x1d6 [rt2870sta]
[  963.084502] RSP: 0018:ffff8800bf293bf8  EFLAGS: 00010246
[  963.088502] RAX: 0000000000000000 RBX: ffffc900127c7000 RCX: 0000000000000000
[  963.096503] RDX: 0000000000000508 RSI: 0000000000000508 RDI: ffffffffa01f6bca
[  963.100505] RBP: ffff8800bf293c08 R08: 0000000000000000 R09: ffff8800bf293d48
[  963.112503] R10: ffffffffa0226e96 R11: 0000000000000246 R12: 000000010002876c
[  963.112503] R13: ffff8800bdcfca00 R14: ffffffff812c0730 R15: 0000000000008b18
[  963.124502] FS:  00007fc25d6e36f0(0000) GS:ffff8800014e1000(0000) knlGS:0000000000000000
[  963.124502] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  963.124502] CR2: 00007fc25d72a000 CR3: 00000000be091000 CR4: 00000000000006f0
[  963.124502] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  963.124502] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[  963.124502] Process wpa_supplicant (pid: 4752, threadinfo ffff8800bf292000, task ffff880037848660)
[  963.124502] Stack:
[  963.124502]  00000000fffffff4 ffff8800bf293de8 ffff8800bf293ca8 ffffffff8126a17e
[  963.124502] <0> ffff8800bf293c98 ffff8800bf293d48 ffff8800378b6000 ffffffffa0226e96
[  963.124502] <0> 0000000000000000 0000000000000000 0000000000001290 ffffffff00000000
[  963.192503] Call Trace:
[  963.196502]  [<ffffffff8126a17e>] ioctl_standard_iw_point+0x198/0x227
[  963.204503]  [<ffffffffa0226e96>] ? rt_ioctl_siwscan+0x0/0x1d6 [rt2870sta]
[  963.208503]  [<ffffffff8126a2a2>] ioctl_standard_call+0x95/0xb4
[  963.216505]  [<ffffffff8126a3f7>] wext_ioctl_dispatch+0x9a/0x172
[  963.220503]  [<ffffffff81269f6d>] ? ioctl_private_call+0x0/0x79
[  963.228503]  [<ffffffff8126a20d>] ? ioctl_standard_call+0x0/0xb4
[  963.234729]  [<ffffffff8126a5ba>] wext_handle_ioctl+0x39/0x6f
[  963.240503]  [<ffffffff810ca59b>] ? core_sys_select+0x23d/0x270
[  963.244503]  [<ffffffff811f73ae>] dev_ioctl+0x60e/0x637
[  963.252502]  [<ffffffff811e6096>] sock_ioctl+0x217/0x226
[  963.256502]  [<ffffffff810c8614>] vfs_ioctl+0x2a/0x78
[  963.256502]  [<ffffffff810c8b75>] do_vfs_ioctl+0x498/0x4d9
[  963.268502]  [<ffffffff810c8c0b>] sys_ioctl+0x55/0x77
[  963.268502]  [<ffffffff8100ba6b>] system_call_fastpath+0x16/0x1b
[  963.276503] Code: 00 00 00 00 00 00 4c 89 a3 90 19 00 00 ba 08 05 00 00 be 05 00 00 00 48 89 df e8 90 fa fc ff 48 8b 03 48 8b 40 08 48 85 c0 75 04 <0f> 0b eb fe 48 8b 80 00 02 00 00 48 85 c0 74 06 83 78 30 00 78 
[  963.292503] RIP  [<ffffffffa0227043>] rt_ioctl_siwscan+0x1ad/0x1d6 [rt2870sta]
[  963.304502]  RSP <ffff8800bf293bf8>
[  963.310285] ---[ end trace 292b4b823f542e3f ]---



^ permalink raw reply

* Re: zd1211rw couldn't load firmware. Error number -145 with Kernel  2.6.30
From: Mladen Horvat @ 2009-07-30  8:32 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <3ace41890907292043rad37b63y12cacfeb713dc575@mail.gmail.com>

Hin-Tak Leung <hintak.leung@...> writes:
> 
> I noticed you have a particularly slow CPU (33MHz?)... the vendor
> driver has some preculiar coding to interrupt some operations to
> prevent deadlocks; I wonder if the rw driver inherit that? One of the
> patches in my patch set for the vendor driver put a delay right after
> firmware load;
> it might be appropriate to add something similiar to the rw driver.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@...
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 


Hi,

its an 300 MHz MIPS Prozessor with usb 1.1 but if you point me to the right
place to patch i can test this.

Tech. Tedails are here: http://www.dream-multimedia-tv.de/dm-7025#tech_details

Regards


^ permalink raw reply

* Re: [RFT] cfg80211: enable country IE support to all cfg80211 drivers
From: Johannes Berg @ 2009-07-30  7:57 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: linux-wireless
In-Reply-To: <1248915719-6208-1-git-send-email-lrodriguez@atheros.com>

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

On Wed, 2009-07-29 at 18:01 -0700, Luis R. Rodriguez wrote:
> Since the bss is always set now once we are connected, if the
> bss has its own information element we refer to it and pass that
> instead of relying on mac80211's parsing.
> 
> Now all cfg80211 drivers get country IE support, automatically.
> 
> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
> ---
> 
> Johill, I think this is what you wanted in the end, I tested it and
> I get no country IE hint going through :( I could debug further but I'm
> done for now and gotta work on some other stuff, not sure when I can
> get back to this.

Well, you've made a critical mistake:

+       regulatory_hint_11d(wdev->wiphy,
+                           bss->information_elements,
+                           bss->len_information_elements);

needs to be

	const u8 *country_ie

	country_ie = ieee80211_bss_get_ie(&bss->pub, WLAN_EID_COUNTRY);
	if (country_ie)
		regulatory_hint_11d(wdev->wiphy,
				    country_ie + 2,
				    country_ie[1]);


It's rather likely that it doesn't come first, so whatever is in
information_elements first would end up not looking like a country IE or
having the right length, so the _11d function would just throw it out.


johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: [PATCH 2/2] cfg80211: decouple regulatory variables from cfg80211_mutex
From: Johannes Berg @ 2009-07-30  7:43 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: linville, linux-wireless
In-Reply-To: <1248914792-6010-3-git-send-email-lrodriguez@atheros.com>

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

On Wed, 2009-07-29 at 17:46 -0700, Luis R. Rodriguez wrote:
> We change regulatory code to be protected by its own regulatory
> spinlock and alleviate cfg80211_mutex to only be used to protect
> cfg80211_rdev_list, the registered device list.
> 
> By doing this we will be able to work on regulatory core components
> without having to have hog up the cfg80211_mutex. An example here is
> we no longer need to use the cfg80211_mutex during the country IE
> regulatory hint; by doing so we end up curing this new lockdep warning:

This is ok with me, but be sure that it changes the API between drivers
and cfg80211 -- the reg notifier can no longer sleep now.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: [PATCH] wireless-regdb: TH gets 5 GHz enabled as of new regulatory rules
From: Phattanon Duangdara @ 2009-07-30  5:46 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <f7de31c0907292242s7c41daefr6ca7b3423180d005@mail.gmail.com>

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

===

Rules for communication equipment that use 2.400-2.500 GHz band:

Communication equipment that use 2.400-2.500 GHz band must stated and
comply with
one of following standards:

2.1.2.1  EN 300 328-2  :  Electromagnetic compatibility and Radio
spectrum Matters
(ERM); Wideband Transmission systems; Data transmission
equipment operating in the 2,4 GHz ISM band and using
spread spectrum modulation techniques; Part 2: Harmonized
EN covering essential requirements under article 3.2 of R&TTE
Directive
2.1.2.2  FCC Part 15.247 :  Code of Federal Regulations (USA); Title 47
Telecommunication; Chapter 1 Federal Communications
Commission; Part 15 Radio Frequency Devices; Subpart C –
Intentional Radiators; §15.247 Operation within the bands 902–
928 MHz, 2400–2483.5 MHz, and 5725–5850 MHz

===

>
>> I corrected power but What a field before power is (that is now N/A below) ?
>
> The rules can be read as follows:
>
> (start - end @ max bandwidth spacing), (max antenna gain, max eirp)
>
>> # TH Data (2008) from
>> http://www.ratchakitcha.soc.go.th/DATA/PDF/2551/E/042/64.PDF
>> country TH:
>>        (2402 - 2472 @ 40), (N/A, 20)
>>        (5170 - 5250 @ 40), (N/A, 23), NO-OUTDOOR
>>        (5250 - 5330 @ 40), (N/A, 23), NO-OUTDOOR, DFS
>>        (5490 - 5710 @ 40), (N/A, 30), DFS
>>        (5735 - 5835 @ 30), (N/A, 30)

Opps, my typo

country TH:
       (2402 - 2472 @ 40), (N/A, 20)
       (5170 - 5250 @ 40), (N/A, 23), NO-OUTDOOR
       (5250 - 5330 @ 40), (N/A, 23), NO-OUTDOOR, DFS
       (5490 - 5710 @ 40), (N/A, 30), DFS
       (5735 - 5835 @ 40), (N/A, 30)

> Michael, does your concur with this?
>>> Summary I got from the document
>>
>> 2400-2500 MHz
>> Max Power (e.i.r.p): 100mW
>> Bandwidth: Not specified
>> Usage: Not specified
>> Ref Standard (either):
>
> Either, does that mean either FCC, or ETSI or ITU, you take a pick?
> That would seem pretty vague for regulatory purposes.
>
>> EN 300 328-2 : Electromagnetic compatibility and Radio spectrum Matters
>> (ERM); Wideband Transmission systems; Data transmission
>> equipment operating in the 2,4 GHz ISM band and using
>> spread spectrum modulation techniques; Part 2: Harmonized
>> EN covering essential requirements under article 3.2 of R&TTE
>> Directive
>
> Did this come from the TH document?

Yes. I managed to get translated documents, but for now I didn't get
any reply from NTC.

>
>> FCC Part 15.247 : Code of Federal Regulations (USA); Title 47
>> Telecommunication; Chapter 1 Federal Communications
>> Commission; Part 15 Radio Frequency Devices; Subpart C –
>> Intentional Radiators; §15.247 Operation within the bands 902–
>> 928 MHz, 2400–2483.5 MHz, and 5725–5850 MHz
>
> This too?? I ask because I see FCC mentioned.
>
>> 5150-5350 MHz
>> Max Power (e.i.r.p): 200mW, Density 10mW/MHz (0.25mW/25KHz)
>> Bandwidth: Not specified
>> Usage: Indoor applications only, DFS is must
>
> Thanks, did this came from the TH document?
>
>> Resolution 229 (WRC-03)
>> (Radio Regulations) - Use of the bands 5 150-5 250 MHz, 5 250-5 350
>> MHz and 5 470-5 725
>> MHz by the mobile service for the implementation of wireless access
>> systems including
>> radio local area networks
>>
>> Recommendation ITU-R M. 1652 (Annex 1): Dynamic
>> frequency selection (DFS) in wireless access systems including radio
>> local area networks
>> for the purpose of protecting the radiocommunication service in the 5 GHz band
>>
>> Ref Standard (either):
>>
>> ETSI EN 301 893 : Broadband Radio Access Networks (BRAN); 5 GHz high
>> performance RLAN; Harmonized EN covering essential
>> requirements of article 3.2 of the R&TTE Directive
>>
>> FCC Part 15.407 : Code of Federal Regulations (USA); Title 47
>> Telecommunications; Chapter 1 Federal Communications
>> Commission; Part 15 Radio Frequency Devices; Subpart E –
>> Unlicensed National Information Infrastructure Devices;
>> § 15.407 General technical requirements
>>
>>
>>
>> 5450-5725 MHz
>> Max Power (e.i.r.p): 1W, Density 50mW/MHz
>> Bandwidth: Not specified
>> Usage: Not specified, DFS is must
>>
>> Resolution 229 (WRC-03)
>> (Radio Regulations) - Use of the bands 5 150-5 250 MHz, 5 250-5 350
>> MHz and 5 470-5 725
>> MHz by the mobile service for the implementation of wireless access
>> systems including
>> radio local area networks
>>
>> Recommendation ITU-R M. 1652 (Annex 1): Dynamic
>> frequency selection (DFS) in wireless access systems including radio
>> local area networks
>> for the purpose of protecting the radiocommunication service in the 5 GHz band
>>
>> Ref Standard (either):
>>
>> ETSI EN 301 893 : Broadband Radio Access Networks (BRAN); 5 GHz high
>> performance RLAN; Harmonized EN covering essential
>> requirements of article 3.2 of the R&TTE Directive
>>
>> Code of Federal Regulations (USA); Title 47
>> Telecommunications; Chapter 1 Federal Communications
>> Commission; Part 15 Radio Frequency Devices; Subpart E –
>> Unlicensed National Information Infrastructure Devices;
>> § 15.407 General technical requirements
>>
>> 5725-5850 MHz
>> Max Power (e.i.r.p): 1W
>> Bandwidth: Not specified
>> Usage: Not specified
>> Ref Standard (either):
>>
>> FCC Part 15.247 : Code of Federal Regulations (USA); Title 47
>> Telecommunication; Chapter 1 Federal Communications
>> Commission; Part 15 Radio Frequency Devices; Subpart C –
>> Intentional Radiators; §15.247 Operation within the bands 902–
>> 928 MHz, 2400–2483.5 MHz, and 5725–5850 MHz
>>
>> Code of Federal Regulations (USA); Title 47
>> Telecommunications; Chapter 1 Federal Communications
>> Commission; Part 15 Radio Frequency Devices; Subpart E –
>> Unlicensed National Information Infrastructure Devices;
>> § 15.407 General technical requirements
>>
>> Phattanon,
>>
>> On Thu, Jul 23, 2009 at 12:51 AM, Luis R.
>> Rodriguez<lrodriguez@atheros.com> wrote:
>>> Phattanon Duangdara reported the National Telecommunication
>>> Commisions of Thailand has announced new regulatory rules
>>> about 5GHz for RLAN last year.
>>>
>>> I have verified this matches our documentation internally
>>> at Atheros.
>>>
>>> Reference in Thai Language:
>>> http://www.ratchakitcha.soc.go.th/DATA/PDF/2551/E/042/64.PDF
>>>
>>> Cc: Michael Green <michael.green@atheros.com>
>>> Cc: David Quan <david.quan@atheros.com>
>>> Reported-by: Phattanon Duangdara <sfalpha@gmail.com>
>>> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
>>> ---
>>>  db.txt |    6 +++++-
>>>  1 files changed, 5 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/db.txt b/db.txt
>>> index fad098d..01536d6 100644
>>> --- a/db.txt
>>> +++ b/db.txt
>>> @@ -534,7 +534,11 @@ country TW:
>>>        (5735 - 5815 @ 40), (3, 30)
>>>
>>>  country TH:
>>> -       (2402 - 2482 @ 40), (N/A, 20)
>>> +       (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)
>>>
>>>  country TT:
>>>        (2402 - 2482 @ 40), (N/A, 20)
>>> --
>>> 1.6.3.3
>>>
>>>

^ permalink raw reply

* Re: [PATCH] mac80211: use beacons for connection monitoring
From: Maxim Levitsky @ 2009-07-30  5:24 UTC (permalink / raw)
  To: reinette chatre
  Cc: Johannes Berg, linville@tuxdriver.com,
	linux-wireless@vger.kernel.org
In-Reply-To: <1248904238.1216.1019.camel@rc-desk>

On Wed, 2009-07-29 at 14:50 -0700, reinette chatre wrote:
> On Wed, 2009-07-29 at 14:45 -0700, Johannes Berg wrote:
> > On Wed, 2009-07-29 at 14:32 -0700, Reinette Chatre wrote:
> > > From: Reinette Chatre <reinette.chatre@intel.com>
> > > 
> > > The connection monitor currently relies on probe requests paired
> > > with probe responses to ensure that a connection is alive. This is
> > > fragile in some environments where probe responses can get lost.
> > > When we receive beacons we can also consider the connection to be
> > > alive, so cancel connection poll instance when we receive a beacon.
> > > 
> > > The debug message "cancelling probereq poll due to a received beacon"
> > > is removed as part of this change as this case is hit very often after
> > > the above change and debug log receives significant number of these messages.
> > 
> > Not doing that was actually intentional -- we want to know whether or
> > not the connection is working both ways, not just whether we can receive
> > frames. This can certainly be improved, but I'm not sure this is the
> > best approach.
> 
> I'd be happy to try out other approaches because my connection is
> dropping every few minutes. 


Mine too, and it even happens when I am a meter away from the AP.
My device is 3945.

Best regards,
	Maxim Levitsky



^ permalink raw reply

* Re: Using compat-wireless w/ 2.6.27.26
From: Philip A. Prindeville @ 2009-07-30  4:36 UTC (permalink / raw)
  To: Bob Copeland; +Cc: Luis R. Rodriguez, linux-wireless
In-Reply-To: <b6c5339f0907240658o38f4ee76t2de8a071cd2f37f4@mail.gmail.com>

Bob Copeland wrote:
> On Thu, Jul 23, 2009 at 6:45 PM, Philip A.
> Prindeville<philipp_subx@redfish-solutions.com> wrote:
>> Bob Copeland wrote:
>>> On Thu, Jul 23, 2009 at 5:53 PM, Philip A.
>>> Prindeville<philipp_subx@redfish-solutions.com> wrote:
>>>>> Getting closer :-)
>>>>>
>>>>> ath5k_tx_processq(sc, &sc->txqs[i]);
>>>>>
>>>> Didn't work with rc4:
>>> What did you apply against?  It's supposed to be against
>>> wireless-testing (or, at worst, latest compat-wireless).
>>>
>>>> BUG: unable to handle kernel NULL pointer dereference at 00000000
>>>> IP: [<d0935658>] :ath5k:ath5k_tasklet_tx+0x5e/0x27b
> 
>> This was against compat-wireless-2.6.31-rc4.
>>
>> Alas, I already blew away the build directory...
> 
> I think you need to use the unstable compat-wireless snapshots;
> I have a feeling that the above doesn't have all of the tx queues.
> 
> Check out ath5k.h, the txq array in struct ath5k_softc should have
> NUM_TX_QUEUES entries, an earlier version only had 2.
> 
> Although your compiler generates rather different code from mine
> (different config or whatever), it looks like the oops happened
> in the list_for_each_entry(... txq->q ...) -- but I don't see how
> that can happen in my copy, since txq[i].q is initialized at the
> same time as txq[i].setup.
> 

Give me a shout when this patch makes its way into compat-wireless-2.6.31-rcN and I'll try again with that.

-Philip


^ permalink raw reply

* Re: zd1211rw couldn't load firmware. Error number -145 with Kernel 2.6.30
From: Hin-Tak Leung @ 2009-07-30  3:43 UTC (permalink / raw)
  To: Mladen Horvat; +Cc: linux-wireless
In-Reply-To: <loom.20090729T120228-576@post.gmane.org>

On Wed, Jul 29, 2009 at 1:08 PM, Mladen
Horvat<acid-burn@opendreambox.org> wrote:
> Holger Schurig <hs4233@...> writes:
>
>>
>> > [  415.271000] usb 1-1: upload_firmware()
>> > firmware device id 0x4810 is equal to the actual device id
>>
>> Looks like your firmware could be successfully loaded and checked
>> by the driver.
>>
>> > [  416.350000] usb 1-1: USB control request for firmware
>> > upload failed. Error number -145
>>
>> Looks like an URB (USB request block) couldn't transferred to the
>> device. As you speak about an embedded device: are you sure that
>> your USB hardware works correctly?
>>
>
>
> Hello Holger,
>
> thanks for your fast answer.
>
> I hope to be sure that the usb hardware works correctly.
> As i said, the same stb only booted with a rt73usb wlan stick attached has no
> problems with the firmware upload and also wpa-supplicant connection and
> everything works on wlan0.  only problem are these two zd1211b usb sticks in the
> zd1211rw driver.
>
> the same stb running a kernel 2.6.12 and the original vendor driver 2.22.00
> works without problems..
>
> so i think i can exclude a hardware bug on the usb/stb side.
>
> Hope this helps.
> If any other logs are needed i will provide them.
>
>
> Regards
>
> Mladen
>
>
>
> --
> 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
>

I noticed you have a particularly slow CPU (33MHz?)... the vendor
driver has some preculiar coding to interrupt some operations to
prevent deadlocks; I wonder if the rw driver inherit that? One of the
patches in my patch set for the vendor driver put a delay right after
firmware load;
it might be appropriate to add something similiar to the rw driver.

^ permalink raw reply

* Re: The problem of driver of rtl8187 wireless card
From: Hin-Tak Leung @ 2009-07-30  3:36 UTC (permalink / raw)
  To: gu gu; +Cc: linux-wireless
In-Reply-To: <109708.86209.qm@web15808.mail.cnb.yahoo.com>

2009/7/29 gu gu <guatsheng@yahoo.com.cn>:
>
> Dear Sir,
>     Rencently,I do a job to transplant a wireless wifi-card connected by the USB,which was designed baseing the chip rtl8187 for ARM board.But in the process i have some trouble in writing the driver programe.
>     My linux kernel is Version-2.6.25.10,It is true that the kernel have the driver for the chip rtl8187 .When I connected the wifi card through the USB port ,the kernel can recoganize the card "Manufacturer_Realtek_RTL8187",So it's sure that the driver of RTL8187 is no problem.But when I ping it to the AP,the missing of datapackets and the delay are both terrible.and more , there is nothing accepted by the wireless router when i typed the "ping".
> so i think there is some bug exist in the driver for RTL8187 of kernel ,isn't it? (ps: I have set several parameter,such essid ,IP address...)
>  So I download a "compat-wireless-2.6-old" packet.following the " Readme",i added the KLIB & KLIB_BUILD in the Makefile and "make" it.It is well to generate  some modules with the typing".o"! but has not compiled the file rtl8187 or generated a "rtl8187.o".
> and so i wanna to know how to solve this problem. i need some help from u,
> Thank you for your attention!

yes, the rtl8187 driver earlier than 26.28/29 were a bit buggy. You
should use compat-wireless, and 2.6 kernel modules are named *.ko. You
should have a rtl8187.ko, and you need a few others (4-5 in total) as
well. There were a reorg and rtl818x now has its own directory,
compared to earlier kernel tree.

^ permalink raw reply

* Re: [PATCH] mac80211: use beacons for connection monitoring
From: Marcel Holtmann @ 2009-07-30  2:39 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Reinette Chatre, linville, linux-wireless
In-Reply-To: <1248903902.8925.1.camel@johannes.local>

Hi Johannes,

> > The connection monitor currently relies on probe requests paired
> > with probe responses to ensure that a connection is alive. This is
> > fragile in some environments where probe responses can get lost.
> > When we receive beacons we can also consider the connection to be
> > alive, so cancel connection poll instance when we receive a beacon.
> > 
> > The debug message "cancelling probereq poll due to a received beacon"
> > is removed as part of this change as this case is hit very often after
> > the above change and debug log receives significant number of these messages.
> 
> Not doing that was actually intentional -- we want to know whether or
> not the connection is working both ways, not just whether we can receive
> frames. This can certainly be improved, but I'm not sure this is the
> best approach.

this patch might be a band-aid and needs improvement or a total
different solution, but it does help my disconnect problems. It makes my
connection fully stable again. So it is not a wrong approach in general,
because otherwise I have to be always close to me AP. And then using
WiFi is bloody pointless since I could just put an Ethernet cable into
the wall socket directly.

Regards

Marcel



^ permalink raw reply

* [RFT] cfg80211: enable country IE support to all cfg80211 drivers
From: Luis R. Rodriguez @ 2009-07-30  1:01 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Luis R. Rodriguez

Since the bss is always set now once we are connected, if the
bss has its own information element we refer to it and pass that
instead of relying on mac80211's parsing.

Now all cfg80211 drivers get country IE support, automatically.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---

Johill, I think this is what you wanted in the end, I tested it and
I get no country IE hint going through :( I could debug further but I'm
done for now and gotta work on some other stuff, not sure when I can
get back to this.

 include/net/cfg80211.h |   14 --------------
 net/mac80211/mlme.c    |    6 +-----
 net/wireless/reg.c     |    1 -
 net/wireless/reg.h     |   15 +++++++++++++++
 net/wireless/sme.c     |    5 +++++
 5 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e1b9235..fa72997 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1514,20 +1514,6 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb);
 extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
 
 /**
- * regulatory_hint_11d - hints a country IE as a regulatory domain
- * @wiphy: the wireless device giving the hint (used only for reporting
- *	conflicts)
- * @country_ie: pointer to the country IE
- * @country_ie_len: length of the country IE
- *
- * We will intersect the rd with the what CRDA tells us should apply
- * for the alpha2 this country IE belongs to, this prevents APs from
- * sending us incorrect or outdated information against a country.
- */
-extern void regulatory_hint_11d(struct wiphy *wiphy,
-				u8 *country_ie,
-				u8 country_ie_len);
-/**
  * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
  * @wiphy: the wireless device we want to process the regulatory domain on
  * @regd: the custom regulatory domain to use for this wiphy
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0779ba1..5ff1496 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1846,12 +1846,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 					       bssid, ap_ht_cap_flags);
 	}
 
+	/* Note: country IE parsing is done for us by cfg80211 */
 	if (elems.country_elem) {
-		/* Note we are only reviewing this on beacons
-		 * for the BSSID we are associated to */
-		regulatory_hint_11d(local->hw.wiphy,
-			elems.country_elem, elems.country_elem_len);
-
 		/* TODO: IBSS also needs this */
 		if (elems.pwr_constr_elem)
 			ieee80211_handle_pwr_constr(sdata,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 41c16fc..48158fc 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1904,7 +1904,6 @@ free_rd_out:
 out:
 	spin_unlock(&reg_lock);
 }
-EXPORT_SYMBOL(regulatory_hint_11d);
 
 static bool freq_is_chan_12_13_14(u16 freq)
 {
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index e37829a..662a9da 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -36,4 +36,19 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
 					struct ieee80211_channel *beacon_chan,
 					gfp_t gfp);
 
+/**
+ * regulatory_hint_11d - hints a country IE as a regulatory domain
+ * @wiphy: the wireless device giving the hint (used only for reporting
+ *	conflicts)
+ * @country_ie: pointer to the country IE
+ * @country_ie_len: length of the country IE
+ *
+ * We will intersect the rd with the what CRDA tells us should apply
+ * for the alpha2 this country IE belongs to, this prevents APs from
+ * sending us incorrect or outdated information against a country.
+ */
+void regulatory_hint_11d(struct wiphy *wiphy,
+			 u8 *country_ie,
+			 u8 country_ie_len);
+
 #endif  /* __NET_WIRELESS_REG_H */
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 3728d2b..c332c42 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -13,6 +13,7 @@
 #include <net/cfg80211.h>
 #include <net/rtnetlink.h>
 #include "nl80211.h"
+#include "reg.h"
 
 struct cfg80211_conn {
 	struct cfg80211_connect_params params;
@@ -401,6 +402,10 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
 
 	wdev->sme_state = CFG80211_SME_CONNECTED;
 	cfg80211_upload_connect_keys(wdev);
+
+	regulatory_hint_11d(wdev->wiphy,
+			    bss->information_elements,
+			    bss->len_information_elements);
 }
 
 void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
-- 
1.6.0.4


^ permalink raw reply related

* [PATCH 2/2] cfg80211: decouple regulatory variables from cfg80211_mutex
From: Luis R. Rodriguez @ 2009-07-30  0:46 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1248914792-6010-1-git-send-email-lrodriguez@atheros.com>

We change regulatory code to be protected by its own regulatory
spinlock and alleviate cfg80211_mutex to only be used to protect
cfg80211_rdev_list, the registered device list.

By doing this we will be able to work on regulatory core components
without having to have hog up the cfg80211_mutex. An example here is
we no longer need to use the cfg80211_mutex during the country IE
regulatory hint; by doing so we end up curing this new lockdep warning:

=======================================================
[ INFO: possible circular locking dependency detected ]
2.6.31-rc4-wl #12
-------------------------------------------------------
phy1/1709 is trying to acquire lock:
 (cfg80211_mutex){+.+.+.}, at: [<ffffffffa00af852>] regulatory_hint_11d+0x32/0x3f0 [cfg80211]

but task is already holding lock:
 (&ifmgd->mtx){+.+.+.}, at: [<ffffffffa0144228>] ieee80211_sta_work+0x108/0x10f0 [mac80211]

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #3 (&ifmgd->mtx){+.+.+.}:
       [<ffffffff810857b6>] __lock_acquire+0xd76/0x12b0
       [<ffffffff81085dd3>] lock_acquire+0xe3/0x120
       [<ffffffff814eeae4>] mutex_lock_nested+0x44/0x350
       [<ffffffffa0141bb8>] ieee80211_mgd_auth+0x108/0x1f0 [mac80211]
       [<ffffffffa0148563>] ieee80211_auth+0x13/0x20 [mac80211]
       [<ffffffffa00bc3a1>] __cfg80211_mlme_auth+0x1b1/0x2a0 [cfg80211]
       [<ffffffffa00bc516>] cfg80211_mlme_auth+0x86/0xc0 [cfg80211]
       [<ffffffffa00b368d>] nl80211_authenticate+0x21d/0x230 [cfg80211]
       [<ffffffff81416ba6>] genl_rcv_msg+0x1b6/0x1f0
       [<ffffffff81415c39>] netlink_rcv_skb+0x89/0xb0
       [<ffffffff814169d9>] genl_rcv+0x29/0x40
       [<ffffffff8141591d>] netlink_unicast+0x29d/0x2b0
       [<ffffffff81416514>] netlink_sendmsg+0x214/0x300
       [<ffffffff813e4407>] sock_sendmsg+0x107/0x130
       [<ffffffff813e45b9>] sys_sendmsg+0x189/0x320
       [<ffffffff81011f82>] system_call_fastpath+0x16/0x1b
       [<ffffffffffffffff>] 0xffffffffffffffff

-> #2 (&wdev->mtx){+.+.+.}:
       [<ffffffff810857b6>] __lock_acquire+0xd76/0x12b0
       [<ffffffff81085dd3>] lock_acquire+0xe3/0x120
       [<ffffffff814eeae4>] mutex_lock_nested+0x44/0x350
       [<ffffffffa00ab304>] cfg80211_netdev_notifier_call+0x1a4/0x390 [cfg80211]
       [<ffffffff814f3dff>] notifier_call_chain+0x3f/0x80
       [<ffffffff81075a91>] raw_notifier_call_chain+0x11/0x20
       [<ffffffff813f665a>] dev_open+0x10a/0x120
       [<ffffffff813f59bd>] dev_change_flags+0x9d/0x1e0
       [<ffffffff8144eb6e>] devinet_ioctl+0x6fe/0x760
       [<ffffffff81450204>] inet_ioctl+0x94/0xc0
       [<ffffffff813e25fa>] sock_ioctl+0x6a/0x290
       [<ffffffff8111e911>] vfs_ioctl+0x31/0xa0
       [<ffffffff8111ea9a>] do_vfs_ioctl+0x8a/0x5c0
       [<ffffffff8111f069>] sys_ioctl+0x99/0xa0
       [<ffffffff81011f82>] system_call_fastpath+0x16/0x1b
       [<ffffffffffffffff>] 0xffffffffffffffff

-> #1 (&rdev->mtx){+.+.+.}:
       [<ffffffff810857b6>] __lock_acquire+0xd76/0x12b0
       [<ffffffff81085dd3>] lock_acquire+0xe3/0x120
       [<ffffffff814eeae4>] mutex_lock_nested+0x44/0x350
       [<ffffffffa00ac4d0>] cfg80211_get_dev_from_ifindex+0x60/0x90 [cfg80211]
       [<ffffffffa00b21ff>] get_rdev_dev_by_info_ifindex+0x6f/0xa0 [cfg80211]
       [<ffffffffa00b51eb>] nl80211_set_interface+0x3b/0x260 [cfg80211]
       [<ffffffff81416ba6>] genl_rcv_msg+0x1b6/0x1f0
       [<ffffffff81415c39>] netlink_rcv_skb+0x89/0xb0
       [<ffffffff814169d9>] genl_rcv+0x29/0x40
       [<ffffffff8141591d>] netlink_unicast+0x29d/0x2b0
       [<ffffffff81416514>] netlink_sendmsg+0x214/0x300
       [<ffffffff813e4407>] sock_sendmsg+0x107/0x130
       [<ffffffff813e45b9>] sys_sendmsg+0x189/0x320
       [<ffffffff81011f82>] system_call_fastpath+0x16/0x1b
       [<ffffffffffffffff>] 0xffffffffffffffff

other info that might help us debug this:

3 locks held by phy1/1709:
 #0:  ((wiphy_name(local->hw.wiphy))){+.+.+.}, at: [<ffffffff8106b45d>] worker_thread+0x19d/0x340
 #1:  (&ifmgd->work){+.+.+.}, at: [<ffffffff8106b45d>] worker_thread+0x19d/0x340
 #2:  (&ifmgd->mtx){+.+.+.}, at: [<ffffffffa0144228>] ieee80211_sta_work+0x108/0x10f0 [mac80211]

Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---
 net/wireless/core.c |    4 +---
 net/wireless/reg.c  |   26 +++++++++++++++++++++-----
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/net/wireless/core.c b/net/wireless/core.c
index 755cdf1..d8dbd7f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -34,9 +34,7 @@ MODULE_DESCRIPTION("wireless configuration support");
 LIST_HEAD(cfg80211_rdev_list);
 
 /*
- * This is used to protect the cfg80211_rdev_list, cfg80211_regdomain,
- * country_ie_regdomain, the reg_beacon_list and the the last regulatory
- * request receipt (last_request).
+ * This is used to protect the cfg80211_rdev_list
  */
 DEFINE_MUTEX(cfg80211_mutex);
 
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2d1d183..41c16fc 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -62,6 +62,15 @@ const struct ieee80211_regdomain *cfg80211_regdomain;
  */
 static const struct ieee80211_regdomain *country_ie_regdomain;
 
+/*
+ * Protects static reg.c components:
+ *     - cfg80211_world_regdom
+ *     - cfg80211_regdom
+ *     - country_ie_regdomain
+ *     - last_request
+ */
+static spinlock_t reg_lock;
+
 /* Used to queue up regulatory hints */
 static LIST_HEAD(reg_requests_list);
 static spinlock_t reg_requests_lock;
@@ -1570,6 +1579,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
 	BUG_ON(!reg_request->alpha2);
 
 	mutex_lock(&cfg80211_mutex);
+	spin_lock(&reg_lock);
 
 	if (wiphy_idx_valid(reg_request->wiphy_idx))
 		wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
@@ -1585,6 +1595,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
 	if (r == -EALREADY && wiphy && wiphy->strict_regulatory)
 		wiphy_update_regulatory(wiphy, reg_request->initiator);
 out:
+	spin_unlock(&reg_lock);
 	mutex_unlock(&cfg80211_mutex);
 }
 
@@ -1734,13 +1745,12 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
 }
 EXPORT_SYMBOL(regulatory_hint);
 
+/* Caller must hold reg_lock */
 static bool reg_same_country_ie_hint(struct wiphy *wiphy,
 			u32 country_ie_checksum)
 {
 	struct wiphy *request_wiphy;
 
-	assert_cfg80211_lock();
-
 	if (unlikely(last_request->initiator !=
 	    NL80211_REGDOM_SET_BY_COUNTRY_IE))
 		return false;
@@ -1772,7 +1782,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
 	enum environment_cap env = ENVIRON_ANY;
 	struct regulatory_request *request;
 
-	mutex_lock(&cfg80211_mutex);
+	spin_lock(&reg_lock);
 
 	if (unlikely(!last_request))
 		goto out;
@@ -1883,7 +1893,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
 	request->country_ie_checksum = checksum;
 	request->country_ie_env = env;
 
-	mutex_unlock(&cfg80211_mutex);
+	spin_unlock(&reg_lock);
 
 	queue_regulatory_request(request);
 
@@ -1892,7 +1902,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
 free_rd_out:
 	kfree(rd);
 out:
-	mutex_unlock(&cfg80211_mutex);
+	spin_unlock(&reg_lock);
 }
 EXPORT_SYMBOL(regulatory_hint_11d);
 
@@ -2225,10 +2235,13 @@ int set_regdom(const struct ieee80211_regdomain *rd)
 
 	assert_cfg80211_lock();
 
+	spin_lock(&reg_lock);
+
 	/* Note that this doesn't update the wiphys, this is done below */
 	r = __set_regdom(rd);
 	if (r) {
 		kfree(rd);
+		spin_unlock(&reg_lock);
 		return r;
 	}
 
@@ -2243,6 +2256,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
 
 	nl80211_send_reg_change_event(last_request);
 
+	spin_unlock(&reg_lock);
+
 	return r;
 }
 
@@ -2275,6 +2290,7 @@ int regulatory_init(void)
 
 	spin_lock_init(&reg_requests_lock);
 	spin_lock_init(&reg_pending_beacons_lock);
+	spin_lock_init(&reg_lock);
 
 #ifdef CONFIG_WIRELESS_OLD_REGULATORY
 	cfg80211_regdomain = static_regdom(ieee80211_regdom);
-- 
1.6.0.4


^ permalink raw reply related

* [PATCH 1/2] cfg80211: use goto out on 11d reg hint failure
From: Luis R. Rodriguez @ 2009-07-30  0:46 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1248914792-6010-1-git-send-email-lrodriguez@atheros.com>

This does not change functionality.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---
 net/wireless/reg.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index fb40428..2d1d183 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1774,10 +1774,8 @@ void regulatory_hint_11d(struct wiphy *wiphy,
 
 	mutex_lock(&cfg80211_mutex);
 
-	if (unlikely(!last_request)) {
-		mutex_unlock(&cfg80211_mutex);
-		return;
-	}
+	if (unlikely(!last_request))
+		goto out;
 
 	/* IE len must be evenly divisible by 2 */
 	if (country_ie_len & 0x01)
-- 
1.6.0.4


^ permalink raw reply related

* [PATCH 0/2] wireless: fix 11d lockdep warning
From: Luis R. Rodriguez @ 2009-07-30  0:46 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Luis R. Rodriguez

This fixes the lockdep warning for me. We take a much simpler
approach than that mess I was doing before. cfg80211 stuff will
go later.

Luis R. Rodriguez (2):
  cfg80211: use goto out on 11d reg hint failure
  cfg80211: decouple regulatory variables from cfg80211_mutex

 net/wireless/core.c |    4 +---
 net/wireless/reg.c  |   32 +++++++++++++++++++++++---------
 2 files changed, 24 insertions(+), 12 deletions(-)


^ permalink raw reply

* [PATCH 2/2 v2] mac80211: redefine usage of the mac80211 workqueue
From: Luis R. Rodriguez @ 2009-07-30  0:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Luis R. Rodriguez

The mac80211 workqueue exists to enable mac80211 and drivers
to queue their own work on a single threaded workqueue. mac80211
takes care to flush the workqueue during suspend but we never
really had requirements on drivers for how they should use
the workqueue in consideration for suspend.

We extend mac80211 to document how the mac80211 workqueue should
be used, how it should not be used and finally move raw access to
the workqueue to mac80211 only. Drivers and mac80211 use helpers
to queue work onto the mac80211 workqueue:

  * ieee80211_queue_work()
  * ieee80211_queue_delayed_work()

These helpers will now warn if mac80211 already completed its
suspend cycle and someone is trying to queue work. mac80211
flushes the mac80211 workqueue prior to suspend a few times,
but we haven't taken the care to ensure drivers won't add more
work after suspend. To help with this we add a warning when
someone tries to add work and mac80211 already completed the
suspend cycle.

Drivers should ensure they cancel any work or delayed work
in the mac80211 stop() callback.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---

I guess I left my valid patch on the other box, was missing
one change on pm.c

 drivers/net/wireless/at76c50x-usb.c         |   10 +++---
 drivers/net/wireless/ath/ar9170/led.c       |   11 ++++--
 drivers/net/wireless/ath/ar9170/main.c      |   26 ++++++++------
 drivers/net/wireless/ath/ath9k/main.c       |   15 ++++----
 drivers/net/wireless/ath/ath9k/virtual.c    |   17 +++++----
 drivers/net/wireless/ath/ath9k/xmit.c       |    2 +-
 drivers/net/wireless/b43/main.c             |    8 ++--
 drivers/net/wireless/b43/phy_common.c       |    2 +-
 drivers/net/wireless/b43/pio.c              |    2 +-
 drivers/net/wireless/b43legacy/main.c       |    8 ++--
 drivers/net/wireless/p54/led.c              |    5 +--
 drivers/net/wireless/p54/main.c             |    2 +-
 drivers/net/wireless/p54/p54spi.c           |    4 +-
 drivers/net/wireless/p54/txrx.c             |    2 +-
 drivers/net/wireless/rt2x00/rt2x00dev.c     |    2 +-
 drivers/net/wireless/rt2x00/rt2x00link.c    |    8 ++--
 drivers/net/wireless/rt2x00/rt2x00mac.c     |    2 +-
 drivers/net/wireless/rtl818x/rtl8187_dev.c  |    2 +-
 drivers/net/wireless/rtl818x/rtl8187_leds.c |   10 +++---
 include/net/mac80211.h                      |   50 ++++++++++++++++++++++----
 net/mac80211/ibss.c                         |    6 ++--
 net/mac80211/ieee80211_i.h                  |    6 +++
 net/mac80211/iface.c                        |    4 +-
 net/mac80211/main.c                         |    8 ++--
 net/mac80211/mesh.c                         |   10 +++---
 net/mac80211/mesh_hwmp.c                    |    4 +-
 net/mac80211/mlme.c                         |   48 ++++++++++++--------------
 net/mac80211/pm.c                           |    4 +-
 net/mac80211/scan.c                         |    8 ++--
 net/mac80211/tx.c                           |    2 +-
 net/mac80211/util.c                         |   41 ++++++++++++++++++++++
 31 files changed, 207 insertions(+), 122 deletions(-)

diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index aff09a1..7218dba 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1875,8 +1875,8 @@ static void at76_dwork_hw_scan(struct work_struct *work)
 	/* FIXME: add maximum time for scan to complete */
 
 	if (ret != CMD_STATUS_COMPLETE) {
-		queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
-				   SCAN_POLL_INTERVAL);
+		ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
+					     SCAN_POLL_INTERVAL);
 		mutex_unlock(&priv->mtx);
 		return;
 	}
@@ -1937,8 +1937,8 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
 		goto exit;
 	}
 
-	queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
-			   SCAN_POLL_INTERVAL);
+	ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
+				     SCAN_POLL_INTERVAL);
 
 exit:
 	mutex_unlock(&priv->mtx);
@@ -2027,7 +2027,7 @@ static void at76_configure_filter(struct ieee80211_hw *hw,
 	} else
 		return;
 
-	queue_work(hw->workqueue, &priv->work_set_promisc);
+	ieee80211_queue_work(hw, &priv->work_set_promisc);
 }
 
 static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c
index 63fda6c..86c4e79 100644
--- a/drivers/net/wireless/ath/ar9170/led.c
+++ b/drivers/net/wireless/ath/ar9170/led.c
@@ -90,9 +90,12 @@ static void ar9170_update_leds(struct work_struct *work)
 	ar9170_set_leds_state(ar, led_val);
 	mutex_unlock(&ar->mutex);
 
-	if (rerun)
-		queue_delayed_work(ar->hw->workqueue, &ar->led_work,
-				   msecs_to_jiffies(blink_delay));
+	if (!rerun)
+		return;
+
+	ieee80211_queue_delayed_work(ar->hw,
+				     &ar->led_work,
+				     msecs_to_jiffies(blink_delay));
 }
 
 static void ar9170_led_brightness_set(struct led_classdev *led,
@@ -110,7 +113,7 @@ static void ar9170_led_brightness_set(struct led_classdev *led,
 	}
 
 	if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
-		queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10);
+		ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10);
 }
 
 static int ar9170_register_led(struct ar9170 *ar, int i, char *name,
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 099ed3c..4fc389a 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -595,10 +595,12 @@ static void ar9170_tx_janitor(struct work_struct *work)
 
 	ar9170_tx_fake_ampdu_status(ar);
 
-	if (resched)
-		queue_delayed_work(ar->hw->workqueue,
-				   &ar->tx_janitor,
-				   msecs_to_jiffies(AR9170_JANITOR_DELAY));
+	if (!resched)
+		return;
+
+	ieee80211_queue_delayed_work(ar->hw,
+				     &ar->tx_janitor,
+				     msecs_to_jiffies(AR9170_JANITOR_DELAY));
 }
 
 void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
@@ -648,7 +650,7 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
 		 * pre-TBTT event
 		 */
 		if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
-			queue_work(ar->hw->workqueue, &ar->beacon_work);
+			ieee80211_queue_work(ar->hw, &ar->beacon_work);
 		break;
 
 	case 0xc2:
@@ -1825,10 +1827,12 @@ static void ar9170_tx(struct ar9170 *ar)
 		}
 	}
 
-	if (schedule_garbagecollector)
-		queue_delayed_work(ar->hw->workqueue,
-				   &ar->tx_janitor,
-				   msecs_to_jiffies(AR9170_JANITOR_DELAY));
+	if (!schedule_garbagecollector)
+		return;
+
+	ieee80211_queue_delayed_work(ar->hw,
+				     &ar->tx_janitor,
+				     msecs_to_jiffies(AR9170_JANITOR_DELAY));
 }
 
 static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb)
@@ -2157,7 +2161,7 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
 	}
 
 	if (likely(IS_STARTED(ar)))
-		queue_work(ar->hw->workqueue, &ar->filter_config_work);
+		ieee80211_queue_work(ar->hw, &ar->filter_config_work);
 }
 
 static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
@@ -2415,7 +2419,7 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw,
 	}
 
 	if (IS_STARTED(ar) && ar->filter_changed)
-		queue_work(ar->hw->workqueue, &ar->filter_config_work);
+		ieee80211_queue_work(ar->hw, &ar->filter_config_work);
 }
 
 static int ar9170_get_stats(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index cf44623..292ac2b 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -973,10 +973,11 @@ static void ath_led_blink_work(struct work_struct *work)
 		ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
 				  (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
 
-	queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work,
-			   (sc->sc_flags & SC_OP_LED_ON) ?
-			   msecs_to_jiffies(sc->led_off_duration) :
-			   msecs_to_jiffies(sc->led_on_duration));
+	ieee80211_queue_delayed_work(sc->hw,
+				     &sc->ath_led_blink_work,
+				     (sc->sc_flags & SC_OP_LED_ON) ?
+					msecs_to_jiffies(sc->led_off_duration) :
+					msecs_to_jiffies(sc->led_on_duration));
 
 	sc->led_on_duration = sc->led_on_cnt ?
 			max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
@@ -1013,8 +1014,8 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
 	case LED_FULL:
 		if (led->led_type == ATH_LED_ASSOC) {
 			sc->sc_flags |= SC_OP_LED_ASSOCIATED;
-			queue_delayed_work(sc->hw->workqueue,
-					   &sc->ath_led_blink_work, 0);
+			ieee80211_queue_delayed_work(sc->hw,
+						     &sc->ath_led_blink_work, 0);
 		} else if (led->led_type == ATH_LED_RADIO) {
 			ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
 			sc->sc_flags |= SC_OP_LED_ON;
@@ -1972,7 +1973,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
 
 	ieee80211_wake_queues(hw);
 
-	queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, 0);
+	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
 
 mutex_unlock:
 	mutex_unlock(&sc->mutex);
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index e1d419e..19b88f8 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -351,7 +351,7 @@ void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 			 * Drop from tasklet to work to allow mutex for channel
 			 * change.
 			 */
-			queue_work(aphy->sc->hw->workqueue,
+			ieee80211_queue_work(aphy->sc->hw,
 				   &aphy->sc->chan_work);
 		}
 	}
@@ -367,7 +367,7 @@ static void ath9k_mark_paused(struct ath_wiphy *aphy)
 	struct ath_softc *sc = aphy->sc;
 	aphy->state = ATH_WIPHY_PAUSED;
 	if (!__ath9k_wiphy_pausing(sc))
-		queue_work(sc->hw->workqueue, &sc->chan_work);
+		ieee80211_queue_work(sc->hw, &sc->chan_work);
 }
 
 static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
@@ -521,7 +521,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
 			spin_unlock_bh(&sc->wiphy_lock);
 			ath_radio_disable(sc);
 			ath_radio_enable(sc);
-			queue_work(aphy->sc->hw->workqueue,
+			ieee80211_queue_work(aphy->sc->hw,
 				   &aphy->sc->chan_work);
 			return -EBUSY; /* previous select still in progress */
 		}
@@ -541,7 +541,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
 
 	if (now) {
 		/* Ready to request channel change immediately */
-		queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work);
+		ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work);
 	}
 
 	/*
@@ -648,8 +648,9 @@ try_again:
 		       "change\n");
 	}
 
-	queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
-			   sc->wiphy_scheduler_int);
+	ieee80211_queue_delayed_work(sc->hw,
+				     &sc->wiphy_work,
+				     sc->wiphy_scheduler_int);
 }
 
 void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
@@ -657,8 +658,8 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
 	cancel_delayed_work_sync(&sc->wiphy_work);
 	sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int);
 	if (sc->wiphy_scheduler_int)
-		queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
-				   sc->wiphy_scheduler_int);
+		ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work,
+					     sc->wiphy_scheduler_int);
 }
 
 /* caller must hold wiphy_lock */
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index b7806e2..87762da 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2063,7 +2063,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
 		ath_reset(sc, false);
 	}
 
-	queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work,
+	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
 			msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
 }
 
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 3f4360a..f985938 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1654,7 +1654,7 @@ static void b43_update_templates(struct b43_wl *wl)
 	wl->current_beacon = beacon;
 	wl->beacon0_uploaded = 0;
 	wl->beacon1_uploaded = 0;
-	queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
+	ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
 }
 
 static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
@@ -2914,7 +2914,7 @@ out_requeue:
 		delay = msecs_to_jiffies(50);
 	else
 		delay = round_jiffies_relative(HZ * 15);
-	queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
+	ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
 out:
 	mutex_unlock(&wl->mutex);
 }
@@ -2925,7 +2925,7 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev)
 
 	dev->periodic_state = 0;
 	INIT_DELAYED_WORK(work, b43_periodic_work_handler);
-	queue_delayed_work(dev->wl->hw->workqueue, work, 0);
+	ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
 }
 
 /* Check if communication with the device works correctly. */
@@ -4871,7 +4871,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
 	if (b43_status(dev) < B43_STAT_INITIALIZED)
 		return;
 	b43info(dev->wl, "Controller RESET (%s) ...\n", reason);
-	queue_work(dev->wl->hw->workqueue, &dev->restart_work);
+	ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 6d24162..f537bfe 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -352,7 +352,7 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
 
 	/* We must adjust the transmission power in hardware.
 	 * Schedule b43_phy_txpower_adjust_work(). */
-	queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work);
+	ieee80211_queue_work(dev->wl->hw, &dev->wl->txpower_adjust_work);
 }
 
 int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 69138e8..73c047d 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -783,7 +783,7 @@ void b43_pio_rx(struct b43_pio_rxqueue *q)
 {
 	/* Due to latency issues we must run the RX path in
 	 * a workqueue to be able to schedule between packets. */
-	queue_work(q->dev->wl->hw->workqueue, &q->rx_work);
+	ieee80211_queue_work(q->dev->wl->hw, &q->rx_work);
 }
 
 static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index c4973c1..b143559 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1252,7 +1252,7 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl)
 	wl->current_beacon = beacon;
 	wl->beacon0_uploaded = 0;
 	wl->beacon1_uploaded = 0;
-	queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
+	ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
 }
 
 static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
@@ -2300,7 +2300,7 @@ out_requeue:
 		delay = msecs_to_jiffies(50);
 	else
 		delay = round_jiffies_relative(HZ * 15);
-	queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
+	ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
 out:
 	mutex_unlock(&wl->mutex);
 }
@@ -2311,7 +2311,7 @@ static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev)
 
 	dev->periodic_state = 0;
 	INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler);
-	queue_delayed_work(dev->wl->hw->workqueue, work, 0);
+	ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
 }
 
 /* Validate access to the chip (SHM) */
@@ -3885,7 +3885,7 @@ void b43legacy_controller_restart(struct b43legacy_wldev *dev,
 	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
 		return;
 	b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason);
-	queue_work(dev->wl->hw->workqueue, &dev->restart_work);
+	ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c
index c00115b..9575ac0 100644
--- a/drivers/net/wireless/p54/led.c
+++ b/drivers/net/wireless/p54/led.c
@@ -61,7 +61,7 @@ static void p54_update_leds(struct work_struct *work)
 			wiphy_name(priv->hw->wiphy), err);
 
 	if (rerun)
-		queue_delayed_work(priv->hw->workqueue, &priv->led_work,
+		ieee80211_queue_delayed_work(priv->hw, &priv->led_work,
 			msecs_to_jiffies(blink_delay));
 }
 
@@ -78,8 +78,7 @@ static void p54_led_brightness_set(struct led_classdev *led_dev,
 
 	if ((brightness) && (led->registered)) {
 		led->toggled++;
-		queue_delayed_work(priv->hw->workqueue, &priv->led_work,
-				   HZ/10);
+		ieee80211_queue_delayed_work(priv->hw, &priv->led_work, HZ/10);
 	}
 }
 
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 955f6d7..a0d0e72 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -180,7 +180,7 @@ static int p54_start(struct ieee80211_hw *dev)
 		goto out;
 	}
 
-	queue_delayed_work(dev->workqueue, &priv->work, 0);
+	ieee80211_queue_delayed_work(dev, &priv->work, 0);
 
 	priv->softled_state = 0;
 	err = p54_set_leds(priv);
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index eef5329..05458d9 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -391,7 +391,7 @@ static irqreturn_t p54spi_interrupt(int irq, void *config)
 	struct spi_device *spi = config;
 	struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
 
-	queue_work(priv->hw->workqueue, &priv->work);
+	ieee80211_queue_work(priv->hw, &priv->work);
 
 	return IRQ_HANDLED;
 }
@@ -479,7 +479,7 @@ static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 	list_add_tail(&di->tx_list, &priv->tx_pending);
 	spin_unlock_irqrestore(&priv->tx_lock, flags);
 
-	queue_work(priv->hw->workqueue, &priv->work);
+	ieee80211_queue_work(priv->hw, &priv->work);
 }
 
 static void p54spi_work(struct work_struct *work)
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index c32a0d2..704685f 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -380,7 +380,7 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
 
 	ieee80211_rx_irqsafe(priv->hw, skb);
 
-	queue_delayed_work(priv->hw->workqueue, &priv->work,
+	ieee80211_queue_delayed_work(priv->hw, &priv->work,
 			   msecs_to_jiffies(P54_STATISTICS_UPDATE));
 
 	return -1;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 658a63b..b717afb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -215,7 +215,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
 						   rt2x00lib_beacondone_iter,
 						   rt2x00dev);
 
-	queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
+	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 7991568..9178316 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -351,8 +351,8 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
 
 	rt2x00link_reset_tuner(rt2x00dev, false);
 
-	queue_delayed_work(rt2x00dev->hw->workqueue,
-			   &link->work, LINK_TUNE_INTERVAL);
+	ieee80211_queue_delayed_work(rt2x00dev->hw,
+				     &link->work, LINK_TUNE_INTERVAL);
 }
 
 void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
@@ -461,8 +461,8 @@ static void rt2x00link_tuner(struct work_struct *work)
 	 * Increase tuner counter, and reschedule the next link tuner run.
 	 */
 	link->count++;
-	queue_delayed_work(rt2x00dev->hw->workqueue,
-			   &link->work, LINK_TUNE_INTERVAL);
+	ieee80211_queue_delayed_work(rt2x00dev->hw,
+				     &link->work, LINK_TUNE_INTERVAL);
 }
 
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index e92c8f9..81febdf 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -431,7 +431,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
 	if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
 		rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
 	else
-		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+		ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->filter_work);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
 
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index c9b9dbe..53f57dc 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -220,7 +220,7 @@ static void rtl8187_tx_cb(struct urb *urb)
 		 * reading a register in the device. We are in interrupt mode
 		 * here, thus queue the skb and finish on a work queue. */
 		skb_queue_tail(&priv->b_tx_status.queue, skb);
-		queue_delayed_work(hw->workqueue, &priv->work, 0);
+		ieee80211_queue_delayed_work(hw, &priv->work, 0);
 	}
 }
 
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c
index cf9f899..a6cfb7e 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_leds.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c
@@ -108,11 +108,11 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
 	struct rtl8187_priv *priv = hw->priv;
 
 	if (brightness == LED_OFF) {
-		queue_delayed_work(hw->workqueue, &priv->led_off, 0);
+		ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
 		/* The LED is off for 1/20 sec so that it just blinks. */
-		queue_delayed_work(hw->workqueue, &priv->led_on, HZ / 20);
+		ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20);
 	} else
-		queue_delayed_work(hw->workqueue, &priv->led_on, 0);
+		ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
 }
 
 static int rtl8187_register_led(struct ieee80211_hw *dev,
@@ -193,7 +193,7 @@ void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
 	err = rtl8187_register_led(dev, &priv->led_rx, name,
 			 ieee80211_get_rx_led_name(dev), ledpin);
 	if (!err) {
-		queue_delayed_work(dev->workqueue, &priv->led_on, 0);
+		ieee80211_queue_delayed_work(dev, &priv->led_on, 0);
 		return;
 	}
 	/* registration of RX LED failed - unregister TX */
@@ -209,7 +209,7 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev)
 	struct rtl8187_priv *priv = dev->priv;
 
 	/* turn the LED off before exiting */
-	queue_delayed_work(dev->workqueue, &priv->led_off, 0);
+	ieee80211_queue_delayed_work(dev, &priv->led_off, 0);
 	cancel_delayed_work_sync(&priv->led_off);
 	cancel_delayed_work_sync(&priv->led_on);
 	rtl8187_unregister_led(&priv->led_rx);
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d4e09a0..5ed93f4 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -73,6 +73,21 @@
  */
 
 /**
+ * DOC: mac80211 workqueue
+ *
+ * mac80211 provides its own workqueue for drivers and internal mac80211 use.
+ * The workqueue is a single threaded workqueue and can only be accessed by
+ * helpers for sanity checking. Drivers must ensure all work added onto the
+ * mac80211 workqueue should be cancelled on the driver stop() callback.
+ *
+ * mac80211 will flushed the workqueue upon interface removal and during
+ * suspend.
+ *
+ * All work performed on the mac80211 workqueue must not acquire the RTNL lock.
+ *
+ */
+
+/**
  * enum ieee80211_max_queues - maximum number of queues
  *
  * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
@@ -913,12 +928,6 @@ enum ieee80211_hw_flags {
  *
  * @conf: &struct ieee80211_conf, device configuration, don't use.
  *
- * @workqueue: single threaded workqueue available for driver use,
- *	allocated by mac80211 on registration and flushed when an
- *	interface is removed.
- *	NOTICE: All work performed on this workqueue must not
- *	acquire the RTNL lock.
- *
  * @priv: pointer to private area that was allocated for driver use
  *	along with this structure.
  *
@@ -954,7 +963,6 @@ enum ieee80211_hw_flags {
 struct ieee80211_hw {
 	struct ieee80211_conf conf;
 	struct wiphy *wiphy;
-	struct workqueue_struct *workqueue;
 	const char *rate_control_algorithm;
 	void *priv;
 	u32 flags;
@@ -1301,7 +1309,8 @@ enum ieee80211_ampdu_mlme_action {
  *	is disabled. This should turn off the hardware (at least
  *	it must turn off frame reception.)
  *	May be called right after add_interface if that rejects
- *	an interface.
+ *	an interface. If you added any work onto the mac80211 workqueue
+ *	you should ensure to cancel it on this callback.
  *	Must be implemented.
  *
  * @add_interface: Called when a netdevice attached to the hardware is
@@ -1928,6 +1937,31 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
 						void *data);
 
 /**
+ * ieee80211_queue_work - add work onto the mac80211 workqueue
+ *
+ * Drivers and mac80211 use this to add work onto the mac80211 workqueue.
+ * This helper ensures drivers are not queueing work when they should not be.
+ *
+ * @hw: the hardware struct for the interface we are adding work for
+ * @work: the work we want to add onto the mac80211 workqueue
+ */
+void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work);
+
+/**
+ * ieee80211_queue_delayed_work - add work onto the mac80211 workqueue
+ *
+ * Drivers and mac80211 use this to queue delayed work onto the mac80211
+ * workqueue.
+ *
+ * @hw: the hardware struct for the interface we are adding work for
+ * @dwork: delayable work to queue onto the mac80211 workqueue
+ * @delay: number of jiffies to wait before queueing
+ */
+void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
+				  struct delayed_work *dwork,
+				  unsigned long delay);
+
+/**
  * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
  * @hw: pointer as obtained from ieee80211_alloc_hw().
  * @ra: receiver address of the BA session recipient
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 6e3cca6..920ec87 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -781,7 +781,7 @@ static void ieee80211_ibss_timer(unsigned long data)
 	}
 
 	set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
-	queue_work(local->hw.workqueue, &ifibss->work);
+	ieee80211_queue_work(&local->hw, &ifibss->work);
 }
 
 #ifdef CONFIG_PM
@@ -853,7 +853,7 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
 	case IEEE80211_STYPE_PROBE_REQ:
 	case IEEE80211_STYPE_AUTH:
 		skb_queue_tail(&sdata->u.ibss.skb_queue, skb);
-		queue_work(local->hw.workqueue, &sdata->u.ibss.work);
+		ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
 		return RX_QUEUED;
 	}
 
@@ -912,7 +912,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
 	ieee80211_recalc_idle(sdata->local);
 
 	set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
-	queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work);
 
 	return 0;
 }
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index aec6853..316825b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -614,6 +614,12 @@ struct ieee80211_local {
 
 	const struct ieee80211_ops *ops;
 
+	/*
+	 * private workqueue to mac80211. mac80211 makes this accessible
+	 * via ieee80211_queue_work()
+	 */
+	struct workqueue_struct *workqueue;
+
 	unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
 	/* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
 	spinlock_t queue_stop_reason_lock;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index a83087f..8c1284d 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -312,7 +312,7 @@ static int ieee80211_open(struct net_device *dev)
 	 * to fix this.
 	 */
 	if (sdata->vif.type == NL80211_IFTYPE_STATION)
-		queue_work(local->hw.workqueue, &sdata->u.mgd.work);
+		ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
 
 	netif_tx_start_all_queues(dev);
 
@@ -551,7 +551,7 @@ static int ieee80211_stop(struct net_device *dev)
 
 		ieee80211_led_radio(local, false);
 
-		flush_workqueue(local->hw.workqueue);
+		flush_workqueue(local->workqueue);
 
 		tasklet_disable(&local->tx_pending_tasklet);
 		tasklet_disable(&local->tasklet);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 5e76dd1..22e0738 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -821,9 +821,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	if (hw->queues > IEEE80211_MAX_QUEUES)
 		hw->queues = IEEE80211_MAX_QUEUES;
 
-	local->hw.workqueue =
+	local->workqueue =
 		create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
-	if (!local->hw.workqueue) {
+	if (!local->workqueue) {
 		result = -ENOMEM;
 		goto fail_workqueue;
 	}
@@ -913,7 +913,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	sta_info_stop(local);
  fail_sta_info:
 	debugfs_hw_del(local);
-	destroy_workqueue(local->hw.workqueue);
+	destroy_workqueue(local->workqueue);
  fail_workqueue:
 	wiphy_unregister(local->hw.wiphy);
  fail_wiphy_register:
@@ -955,7 +955,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 	skb_queue_purge(&local->skb_queue);
 	skb_queue_purge(&local->skb_queue_unreliable);
 
-	destroy_workqueue(local->hw.workqueue);
+	destroy_workqueue(local->workqueue);
 	wiphy_unregister(local->hw.wiphy);
 	ieee80211_wep_free(local);
 	ieee80211_led_exit(local);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 9a38269..2f4f518 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -54,7 +54,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
 		return;
 	}
 
-	queue_work(local->hw.workqueue, &ifmsh->work);
+	ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
 }
 
 /**
@@ -357,7 +357,7 @@ static void ieee80211_mesh_path_timer(unsigned long data)
 		return;
 	}
 
-	queue_work(local->hw.workqueue, &ifmsh->work);
+	ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
 }
 
 struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
@@ -471,7 +471,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 	struct ieee80211_local *local = sdata->local;
 
 	ifmsh->housekeeping = true;
-	queue_work(local->hw.workqueue, &ifmsh->work);
+	ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
 	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
 						BSS_CHANGED_BEACON_ENABLED);
 }
@@ -619,7 +619,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list)
 		if (ieee80211_vif_is_mesh(&sdata->vif))
-			queue_work(local->hw.workqueue, &sdata->u.mesh.work);
+			ieee80211_queue_work(local->hw.workqueue, &sdata->u.mesh.work);
 	rcu_read_unlock();
 }
 
@@ -692,7 +692,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
 	case IEEE80211_STYPE_PROBE_RESP:
 	case IEEE80211_STYPE_BEACON:
 		skb_queue_tail(&ifmsh->skb_queue, skb);
-		queue_work(local->hw.workqueue, &ifmsh->work);
+		ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
 		return RX_QUEUED;
 	}
 
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index e93c37e..11ab71a 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -660,14 +660,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
 	spin_unlock(&ifmsh->mesh_preq_queue_lock);
 
 	if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
-		queue_work(sdata->local->hw.workqueue, &ifmsh->work);
+		ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work);
 
 	else if (time_before(jiffies, ifmsh->last_preq)) {
 		/* avoid long wait if did not send preqs for a long time
 		 * and jiffies wrapped around
 		 */
 		ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
-		queue_work(sdata->local->hw.workqueue, &ifmsh->work);
+		ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work);
 	} else
 		mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
 						min_preq_int_jiff(sdata));
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ee83125..0779ba1 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -565,7 +565,7 @@ static void ieee80211_chswitch_timer(unsigned long data)
 		return;
 	}
 
-	queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
+	ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
 }
 
 void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
@@ -597,7 +597,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 	sdata->local->csa_channel = new_ch;
 
 	if (sw_elem->count <= 1) {
-		queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
+		ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
 	} else {
 		ieee80211_stop_queues_by_reason(&sdata->local->hw,
 					IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -763,7 +763,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
 	if (local->quiescing || local->suspended)
 		return;
 
-	queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
+	ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
 }
 
 /* MLME */
@@ -950,7 +950,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
 		 * due to work needing to be done. Hence, queue the STAs work
 		 * again for that.
 		 */
-		queue_work(local->hw.workqueue, &ifmgd->work);
+		ieee80211_queue_work(&local->hw, &ifmgd->work);
 		return RX_MGMT_CFG80211_AUTH_TO;
 	}
 
@@ -995,7 +995,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
 		 * due to work needing to be done. Hence, queue the STAs work
 		 * again for that.
 		 */
-		queue_work(local->hw.workqueue, &ifmgd->work);
+		ieee80211_queue_work(&local->hw, &ifmgd->work);
 		return RX_MGMT_CFG80211_AUTH_TO;
 	}
 
@@ -1124,7 +1124,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata,
 		 * due to work needing to be done. Hence, queue the STAs work
 		 * again for that.
 		 */
-		queue_work(local->hw.workqueue, &ifmgd->work);
+		ieee80211_queue_work(&local->hw, &ifmgd->work);
 		return RX_MGMT_CFG80211_ASSOC_TO;
 	}
 
@@ -1232,8 +1232,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
 {
 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 
-	queue_work(sdata->local->hw.workqueue,
-		   &sdata->u.mgd.beacon_loss_work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
 }
 EXPORT_SYMBOL(ieee80211_beacon_loss);
 
@@ -1888,7 +1887,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
 	case IEEE80211_STYPE_DISASSOC:
 	case IEEE80211_STYPE_ACTION:
 		skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
-		queue_work(local->hw.workqueue, &sdata->u.mgd.work);
+		ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
 		return RX_QUEUED;
 	}
 
@@ -2026,7 +2025,7 @@ static void ieee80211_sta_timer(unsigned long data)
 		return;
 	}
 
-	queue_work(local->hw.workqueue, &ifmgd->work);
+	ieee80211_queue_work(&local->hw, &ifmgd->work);
 }
 
 static void ieee80211_sta_work(struct work_struct *work)
@@ -2051,13 +2050,11 @@ static void ieee80211_sta_work(struct work_struct *work)
 		return;
 
 	/*
-	 * Nothing should have been stuffed into the workqueue during
-	 * the suspend->resume cycle. If this WARN is seen then there
-	 * is a bug with either the driver suspend or something in
-	 * mac80211 stuffing into the workqueue which we haven't yet
-	 * cleared during mac80211's suspend cycle.
+	 * ieee80211_queue_work() should have picked up most cases,
+	 * here we'll pick the the rest.
 	 */
-	if (WARN_ON(local->suspended))
+	if (WARN(local->suspended, "STA MLME work scheduled while "
+		 "going to suspend\n"))
 		return;
 
 	ifmgd = &sdata->u.mgd;
@@ -2113,9 +2110,9 @@ static void ieee80211_sta_work(struct work_struct *work)
 		mutex_unlock(&ifmgd->mtx);
 
 		if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
-			queue_delayed_work(local->hw.workqueue,
-					   &local->scan_work,
-					   round_jiffies_relative(0));
+			ieee80211_queue_delayed_work(&local->hw,
+						     &local->scan_work,
+						     round_jiffies_relative(0));
 		return;
 	}
 
@@ -2196,8 +2193,7 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
 	if (local->quiescing)
 		return;
 
-	queue_work(sdata->local->hw.workqueue,
-		   &sdata->u.mgd.beacon_loss_work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
 }
 
 static void ieee80211_sta_conn_mon_timer(unsigned long data)
@@ -2210,7 +2206,7 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data)
 	if (local->quiescing)
 		return;
 
-	queue_work(local->hw.workqueue, &ifmgd->monitor_work);
+	ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
 }
 
 static void ieee80211_sta_monitor_work(struct work_struct *work)
@@ -2229,10 +2225,10 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
 					IEEE80211_STA_CONNECTION_POLL);
 
 		/* let's probe the connection once */
-		queue_work(sdata->local->hw.workqueue,
+		ieee80211_queue_work(&sdata->local->hw,
 			   &sdata->u.mgd.monitor_work);
 		/* and do all the other regular work too */
-		queue_work(sdata->local->hw.workqueue,
+		ieee80211_queue_work(&sdata->local->hw,
 			   &sdata->u.mgd.work);
 	}
 }
@@ -2393,7 +2389,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 	list_add(&wk->list, &sdata->u.mgd.work_list);
 	mutex_unlock(&ifmgd->mtx);
 
-	queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
 	return 0;
 }
 
@@ -2467,7 +2463,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	else
 		ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
 
-	queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
 
 	err = 0;
 
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index e79aa7e..09c9c62 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -25,7 +25,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
 	/* make quiescing visible to timers everywhere */
 	mb();
 
-	flush_workqueue(local->hw.workqueue);
+	flush_workqueue(local->workqueue);
 
 	/* Don't try to run timers while suspended. */
 	del_timer_sync(&local->sta_cleanup);
@@ -116,7 +116,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
 	 * shouldn't be doing (or cancel everything in the
 	 * stop callback) that but better safe than sorry.
 	 */
-	flush_workqueue(local->hw.workqueue);
+	flush_workqueue(local->workqueue);
 
 	local->suspended = true;
 	/* need suspended to be visible before quiescing is false */
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 4573100..244f53f 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -385,8 +385,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
 	spin_unlock_bh(&local->filter_lock);
 
 	/* TODO: start scan as soon as all nullfunc frames are ACKed */
-	queue_delayed_work(local->hw.workqueue, &local->scan_work,
-			   IEEE80211_CHANNEL_TIME);
+	ieee80211_queue_delayed_work(&local->hw,
+				     &local->scan_work,
+				     IEEE80211_CHANNEL_TIME);
 
 	return 0;
 }
@@ -715,8 +716,7 @@ void ieee80211_scan_work(struct work_struct *work)
 		}
 	} while (next_delay == 0);
 
-	queue_delayed_work(local->hw.workqueue, &local->scan_work,
-			   next_delay);
+	ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
 }
 
 int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 9b64f1b..d265d6f 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1399,7 +1399,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
 		if (local->hw.conf.flags & IEEE80211_CONF_PS) {
 			ieee80211_stop_queues_by_reason(&local->hw,
 					IEEE80211_QUEUE_STOP_REASON_PS);
-			queue_work(local->hw.workqueue,
+			ieee80211_queue_work(&local->hw,
 					&local->dynamic_ps_disable_work);
 		}
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 988a2b8..e006fa6 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -511,6 +511,46 @@ void ieee80211_iterate_active_interfaces_atomic(
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
 
+/*
+ * Nothing should have been stuffed into the workqueue during
+ * the suspend->resume cycle. If this WARN is seen then there
+ * is a bug with either the driver suspend or something in
+ * mac80211 stuffing into the workqueue which we haven't yet
+ * cleared during mac80211's suspend cycle.
+ */
+static bool ieee80211_can_queue_work(struct ieee80211_local *local)
+{
+        if (WARN(local->suspended, "queueing ieee80211 work while "
+		 "going to suspend\n"))
+                return false;
+
+	return true;
+}
+
+void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	if (!ieee80211_can_queue_work(local))
+		return;
+
+	queue_work(local->workqueue, work);
+}
+EXPORT_SYMBOL(ieee80211_queue_work);
+
+void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
+				  struct delayed_work *dwork,
+				  unsigned long delay)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	if (!ieee80211_can_queue_work(local))
+		return;
+
+	queue_delayed_work(local->workqueue, dwork, delay);
+}
+EXPORT_SYMBOL(ieee80211_queue_delayed_work);
+
 void ieee802_11_parse_elems(u8 *start, size_t len,
 			    struct ieee802_11_elems *elems)
 {
@@ -1113,3 +1153,4 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 #endif
 	return 0;
 }
+
-- 
1.6.0.4


^ permalink raw reply related

* Re: [PATCH] mac80211: use beacons for connection monitoring
From: Ben Greear @ 2009-07-29 22:10 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Reinette Chatre, linville, linux-wireless
In-Reply-To: <1248903902.8925.1.camel@johannes.local>

On 07/29/2009 02:45 PM, Johannes Berg wrote:
> On Wed, 2009-07-29 at 14:32 -0700, Reinette Chatre wrote:
>> From: Reinette Chatre<reinette.chatre@intel.com>
>>
>> The connection monitor currently relies on probe requests paired
>> with probe responses to ensure that a connection is alive. This is
>> fragile in some environments where probe responses can get lost.
>> When we receive beacons we can also consider the connection to be
>> alive, so cancel connection poll instance when we receive a beacon.
>>
>> The debug message "cancelling probereq poll due to a received beacon"
>> is removed as part of this change as this case is hit very often after
>> the above change and debug log receives significant number of these messages.
>
> Not doing that was actually intentional -- we want to know whether or
> not the connection is working both ways, not just whether we can receive
> frames. This can certainly be improved, but I'm not sure this is the
> best approach.
>
> johannes


While poking in this code, I think I found a logic bug:

In mlme.c ieee80211_associated, there are several places that do a mod-timer,
and then goto out.  But, out: just does a mod timer again blindly.

Am I missing something, or is this just wrong?

....
		mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
		goto out;
	}

	if (time_after(jiffies, last_rx + IEEE80211_PROBE_IDLE_TIME)) {
		ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
		mutex_lock(&local->iflist_mtx);
		ieee80211_recalc_ps(local, -1);
		mutex_unlock(&local->iflist_mtx);
		ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
					 ifmgd->ssid_len, NULL, 0);
	}

  out:
	if (!disassoc)
		mod_timer(&ifmgd->timer,
			  jiffies + IEEE80211_MONITORING_INTERVAL);


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: [Linux Wireless] Update of "en/users/Download" by ReinetteChatre
From: Luis R. Rodriguez @ 2009-07-29 22:04 UTC (permalink / raw)
  To: reinette chatre, rmacko72; +Cc: linux-wireless
In-Reply-To: <1248904631.1216.1027.camel@rc-desk>

On Wed, Jul 29, 2009 at 2:57 PM, reinette
chatre<reinette.chatre@intel.com> wrote:
> On Wed, 2009-07-29 at 14:53 -0700, Luis R. Rodriguez wrote:
>> On Wed, Jul 29, 2009 at 2:45 PM, Linux
>> Wireless<johannes@sipsolutions.net> wrote:
>> > Dear Wiki user,
>> >
>> > You have subscribed to a wiki page or wiki category on "Linux Wireless" for change notification.
>> >
>> > The "en/users/Download" page has been changed by ReinetteChatre:
>> > http://wireless.kernel.org/en/users/Download?action=diff&rev1=93&rev2=94
>> >
>> >  }}}
>> >  '''Install''':
>> >
>> > - We use the updates/ directory so your distribution's drivers are left intact.
>> > + We use the updates/ directory so your distribution's drivers are left intact. By default depmod will search this directory first, but if you find that it does not then check that your depmod.conf file lists the search order correctly with ''updates'' appearing first (before ''built-in'').
>>
>> Hm, so compat-wireless now actually checks this for you and if its not
>> there it adds it for you. Was there an issue with a particular user on
>> this?
>
> Yes, a madriva user ran into this problem. See
> http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=2061#c6

Roman, I added a little check for this, specifically since another
user reported the same issue. Did you use bleeding edge
compat-wireless?

The script is in:

scripts/check_depmod

We run this at make install time.

Can you run that manually?

  Luis

^ permalink raw reply

* Re: [Linux Wireless] Update of "en/users/Download" by ReinetteChatre
From: reinette chatre @ 2009-07-29 21:57 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: linux-wireless
In-Reply-To: <43e72e890907291453k444e2d06k864149ddcda8f351@mail.gmail.com>

On Wed, 2009-07-29 at 14:53 -0700, Luis R. Rodriguez wrote:
> On Wed, Jul 29, 2009 at 2:45 PM, Linux
> Wireless<johannes@sipsolutions.net> wrote:
> > Dear Wiki user,
> >
> > You have subscribed to a wiki page or wiki category on "Linux Wireless" for change notification.
> >
> > The "en/users/Download" page has been changed by ReinetteChatre:
> > http://wireless.kernel.org/en/users/Download?action=diff&rev1=93&rev2=94
> >
> >  }}}
> >  '''Install''':
> >
> > - We use the updates/ directory so your distribution's drivers are left intact.
> > + We use the updates/ directory so your distribution's drivers are left intact. By default depmod will search this directory first, but if you find that it does not then check that your depmod.conf file lists the search order correctly with ''updates'' appearing first (before ''built-in'').
> 
> Hm, so compat-wireless now actually checks this for you and if its not
> there it adds it for you. Was there an issue with a particular user on
> this?

Yes, a madriva user ran into this problem. See
http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=2061#c6 


Reinette



^ permalink raw reply

* Re: [Linux Wireless] Update of "en/users/Download" by ReinetteChatre
From: Luis R. Rodriguez @ 2009-07-29 21:53 UTC (permalink / raw)
  To: reinette chatre; +Cc: linux-wireless
In-Reply-To: <20090729214510.31738.90990@cl-1649.ham-01.de.sixxs.net>

On Wed, Jul 29, 2009 at 2:45 PM, Linux
Wireless<johannes@sipsolutions.net> wrote:
> Dear Wiki user,
>
> You have subscribed to a wiki page or wiki category on "Linux Wireless" for change notification.
>
> The "en/users/Download" page has been changed by ReinetteChatre:
> http://wireless.kernel.org/en/users/Download?action=diff&rev1=93&rev2=94
>
>  }}}
>  '''Install''':
>
> - We use the updates/ directory so your distribution's drivers are left intact.
> + We use the updates/ directory so your distribution's drivers are left intact. By default depmod will search this directory first, but if you find that it does not then check that your depmod.conf file lists the search order correctly with ''updates'' appearing first (before ''built-in'').

Hm, so compat-wireless now actually checks this for you and if its not
there it adds it for you. Was there an issue with a particular user on
this?

  Luis

^ permalink raw reply

* Re: [PATCH] mac80211: use beacons for connection monitoring
From: reinette chatre @ 2009-07-29 21:50 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <1248903902.8925.1.camel@johannes.local>

On Wed, 2009-07-29 at 14:45 -0700, Johannes Berg wrote:
> On Wed, 2009-07-29 at 14:32 -0700, Reinette Chatre wrote:
> > From: Reinette Chatre <reinette.chatre@intel.com>
> > 
> > The connection monitor currently relies on probe requests paired
> > with probe responses to ensure that a connection is alive. This is
> > fragile in some environments where probe responses can get lost.
> > When we receive beacons we can also consider the connection to be
> > alive, so cancel connection poll instance when we receive a beacon.
> > 
> > The debug message "cancelling probereq poll due to a received beacon"
> > is removed as part of this change as this case is hit very often after
> > the above change and debug log receives significant number of these messages.
> 
> Not doing that was actually intentional -- we want to know whether or
> not the connection is working both ways, not just whether we can receive
> frames. This can certainly be improved, but I'm not sure this is the
> best approach.

I'd be happy to try out other approaches because my connection is
dropping every few minutes. 

Reinette



^ permalink raw reply

* Re: [PATCH v3] mac80211: redefine usage of the mac80211 workqueue
From: Luis R. Rodriguez @ 2009-07-29 21:13 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <43e72e890907291345u5de674fem7b0769f52a7251c5@mail.gmail.com>

On Wed, Jul 29, 2009 at 1:45 PM, Luis R.
Rodriguez<lrodriguez@atheros.com> wrote:
> On Wed, Jul 29, 2009 at 1:00 PM, John W. Linville<linville@tuxdriver.com> wrote:
>> On Mon, Jul 27, 2009 at 03:21:31PM -0700, Luis R. Rodriguez wrote:
>>> The mac80211 workqueue exists to enable mac80211 and drivers
>>> to queue their own work on a single threaded workqueue. mac80211
>>> takes care to flush the workqueue during suspend but we never
>>> really had requirements on drivers for how they should use
>>> the workqueue in consideration for suspend.
>>>
>>> We extend mac80211 to document how the mac80211 workqueue should
>>> be used, how it should not be used and finally move raw access to
>>> the workqueue to mac80211 only. Drivers and mac80211 use helpers
>>> to queue work onto the mac80211 workqueue:
>>>
>>>   * ieee80211_queue_work()
>>>   * ieee80211_queue_delayed_work()
>>>
>>> These helpers will now warn if mac80211 already completed its
>>> suspend cycle and someone is trying to queue work. mac80211
>>> flushes the mac80211 workqueue prior to suspend a few times,
>>> but we haven't taken the care to ensure drivers won't add more
>>> work after suspend. To help with this we add a warning when
>>> someone tries to add work and mac80211 already completed the
>>> suspend cycle.
>>>
>>> Drivers should ensure they cancel any work or delayed work
>>> in the mac80211 stop() callback.
>>
>> How are they supposed to do that after you've removed workqueue
>> from the ieee80211_hw structure?
>
> They do not refer to the mac80211 workqueue for that, they can cancel
> work using cancel_work_sync(their_foo_work_struct).
>
>> This breaks the compilation of
>> at76c50x-usb.c...
>
> Strange, I thought I tested that, will retest,

Oh ok, sorry about that this requires a patch which I thought I had
sent but it seems I didn't:

at76c50x-usb: remove unneeded flush_workqueue() at usb disconnect

Will send.

  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