* Re: kmemleak reports on wireless-testing master-2009-09-04 + kmemleak tree
From: Luis R. Rodriguez @ 2009-09-04 22:40 UTC (permalink / raw)
To: Catalin Marinas; +Cc: linux-wireless
In-Reply-To: <1252103579.21380.10.camel@pc1117.cambridge.arm.com>
On Fri, Sep 4, 2009 at 3:32 PM, Catalin Marinas<catalin.marinas@arm.com> wrote:
> On Fri, 2009-09-04 at 15:15 -0700, Luis R. Rodriguez wrote:
>> I get these with today's wireless-testing + pulling Catalin's kmemleak
>> tree. I nothing upon bootup, and then after a while I force a scan and
>> get (besides some other acpi stuff):
>>
>> unreferenced object 0xffff880039c7d700 (size 256):
>> comm "events/1", pid 10, jiffies 4295050369
>> hex dump (first 32 bytes):
>> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>> backtrace:
>> [<ffffffff814e9d55>] kmemleak_alloc+0x25/0x60
>> [<ffffffff81118a83>] kmem_cache_alloc_node+0x193/0x200
>> [<ffffffff8141dc6a>] __alloc_skb+0x4a/0x180
>> [<ffffffff814ddb82>] wireless_send_event+0x1f2/0x410
>> [<ffffffffa01b7084>] ___cfg80211_scan_done+0xe4/0x110 [cfg80211]
>> [<ffffffffa01b70d6>] __cfg80211_scan_done+0x26/0x50 [cfg80211]
>> [<ffffffff8106de80>] worker_thread+0x1d0/0x380
>> [<ffffffff81073266>] kthread+0xa6/0xb0
>> [<ffffffff810130ca>] child_rip+0xa/0x20
>> [<ffffffffffffffff>] 0xffffffffffffffff
>
> If you force a few scans, do we still get the same objects reported as
> leaks?
Just tried it, and yes.
Luis
^ permalink raw reply
* Re: kmemleak reports on wireless-testing master-2009-09-04 + kmemleak tree
From: Catalin Marinas @ 2009-09-04 22:32 UTC (permalink / raw)
To: Luis R. Rodriguez; +Cc: linux-wireless
In-Reply-To: <43e72e890909041515s38e7c502kf552a5cf90e99d94@mail.gmail.com>
On Fri, 2009-09-04 at 15:15 -0700, Luis R. Rodriguez wrote:
> I get these with today's wireless-testing + pulling Catalin's kmemleak
> tree. I nothing upon bootup, and then after a while I force a scan and
> get (besides some other acpi stuff):
>
> unreferenced object 0xffff880039c7d700 (size 256):
> comm "events/1", pid 10, jiffies 4295050369
> hex dump (first 32 bytes):
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> backtrace:
> [<ffffffff814e9d55>] kmemleak_alloc+0x25/0x60
> [<ffffffff81118a83>] kmem_cache_alloc_node+0x193/0x200
> [<ffffffff8141dc6a>] __alloc_skb+0x4a/0x180
> [<ffffffff814ddb82>] wireless_send_event+0x1f2/0x410
> [<ffffffffa01b7084>] ___cfg80211_scan_done+0xe4/0x110 [cfg80211]
> [<ffffffffa01b70d6>] __cfg80211_scan_done+0x26/0x50 [cfg80211]
> [<ffffffff8106de80>] worker_thread+0x1d0/0x380
> [<ffffffff81073266>] kthread+0xa6/0xb0
> [<ffffffff810130ca>] child_rip+0xa/0x20
> [<ffffffffffffffff>] 0xffffffffffffffff
If you force a few scans, do we still get the same objects reported as
leaks?
> unreferenced object 0xffff8800322bd000 (size 4096):
> comm "events/1", pid 10, jiffies 4295050369
> hex dump (first 32 bytes):
> 38 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 8...............
> 00 00 01 00 03 00 00 00 43 10 01 00 00 00 00 00 ........C.......
> backtrace:
> [<ffffffff814e9d55>] kmemleak_alloc+0x25/0x60
> [<ffffffff811198fb>] __kmalloc_node_track_caller+0x1ab/0x220
> [<ffffffff8141dc9b>] __alloc_skb+0x7b/0x180
> [<ffffffff814ddb82>] wireless_send_event+0x1f2/0x410
> [<ffffffffa01b7084>] ___cfg80211_scan_done+0xe4/0x110 [cfg80211]
> [<ffffffffa01b70d6>] __cfg80211_scan_done+0x26/0x50 [cfg80211]
> [<ffffffff8106de80>] worker_thread+0x1d0/0x380
> [<ffffffff81073266>] kthread+0xa6/0xb0
> [<ffffffff810130ca>] child_rip+0xa/0x20
> [<ffffffffffffffff>] 0xffffffffffffffff
This is probably referenced from the first one, so we usually need to
look into the first reported leak.
--
Catalin
^ permalink raw reply
* Re: [PATCH] cfg80211: clear cfg80211_inform_bss() from kmemleak reports
From: Catalin Marinas @ 2009-09-04 22:24 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: John W. Linville, Johannes Berg, Luis Rodriguez,
linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org
In-Reply-To: <43e72e890909041458u505ce89tf38743dd6305bf7b@mail.gmail.com>
On Fri, 2009-09-04 at 14:58 -0700, Luis R. Rodriguez wrote:
> On Fri, Sep 4, 2009 at 2:21 PM, Luis R. Rodriguez<lrodriguez@atheros.com> wrote:
>
> > BTW I should not I got this kmemleak report after using the clear
> > command by painting objects black. I'll test it now with your
> > suggested changes.
>
> So I pulled your git://linux-arm.org/linux-2.6 master into my tree and
> didn't even need a 'clear' command now, the output of
> /sys/kernel/debug/kmemleak is empty :), so I suspect you have quite a
> few changes which should help avoid getting false positives.
>
> Will these changes make it for 2.6.32?
The kmemleak branch is planned for the upcoming merging window. I don't
think you need to merge the master branch as it has a lot of
arm-specific code.
--
Catalin
^ permalink raw reply
* kmemleak reports on wireless-testing master-2009-09-04 + kmemleak tree
From: Luis R. Rodriguez @ 2009-09-04 22:15 UTC (permalink / raw)
To: linux-wireless, Catalin Marinas
I get these with today's wireless-testing + pulling Catalin's kmemleak
tree. I nothing upon bootup, and then after a while I force a scan and
get (besides some other acpi stuff):
unreferenced object 0xffff880039c7d700 (size 256):
comm "events/1", pid 10, jiffies 4295050369
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<ffffffff814e9d55>] kmemleak_alloc+0x25/0x60
[<ffffffff81118a83>] kmem_cache_alloc_node+0x193/0x200
[<ffffffff8141dc6a>] __alloc_skb+0x4a/0x180
[<ffffffff814ddb82>] wireless_send_event+0x1f2/0x410
[<ffffffffa01b7084>] ___cfg80211_scan_done+0xe4/0x110 [cfg80211]
[<ffffffffa01b70d6>] __cfg80211_scan_done+0x26/0x50 [cfg80211]
[<ffffffff8106de80>] worker_thread+0x1d0/0x380
[<ffffffff81073266>] kthread+0xa6/0xb0
[<ffffffff810130ca>] child_rip+0xa/0x20
[<ffffffffffffffff>] 0xffffffffffffffff
unreferenced object 0xffff8800322bd000 (size 4096):
comm "events/1", pid 10, jiffies 4295050369
hex dump (first 32 bytes):
38 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 8...............
00 00 01 00 03 00 00 00 43 10 01 00 00 00 00 00 ........C.......
backtrace:
[<ffffffff814e9d55>] kmemleak_alloc+0x25/0x60
[<ffffffff811198fb>] __kmalloc_node_track_caller+0x1ab/0x220
[<ffffffff8141dc9b>] __alloc_skb+0x7b/0x180
[<ffffffff814ddb82>] wireless_send_event+0x1f2/0x410
[<ffffffffa01b7084>] ___cfg80211_scan_done+0xe4/0x110 [cfg80211]
[<ffffffffa01b70d6>] __cfg80211_scan_done+0x26/0x50 [cfg80211]
[<ffffffff8106de80>] worker_thread+0x1d0/0x380
[<ffffffff81073266>] kthread+0xa6/0xb0
[<ffffffff810130ca>] child_rip+0xa/0x20
[<ffffffffffffffff>] 0xffffffffffffffff
Luis
^ permalink raw reply
* Re: [PATCH] cfg80211: clear cfg80211_inform_bss() from kmemleak reports
From: Luis R. Rodriguez @ 2009-09-04 21:58 UTC (permalink / raw)
To: Catalin Marinas, John W. Linville
Cc: Johannes Berg, Luis Rodriguez, linux-kernel@vger.kernel.org,
linux-wireless@vger.kernel.org
In-Reply-To: <43e72e890909041421m243bbea6i95c26ab21dc8732d@mail.gmail.com>
On Fri, Sep 4, 2009 at 2:21 PM, Luis R. Rodriguez<lrodriguez@atheros.com> wrote:
> BTW I should not I got this kmemleak report after using the clear
> command by painting objects black. I'll test it now with your
> suggested changes.
So I pulled your git://linux-arm.org/linux-2.6 master into my tree and
didn't even need a 'clear' command now, the output of
/sys/kernel/debug/kmemleak is empty :), so I suspect you have quite a
few changes which should help avoid getting false positives.
Will these changes make it for 2.6.32?
Luis
^ permalink raw reply
* Re: Atheros Linux wireless drivers home page - and two new driver projects
From: Xavier Bestel @ 2009-09-04 22:00 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: Dan Williams, Witold Sowa, Pavel Roskin, linux-kernel, devel,
Len Widra, Jouni Malinen, linux-wireless, Werner Almesberger,
Stefan Lippers-Hollmann, Nick Kossifidis, Bob Copeland, Greg KH,
rshlinux, b_yogesh_snowy, Michael Renzmann, Stephen Chen,
Paul Fertser, Harald Welte
In-Reply-To: <43e72e890909040951y6a1e639bl771a63389665ca2a@mail.gmail.com>
Le vendredi 04 septembre 2009 à 09:51 -0700, Luis R. Rodriguez a écrit :
> On Fri, Sep 4, 2009 at 9:18 AM, Xavier Bestel<xavier.bestel@free.fr> wrote:
> >
> > On Fri, 2009-09-04 at 12:06 -0400, Pavel Roskin wrote:
> >> On Fri, 2009-09-04 at 13:53 +0200, Xavier Bestel wrote:
> >> > On Thu, 2009-09-03 at 15:54 -0700, Luis R. Rodriguez wrote:
> >> > > I'm pleased to announce the new home page to Atheros Linux wireless drivers:
> >> > >
> >> > > http://wireless.kernel.org/en/users/Drivers/Atheros
> >> >
> >> > ath5k is marked as not master-mode capable. I thought this had been
> >> > fixed for 2.6.31 ?
> >>
> >> The above page makes no such statements. I have fixed
> >> http://wireless.kernel.org/en/users/Drivers/ath5k
> >
> > Right, thanks.
> >
> >> https://madwifi-project.org/wiki/UserDocs/ath5kAccessPoint still needs a
> >> lot of work, or maybe it should be removed as obsolete.
> >
> > Yes, I miss access-point functionality in NetworkManager :)
>
> BTW a GSoC project this year was to add AP support to Network Manager.
> As far I can tell the Witold Sowa finished this so you should be able
> to test this.
Awesome.
> Witold, can you update the wiki page on this project with details as
> to how people can test this?
>
> http://wireless.kernel.org/en/developers/GSoC/2009/Add_AP_Support_to_Network_Manager
>
> Luis
>
^ permalink raw reply
* Re: [PATCH] cfg80211: clear cfg80211_inform_bss() from kmemleak reports
From: Luis R. Rodriguez @ 2009-09-04 21:41 UTC (permalink / raw)
To: Catalin Marinas, John W. Linville
Cc: Johannes Berg, Luis Rodriguez, linux-kernel@vger.kernel.org,
linux-wireless@vger.kernel.org
In-Reply-To: <43e72e890909041421m243bbea6i95c26ab21dc8732d@mail.gmail.com>
On Fri, Sep 04, 2009 at 02:21:40PM -0700, Luis Rodriguez wrote:
> On Fri, Sep 4, 2009 at 1:25 AM, Catalin Marinas<catalin.marinas@arm.com> wrote:
> > On Fri, 2009-09-04 at 07:04 +0200, Johannes Berg wrote:
> >> On Thu, 2009-09-03 at 13:43 -0700, Luis R. Rodriguez wrote:
> >> > On Thu, Sep 03, 2009 at 11:17:17AM -0700, Johannes Berg wrote:
> >> > > On Thu, 2009-09-03 at 11:13 -0700, Luis R. Rodriguez wrote:
> >> > >
> >> > > > What I meant is it gobbles it up and spits another thing out. When it
> >> > > > gobbles it up the routine then uses kref_put().
> >> > > >
> >> > > > > Why can it not track this?
> >> > > >
> >> > > > It probably can, just not sure if it follows kref_put(), I was under
> >> > > > the impression here it doesn't and because of it we were getting false
> >> > > > positives. Catalin, can you confirm?
> >> > >
> >> > > Ah I'd think that if it can't track it then that's because we use a
> >> > > pointer to the middle of the struct to keep track of it much of the
> >> > > time.
> >> >
> >> > So you agree with the patch but not the commit log entry?
> >>
> >> I'm not sure -- I think kmemleak should be able to figure it out, and if
> >> you were using IBSS then we actually have a leak that we need to plug,
> >> but otherwise I'd prefer to get some more input from Catalin first.
> >
> > First of all, kmemleak_ignore() is not the right function to mark a
> > false positive as it completely ignores an object even though it may
> > have pointers to others. The kmemleak_not_leak() function should be
> > used. However, there are only two places in the kernel where this was
> > actually needed (one of them is a real leak but we ignore it as it makes
> > the code more complicated).
> >
> > So, I think we should try to figure out why kmemleak reports it. There
> > are a few common cases:
> > 1. transient false positive - this should disappear after a few
> > scans
> > 2. a pointer leading to the reported object is stored in an area of
> > memory not scanned by kmemleak - most commonly pages allocated
> > explicitly (alloc_pages etc.) as kmemleak doesn't track these.
> > The preferred solution is to inform kmemleak about such page
> > (kmemleak_alloc/kmemleak_free) rather than marking the false
> > positive
> > 3. a pointer leading to the reported object isn't actually pointing
> > to anywhere inside the structure (i.e. using the physical
> > address). Here we would use kmemleak_not_leak()
>
> John please revert this merged patch
> (b563f91105758c35d7cd4589992198b9da52d579) on wireless-testing as we'd
> like to investigate further why we get this.
>
> BTW I should
> not
This should be *note* :)
> I got this kmemleak report after using the clear
> command by painting objects black. I'll test it now with your
> suggested changes.
Luis
^ permalink raw reply
* Re: [PATCH] cfg80211: clear cfg80211_inform_bss() from kmemleak reports
From: Luis R. Rodriguez @ 2009-09-04 21:21 UTC (permalink / raw)
To: Catalin Marinas, John W. Linville
Cc: Johannes Berg, Luis Rodriguez, linux-kernel@vger.kernel.org,
linux-wireless@vger.kernel.org
In-Reply-To: <1252052757.26413.9.camel@pc1117.cambridge.arm.com>
On Fri, Sep 4, 2009 at 1:25 AM, Catalin Marinas<catalin.marinas@arm.com> wrote:
> On Fri, 2009-09-04 at 07:04 +0200, Johannes Berg wrote:
>> On Thu, 2009-09-03 at 13:43 -0700, Luis R. Rodriguez wrote:
>> > On Thu, Sep 03, 2009 at 11:17:17AM -0700, Johannes Berg wrote:
>> > > On Thu, 2009-09-03 at 11:13 -0700, Luis R. Rodriguez wrote:
>> > >
>> > > > What I meant is it gobbles it up and spits another thing out. When it
>> > > > gobbles it up the routine then uses kref_put().
>> > > >
>> > > > > Why can it not track this?
>> > > >
>> > > > It probably can, just not sure if it follows kref_put(), I was under
>> > > > the impression here it doesn't and because of it we were getting false
>> > > > positives. Catalin, can you confirm?
>> > >
>> > > Ah I'd think that if it can't track it then that's because we use a
>> > > pointer to the middle of the struct to keep track of it much of the
>> > > time.
>> >
>> > So you agree with the patch but not the commit log entry?
>>
>> I'm not sure -- I think kmemleak should be able to figure it out, and if
>> you were using IBSS then we actually have a leak that we need to plug,
>> but otherwise I'd prefer to get some more input from Catalin first.
>
> First of all, kmemleak_ignore() is not the right function to mark a
> false positive as it completely ignores an object even though it may
> have pointers to others. The kmemleak_not_leak() function should be
> used. However, there are only two places in the kernel where this was
> actually needed (one of them is a real leak but we ignore it as it makes
> the code more complicated).
>
> So, I think we should try to figure out why kmemleak reports it. There
> are a few common cases:
> 1. transient false positive - this should disappear after a few
> scans
> 2. a pointer leading to the reported object is stored in an area of
> memory not scanned by kmemleak - most commonly pages allocated
> explicitly (alloc_pages etc.) as kmemleak doesn't track these.
> The preferred solution is to inform kmemleak about such page
> (kmemleak_alloc/kmemleak_free) rather than marking the false
> positive
> 3. a pointer leading to the reported object isn't actually pointing
> to anywhere inside the structure (i.e. using the physical
> address). Here we would use kmemleak_not_leak()
John please revert this merged patch
(b563f91105758c35d7cd4589992198b9da52d579) on wireless-testing as we'd
like to investigate further why we get this.
BTW I should not I got this kmemleak report after using the clear
command by painting objects black. I'll test it now with your
suggested changes.
Luis
^ permalink raw reply
* [PATCH 5/5] b43: remove SHM spinlock
From: Michael Buesch @ 2009-09-04 20:57 UTC (permalink / raw)
To: John Linville; +Cc: Broadcom Wireless, linux-wireless, Albert Herranz
This removes the SHM spinlock.
SHM is protected by wl->mutex.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-testing/drivers/net/wireless/b43/b43.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/b43.h 2009-09-04 22:18:48.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/b43.h 2009-09-04 22:18:58.000000000 +0200
@@ -635,8 +635,6 @@ struct b43_wl {
rwlock_t tx_lock;
/* Lock for LEDs access. */
spinlock_t leds_lock;
- /* Lock for SHM access. */
- spinlock_t shm_lock;
/* We can only have one operating interface (802.11 core)
* at a time. General information about this interface follows.
Index: wireless-testing/drivers/net/wireless/b43/debugfs.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/debugfs.c 2009-09-04 22:18:42.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/debugfs.c 2009-09-04 22:18:58.000000000 +0200
@@ -125,7 +125,6 @@ static int shm16write__write_file(struct
unsigned int routing, addr, mask, set;
u16 val;
int res;
- unsigned long flags;
res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
&routing, &addr, &mask, &set);
@@ -142,15 +141,13 @@ static int shm16write__write_file(struct
if ((mask > 0xFFFF) || (set > 0xFFFF))
return -E2BIG;
- spin_lock_irqsave(&dev->wl->shm_lock, flags);
if (mask == 0)
val = 0;
else
- val = __b43_shm_read16(dev, routing, addr);
+ val = b43_shm_read16(dev, routing, addr);
val &= mask;
val |= set;
- __b43_shm_write16(dev, routing, addr, val);
- spin_unlock_irqrestore(&dev->wl->shm_lock, flags);
+ b43_shm_write16(dev, routing, addr, val);
return 0;
}
@@ -204,7 +201,6 @@ static int shm32write__write_file(struct
unsigned int routing, addr, mask, set;
u32 val;
int res;
- unsigned long flags;
res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
&routing, &addr, &mask, &set);
@@ -221,15 +217,13 @@ static int shm32write__write_file(struct
if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
return -E2BIG;
- spin_lock_irqsave(&dev->wl->shm_lock, flags);
if (mask == 0)
val = 0;
else
- val = __b43_shm_read32(dev, routing, addr);
+ val = b43_shm_read32(dev, routing, addr);
val &= mask;
val |= set;
- __b43_shm_write32(dev, routing, addr, val);
- spin_unlock_irqrestore(&dev->wl->shm_lock, flags);
+ b43_shm_write32(dev, routing, addr, val);
return 0;
}
Index: wireless-testing/drivers/net/wireless/b43/main.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/main.c 2009-09-04 22:18:54.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/main.c 2009-09-04 22:18:58.000000000 +0200
@@ -390,7 +390,7 @@ static inline void b43_shm_control_word(
b43_write32(dev, B43_MMIO_SHM_CONTROL, control);
}
-u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
+u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
{
u32 ret;
@@ -413,20 +413,7 @@ out:
return ret;
}
-u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
-{
- struct b43_wl *wl = dev->wl;
- unsigned long flags;
- u32 ret;
-
- spin_lock_irqsave(&wl->shm_lock, flags);
- ret = __b43_shm_read32(dev, routing, offset);
- spin_unlock_irqrestore(&wl->shm_lock, flags);
-
- return ret;
-}
-
-u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset)
+u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset)
{
u16 ret;
@@ -447,20 +434,7 @@ out:
return ret;
}
-u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset)
-{
- struct b43_wl *wl = dev->wl;
- unsigned long flags;
- u16 ret;
-
- spin_lock_irqsave(&wl->shm_lock, flags);
- ret = __b43_shm_read16(dev, routing, offset);
- spin_unlock_irqrestore(&wl->shm_lock, flags);
-
- return ret;
-}
-
-void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
+void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
{
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
@@ -480,17 +454,7 @@ void __b43_shm_write32(struct b43_wldev
b43_write32(dev, B43_MMIO_SHM_DATA, value);
}
-void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
-{
- struct b43_wl *wl = dev->wl;
- unsigned long flags;
-
- spin_lock_irqsave(&wl->shm_lock, flags);
- __b43_shm_write32(dev, routing, offset, value);
- spin_unlock_irqrestore(&wl->shm_lock, flags);
-}
-
-void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
+void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
{
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
@@ -506,16 +470,6 @@ void __b43_shm_write16(struct b43_wldev
b43_write16(dev, B43_MMIO_SHM_DATA, value);
}
-void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
-{
- struct b43_wl *wl = dev->wl;
- unsigned long flags;
-
- spin_lock_irqsave(&wl->shm_lock, flags);
- __b43_shm_write16(dev, routing, offset, value);
- spin_unlock_irqrestore(&wl->shm_lock, flags);
-}
-
/* Read HostFlags */
u64 b43_hf_read(struct b43_wldev *dev)
{
@@ -4866,7 +4820,6 @@ static int b43_wireless_init(struct ssb_
/* Initialize struct b43_wl */
wl->hw = hw;
spin_lock_init(&wl->leds_lock);
- spin_lock_init(&wl->shm_lock);
mutex_init(&wl->mutex);
spin_lock_init(&wl->hardirq_lock);
INIT_LIST_HEAD(&wl->devlist);
Index: wireless-testing/drivers/net/wireless/b43/main.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/main.h 2009-09-04 22:15:29.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/main.h 2009-09-04 22:18:58.000000000 +0200
@@ -112,13 +112,9 @@ void b43_tsf_read(struct b43_wldev *dev,
void b43_tsf_write(struct b43_wldev *dev, u64 tsf);
u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset);
-u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset);
u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
-u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
-void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
-void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
u64 b43_hf_read(struct b43_wldev *dev);
void b43_hf_write(struct b43_wldev *dev, u64 value);
--
Greetings, Michael.
^ permalink raw reply
* [PATCH 3/5] b43: Remove DMA/PIO queue locks
From: Michael Buesch @ 2009-09-04 20:55 UTC (permalink / raw)
To: John Linville; +Cc: Broadcom Wireless, linux-wireless, Albert Herranz
This removes the DMA/PIO queue locks. Locking is handled by
wl->mutex now.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-testing/drivers/net/wireless/b43/dma.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/dma.c 2009-08-23 13:43:13.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/dma.c 2009-08-23 14:21:21.000000000 +0200
@@ -856,7 +856,6 @@ struct b43_dmaring *b43_setup_dmaring(st
} else
B43_WARN_ON(1);
}
- spin_lock_init(&ring->lock);
#ifdef CONFIG_B43_DEBUG
ring->last_injected_overflow = jiffies;
#endif
@@ -1315,7 +1314,6 @@ int b43_dma_tx(struct b43_wldev *dev, st
struct b43_dmaring *ring;
struct ieee80211_hdr *hdr;
int err = 0;
- unsigned long flags;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
hdr = (struct ieee80211_hdr *)skb->data;
@@ -1331,8 +1329,6 @@ int b43_dma_tx(struct b43_wldev *dev, st
dev, skb_get_queue_mapping(skb));
}
- spin_lock_irqsave(&ring->lock, flags);
-
B43_WARN_ON(!ring->tx);
if (unlikely(ring->stopped)) {
@@ -1343,7 +1339,7 @@ int b43_dma_tx(struct b43_wldev *dev, st
if (b43_debug(dev, B43_DBG_DMAVERBOSE))
b43err(dev->wl, "Packet after queue stopped\n");
err = -ENOSPC;
- goto out_unlock;
+ goto out;
}
if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) {
@@ -1351,7 +1347,7 @@ int b43_dma_tx(struct b43_wldev *dev, st
* full, but queues not stopped. */
b43err(dev->wl, "DMA queue overflow\n");
err = -ENOSPC;
- goto out_unlock;
+ goto out;
}
/* Assign the queue number to the ring (if not already done before)
@@ -1365,11 +1361,11 @@ int b43_dma_tx(struct b43_wldev *dev, st
* anymore and must not transmit it unencrypted. */
dev_kfree_skb_any(skb);
err = 0;
- goto out_unlock;
+ goto out;
}
if (unlikely(err)) {
b43err(dev->wl, "DMA tx mapping failure\n");
- goto out_unlock;
+ goto out;
}
ring->nr_tx_packets++;
if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
@@ -1381,8 +1377,7 @@ int b43_dma_tx(struct b43_wldev *dev, st
b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
}
}
-out_unlock:
- spin_unlock_irqrestore(&ring->lock, flags);
+out:
return err;
}
@@ -1401,8 +1396,6 @@ void b43_dma_handle_txstatus(struct b43_
if (unlikely(!ring))
return;
- spin_lock_irq(&ring->lock);
-
B43_WARN_ON(!ring->tx);
ops = ring->ops;
while (1) {
@@ -1461,8 +1454,6 @@ void b43_dma_handle_txstatus(struct b43_
b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
}
}
-
- spin_unlock_irq(&ring->lock);
}
void b43_dma_get_tx_stats(struct b43_wldev *dev,
@@ -1470,17 +1461,14 @@ void b43_dma_get_tx_stats(struct b43_wld
{
const int nr_queues = dev->wl->hw->queues;
struct b43_dmaring *ring;
- unsigned long flags;
int i;
for (i = 0; i < nr_queues; i++) {
ring = select_ring_by_priority(dev, i);
- spin_lock_irqsave(&ring->lock, flags);
stats[i].len = ring->used_slots / TX_SLOTS_PER_FRAME;
stats[i].limit = ring->nr_slots / TX_SLOTS_PER_FRAME;
stats[i].count = ring->nr_tx_packets;
- spin_unlock_irqrestore(&ring->lock, flags);
}
}
@@ -1591,22 +1579,14 @@ void b43_dma_rx(struct b43_dmaring *ring
static void b43_dma_tx_suspend_ring(struct b43_dmaring *ring)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ring->lock, flags);
B43_WARN_ON(!ring->tx);
ring->ops->tx_suspend(ring);
- spin_unlock_irqrestore(&ring->lock, flags);
}
static void b43_dma_tx_resume_ring(struct b43_dmaring *ring)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ring->lock, flags);
B43_WARN_ON(!ring->tx);
ring->ops->tx_resume(ring);
- spin_unlock_irqrestore(&ring->lock, flags);
}
void b43_dma_tx_suspend(struct b43_wldev *dev)
Index: wireless-testing/drivers/net/wireless/b43/dma.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/dma.h 2009-08-23 13:43:13.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/dma.h 2009-08-23 14:21:21.000000000 +0200
@@ -2,7 +2,6 @@
#define B43_DMA_H_
#include <linux/ieee80211.h>
-#include <linux/spinlock.h>
#include "b43.h"
@@ -244,8 +243,6 @@ struct b43_dmaring {
/* The QOS priority assigned to this ring. Only used for TX rings.
* This is the mac80211 "queue" value. */
u8 queue_prio;
- /* Lock, only used for TX. */
- spinlock_t lock;
struct b43_wldev *dev;
#ifdef CONFIG_B43_DEBUG
/* Maximum number of used slots. */
Index: wireless-testing/drivers/net/wireless/b43/pio.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/pio.c 2009-08-23 13:43:13.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/pio.c 2009-08-23 14:21:21.000000000 +0200
@@ -144,7 +144,6 @@ static struct b43_pio_txqueue *b43_setup
q = kzalloc(sizeof(*q), GFP_KERNEL);
if (!q)
return NULL;
- spin_lock_init(&q->lock);
q->dev = dev;
q->rev = dev->dev->id.revision;
q->mmio_base = index_to_pioqueue_base(dev, index) +
@@ -179,7 +178,6 @@ static struct b43_pio_rxqueue *b43_setup
q = kzalloc(sizeof(*q), GFP_KERNEL);
if (!q)
return NULL;
- spin_lock_init(&q->lock);
q->dev = dev;
q->rev = dev->dev->id.revision;
q->mmio_base = index_to_pioqueue_base(dev, index) +
@@ -494,7 +492,6 @@ int b43_pio_tx(struct b43_wldev *dev, st
{
struct b43_pio_txqueue *q;
struct ieee80211_hdr *hdr;
- unsigned long flags;
unsigned int hdrlen, total_len;
int err = 0;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -512,20 +509,18 @@ int b43_pio_tx(struct b43_wldev *dev, st
q = select_queue_by_priority(dev, skb_get_queue_mapping(skb));
}
- spin_lock_irqsave(&q->lock, flags);
-
hdrlen = b43_txhdr_size(dev);
total_len = roundup(skb->len + hdrlen, 4);
if (unlikely(total_len > q->buffer_size)) {
err = -ENOBUFS;
b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
- goto out_unlock;
+ goto out;
}
if (unlikely(q->free_packet_slots == 0)) {
err = -ENOBUFS;
b43warn(dev->wl, "PIO: TX packet overflow.\n");
- goto out_unlock;
+ goto out;
}
B43_WARN_ON(q->buffer_used > q->buffer_size);
@@ -534,7 +529,7 @@ int b43_pio_tx(struct b43_wldev *dev, st
err = -EBUSY;
ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
q->stopped = 1;
- goto out_unlock;
+ goto out;
}
/* Assign the queue number to the ring (if not already done before)
@@ -548,11 +543,11 @@ int b43_pio_tx(struct b43_wldev *dev, st
* anymore and must not transmit it unencrypted. */
dev_kfree_skb_any(skb);
err = 0;
- goto out_unlock;
+ goto out;
}
if (unlikely(err)) {
b43err(dev->wl, "PIO transmission failure\n");
- goto out_unlock;
+ goto out;
}
q->nr_tx_packets++;
@@ -564,9 +559,7 @@ int b43_pio_tx(struct b43_wldev *dev, st
q->stopped = 1;
}
-out_unlock:
- spin_unlock_irqrestore(&q->lock, flags);
-
+out:
return err;
}
@@ -583,8 +576,6 @@ void b43_pio_handle_txstatus(struct b43_
return;
B43_WARN_ON(!pack);
- spin_lock_irq(&q->lock);
-
info = IEEE80211_SKB_CB(pack->skb);
b43_fill_txstatus_report(dev, info, status);
@@ -602,8 +593,6 @@ void b43_pio_handle_txstatus(struct b43_
ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
q->stopped = 0;
}
-
- spin_unlock_irq(&q->lock);
}
void b43_pio_get_tx_stats(struct b43_wldev *dev,
@@ -611,17 +600,14 @@ void b43_pio_get_tx_stats(struct b43_wld
{
const int nr_queues = dev->wl->hw->queues;
struct b43_pio_txqueue *q;
- unsigned long flags;
int i;
for (i = 0; i < nr_queues; i++) {
q = select_queue_by_priority(dev, i);
- spin_lock_irqsave(&q->lock, flags);
stats[i].len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots;
stats[i].limit = B43_PIO_MAX_NR_TXPACKETS;
stats[i].count = q->nr_tx_packets;
- spin_unlock_irqrestore(&q->lock, flags);
}
}
@@ -768,9 +754,9 @@ static void b43_pio_rx_work(struct work_
bool stop;
do {
- spin_lock_irq(&q->lock);
+ mutex_lock(&q->dev->wl->mutex);
stop = (pio_rx_frame(q) == 0);
- spin_unlock_irq(&q->lock);
+ mutex_unlock(&q->dev->wl->mutex);
cond_resched();
if (stop)
break;
@@ -787,9 +773,6 @@ void b43_pio_rx(struct b43_pio_rxqueue *
static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
{
- unsigned long flags;
-
- spin_lock_irqsave(&q->lock, flags);
if (q->rev >= 8) {
b43_piotx_write32(q, B43_PIO8_TXCTL,
b43_piotx_read32(q, B43_PIO8_TXCTL)
@@ -799,14 +782,10 @@ static void b43_pio_tx_suspend_queue(str
b43_piotx_read16(q, B43_PIO_TXCTL)
| B43_PIO_TXCTL_SUSPREQ);
}
- spin_unlock_irqrestore(&q->lock, flags);
}
static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
{
- unsigned long flags;
-
- spin_lock_irqsave(&q->lock, flags);
if (q->rev >= 8) {
b43_piotx_write32(q, B43_PIO8_TXCTL,
b43_piotx_read32(q, B43_PIO8_TXCTL)
@@ -816,7 +795,6 @@ static void b43_pio_tx_resume_queue(stru
b43_piotx_read16(q, B43_PIO_TXCTL)
& ~B43_PIO_TXCTL_SUSPREQ);
}
- spin_unlock_irqrestore(&q->lock, flags);
}
void b43_pio_tx_suspend(struct b43_wldev *dev)
Index: wireless-testing/drivers/net/wireless/b43/pio.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/pio.h 2009-08-23 13:43:13.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/pio.h 2009-08-23 14:21:21.000000000 +0200
@@ -70,7 +70,6 @@ struct b43_pio_txpacket {
struct b43_pio_txqueue {
struct b43_wldev *dev;
- spinlock_t lock;
u16 mmio_base;
/* The device queue buffer size in bytes. */
@@ -103,7 +102,6 @@ struct b43_pio_txqueue {
struct b43_pio_rxqueue {
struct b43_wldev *dev;
- spinlock_t lock;
u16 mmio_base;
/* Work to reduce latency issues on RX. */
--
Greetings, Michael.
^ permalink raw reply
* [PATCH 4/5] b43: Remove PIO RX workqueue
From: Michael Buesch @ 2009-09-04 20:56 UTC (permalink / raw)
To: John Linville; +Cc: Broadcom Wireless, linux-wireless, Albert Herranz
This removes the PIO RX work. It's not needed anymore, because
we can sleep in the threaded interrupt handler.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-testing/drivers/net/wireless/b43/pio.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/pio.c 2009-09-04 22:18:53.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/pio.c 2009-09-04 22:18:54.000000000 +0200
@@ -32,9 +32,6 @@
#include <linux/delay.h>
-static void b43_pio_rx_work(struct work_struct *work);
-
-
static u16 generate_cookie(struct b43_pio_txqueue *q,
struct b43_pio_txpacket *pack)
{
@@ -182,7 +179,6 @@ static struct b43_pio_rxqueue *b43_setup
q->rev = dev->dev->id.revision;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_rxqueue_offset(dev);
- INIT_WORK(&q->rx_work, b43_pio_rx_work);
/* Enable Direct FIFO RX (PIO) on the engine. */
b43_dma_direct_fifo_rx(dev, index, 1);
@@ -247,13 +243,6 @@ void b43_pio_free(struct b43_wldev *dev)
destroy_queue_tx(pio, tx_queue_AC_BK);
}
-void b43_pio_stop(struct b43_wldev *dev)
-{
- if (!b43_using_pio_transfers(dev))
- return;
- cancel_work_sync(&dev->pio.rx_queue->rx_work);
-}
-
int b43_pio_init(struct b43_wldev *dev)
{
struct b43_pio *pio = &dev->pio;
@@ -745,30 +734,19 @@ rx_error:
return 1;
}
-/* RX workqueue. We can sleep, yay! */
-static void b43_pio_rx_work(struct work_struct *work)
+void b43_pio_rx(struct b43_pio_rxqueue *q)
{
- struct b43_pio_rxqueue *q = container_of(work, struct b43_pio_rxqueue,
- rx_work);
- unsigned int budget = 50;
+ unsigned int count = 0;
bool stop;
- do {
- mutex_lock(&q->dev->wl->mutex);
+ while (1) {
stop = (pio_rx_frame(q) == 0);
- mutex_unlock(&q->dev->wl->mutex);
- cond_resched();
if (stop)
break;
- } while (--budget);
-}
-
-/* Called with IRQs disabled. */
-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. */
- ieee80211_queue_work(q->dev->wl->hw, &q->rx_work);
+ cond_resched();
+ if (WARN_ON_ONCE(++count > 10000))
+ break;
+ }
}
static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
Index: wireless-testing/drivers/net/wireless/b43/pio.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/pio.h 2009-09-04 22:18:53.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/pio.h 2009-09-04 22:18:54.000000000 +0200
@@ -104,9 +104,6 @@ struct b43_pio_rxqueue {
struct b43_wldev *dev;
u16 mmio_base;
- /* Work to reduce latency issues on RX. */
- struct work_struct rx_work;
-
/* Shortcut to the 802.11 core revision. This is to
* avoid horrible pointer dereferencing in the fastpaths. */
u8 rev;
@@ -160,7 +157,6 @@ static inline void b43_piorx_write32(str
int b43_pio_init(struct b43_wldev *dev);
-void b43_pio_stop(struct b43_wldev *dev);
void b43_pio_free(struct b43_wldev *dev);
int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb);
Index: wireless-testing/drivers/net/wireless/b43/main.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/main.c 2009-09-04 22:18:49.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/main.c 2009-09-04 22:18:54.000000000 +0200
@@ -3883,7 +3883,6 @@ redo:
while (skb_queue_len(&wl->tx_queue))
dev_kfree_skb(skb_dequeue(&wl->tx_queue));
- b43_pio_stop(dev);
b43_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
b43dbg(wl, "Wireless interface stopped\n");
--
Greetings, Michael.
^ permalink raw reply
* [PATCH 2/5] b43: Remove TX spinlock
From: Michael Buesch @ 2009-09-04 20:53 UTC (permalink / raw)
To: John Linville; +Cc: Broadcom Wireless, linux-wireless, Albert Herranz
This removes the TX spinlock and defers TX to a workqueue to allow
locking wl->mutex instead and to allow sleeping for register accesses.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-testing/drivers/net/wireless/b43/b43.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/b43.h 2009-09-04 22:18:47.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/b43.h 2009-09-04 22:18:48.000000000 +0200
@@ -683,6 +683,11 @@ struct b43_wl {
* This is scheduled when we determine that the actual TX output
* power doesn't match what we want. */
struct work_struct txpower_adjust_work;
+
+ /* Packet transmit work */
+ struct work_struct tx_work;
+ /* Queue of packets to be transmitted. */
+ struct sk_buff_head tx_queue;
};
/* The type of the firmware file. */
Index: wireless-testing/drivers/net/wireless/b43/main.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/main.c 2009-09-04 22:18:47.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/main.c 2009-09-04 22:18:49.000000000 +0200
@@ -690,7 +690,6 @@ static void b43_short_slot_timing_disabl
*/
void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
{
- struct b43_wl *wl = dev->wl;
struct b43_phy *phy = &dev->phy;
unsigned int i, max_loop;
u16 value;
@@ -710,8 +709,6 @@ void b43_dummy_transmission(struct b43_w
buffer[0] = 0x000B846E;
}
- write_lock_irq(&wl->tx_lock);
-
for (i = 0; i < 5; i++)
b43_ram_write(dev, i * 4, buffer[i]);
@@ -767,8 +764,6 @@ void b43_dummy_transmission(struct b43_w
}
if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
b43_radio_write16(dev, 0x0051, 0x0037);
-
- write_unlock_irq(&wl->tx_lock);
}
static void key_write(struct b43_wldev *dev,
@@ -3098,42 +3093,49 @@ static int b43_rng_init(struct b43_wl *w
return err;
}
-static int b43_op_tx(struct ieee80211_hw *hw,
- struct sk_buff *skb)
+static void b43_tx_work(struct work_struct *work)
{
- struct b43_wl *wl = hw_to_b43_wl(hw);
- struct b43_wldev *dev = wl->current_dev;
- unsigned long flags;
- int err;
+ struct b43_wl *wl = container_of(work, struct b43_wl, tx_work);
+ struct b43_wldev *dev;
+ struct sk_buff *skb;
+ int err = 0;
- if (unlikely(skb->len < 2 + 2 + 6)) {
- /* Too short, this can't be a valid frame. */
- goto drop_packet;
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED)) {
+ mutex_unlock(&wl->mutex);
+ return;
}
- B43_WARN_ON(skb_shinfo(skb)->nr_frags);
- if (unlikely(!dev))
- goto drop_packet;
- /* Transmissions on seperate queues can run concurrently. */
- read_lock_irqsave(&wl->tx_lock, flags);
+ while (skb_queue_len(&wl->tx_queue)) {
+ skb = skb_dequeue(&wl->tx_queue);
- err = -ENODEV;
- if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
if (b43_using_pio_transfers(dev))
err = b43_pio_tx(dev, skb);
else
err = b43_dma_tx(dev, skb);
+ if (unlikely(err))
+ dev_kfree_skb(skb); /* Drop it */
}
- read_unlock_irqrestore(&wl->tx_lock, flags);
+ mutex_unlock(&wl->mutex);
+}
- if (unlikely(err))
- goto drop_packet;
- return NETDEV_TX_OK;
+static int b43_op_tx(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
+{
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+
+ if (unlikely(skb->len < 2 + 2 + 6)) {
+ /* Too short, this can't be a valid frame. */
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ B43_WARN_ON(skb_shinfo(skb)->nr_frags);
+
+ skb_queue_tail(&wl->tx_queue, skb);
+ ieee80211_queue_work(wl->hw, &wl->tx_work);
-drop_packet:
- /* We can not transmit this packet. Drop it. */
- dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -3686,18 +3688,12 @@ static int b43_op_set_key(struct ieee802
u8 algorithm;
u8 index;
int err;
- unsigned long flags;
static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
if (modparam_nohwcrypt)
return -ENOSPC; /* User disabled HW-crypto */
mutex_lock(&wl->mutex);
- write_lock_irqsave(&wl->tx_lock, flags);
- /* mutex -> Every config operation must take it.
- * tx_lock -> We modify the dev->key array, which is accessed
- * in the TX handler.
- */
dev = wl->current_dev;
err = -ENODEV;
@@ -3789,7 +3785,6 @@ out_unlock:
sta ? sta->addr : bcast_addr);
b43_dump_keymemory(dev);
}
- write_unlock_irqrestore(&wl->tx_lock, flags);
mutex_unlock(&wl->mutex);
return err;
@@ -3846,9 +3841,10 @@ redo:
if (!dev || b43_status(dev) < B43_STAT_STARTED)
return dev;
- /* Disable periodic work. Unlock to avoid deadlocks. */
+ /* Cancel work. Unlock to avoid deadlocks. */
mutex_unlock(&wl->mutex);
cancel_delayed_work_sync(&dev->periodic_work);
+ cancel_work_sync(&wl->tx_work);
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (!dev || b43_status(dev) < B43_STAT_STARTED) {
@@ -3883,6 +3879,10 @@ redo:
}
B43_WARN_ON(b43_read32(dev, B43_MMIO_GEN_IRQ_MASK));
+ /* Drain the TX queue */
+ while (skb_queue_len(&wl->tx_queue))
+ dev_kfree_skb(skb_dequeue(&wl->tx_queue));
+
b43_pio_stop(dev);
b43_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
@@ -4866,7 +4866,6 @@ static int b43_wireless_init(struct ssb_
/* Initialize struct b43_wl */
wl->hw = hw;
- rwlock_init(&wl->tx_lock);
spin_lock_init(&wl->leds_lock);
spin_lock_init(&wl->shm_lock);
mutex_init(&wl->mutex);
@@ -4874,6 +4873,8 @@ static int b43_wireless_init(struct ssb_
INIT_LIST_HEAD(&wl->devlist);
INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
+ INIT_WORK(&wl->tx_work, b43_tx_work);
+ skb_queue_head_init(&wl->tx_queue);
ssb_set_devtypedata(dev, wl);
b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
--
Greetings, Michael.
^ permalink raw reply
* [PATCH 1/5] b43: Use a threaded IRQ handler
From: Michael Buesch @ 2009-09-04 20:51 UTC (permalink / raw)
To: John Linville; +Cc: Broadcom Wireless, linux-wireless, Albert Herranz
Use a threaded IRQ handler to allow locking the mutex and
sleeping while executing an interrupt.
This removes usage of the irq_lock spinlock, but introduces
a new hardirq_lock, which is _only_ used for the PCI/SSB lowlevel
hard-irq handler. Sleeping busses (SDIO) will use mutex instead.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-testing/drivers/net/wireless/b43/b43.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/b43.h 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/b43.h 2009-09-04 22:15:32.000000000 +0200
@@ -616,6 +616,12 @@ struct b43_wl {
/* Pointer to the ieee80211 hardware data structure */
struct ieee80211_hw *hw;
+ /* Global driver mutex. Every operation must run with this mutex locked. */
+ struct mutex mutex;
+ /* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ
+ * handler, only. This basically is just the IRQ mask register. */
+ spinlock_t hardirq_lock;
+
/* The number of queues that were registered with the mac80211 subsystem
* initially. This is a backup copy of hw->queues in case hw->queues has
* to be dynamically lowered at runtime (Firmware does not support QoS).
@@ -623,8 +629,6 @@ struct b43_wl {
* from the mac80211 subsystem. */
u16 mac80211_initially_registered_queues;
- struct mutex mutex;
- spinlock_t irq_lock;
/* R/W lock for data transmission.
* Transmissions on 2+ queues can run concurrently, but somebody else
* might sync with TX by write_lock_irqsave()'ing. */
@@ -665,8 +669,7 @@ struct b43_wl {
bool radiotap_enabled;
bool radio_enabled;
- /* The beacon we are currently using (AP or IBSS mode).
- * This beacon stuff is protected by the irq_lock. */
+ /* The beacon we are currently using (AP or IBSS mode). */
struct sk_buff *current_beacon;
bool beacon0_uploaded;
bool beacon1_uploaded;
@@ -754,14 +757,6 @@ enum {
smp_wmb(); \
} while (0)
-/* XXX--- HOW LOCKING WORKS IN B43 ---XXX
- *
- * You should always acquire both, wl->mutex and wl->irq_lock unless:
- * - You don't need to acquire wl->irq_lock, if the interface is stopped.
- * - You don't need to acquire wl->mutex in the IRQ handler, IRQ tasklet
- * and packet TX path (and _ONLY_ there.)
- */
-
/* Data structure for one wireless device (802.11 core) */
struct b43_wldev {
struct ssb_device *dev;
@@ -807,14 +802,12 @@ struct b43_wldev {
u32 dma_reason[6];
/* The currently active generic-interrupt mask. */
u32 irq_mask;
+
/* Link Quality calculation context. */
struct b43_noise_calculation noisecalc;
/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
int mac_suspended;
- /* Interrupt Service Routine tasklet (bottom-half) */
- struct tasklet_struct isr_tasklet;
-
/* Periodic tasks */
struct delayed_work periodic_work;
unsigned int periodic_state;
Index: wireless-testing/drivers/net/wireless/b43/debugfs.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/debugfs.c 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/debugfs.c 2009-09-04 22:15:32.000000000 +0200
@@ -46,8 +46,6 @@ struct b43_debugfs_fops {
struct file_operations fops;
/* Offset of struct b43_dfs_file in struct b43_dfsentry */
size_t file_struct_offset;
- /* Take wl->irq_lock before calling read/write? */
- bool take_irqlock;
};
static inline
@@ -372,14 +370,12 @@ static ssize_t txstat_read_file(struct b
{
struct b43_txstatus_log *log = &dev->dfsentry->txstatlog;
ssize_t count = 0;
- unsigned long flags;
int i, idx;
struct b43_txstatus *stat;
- spin_lock_irqsave(&log->lock, flags);
if (log->end < 0) {
fappend("Nothing transmitted, yet\n");
- goto out_unlock;
+ goto out;
}
fappend("b43 TX status reports:\n\n"
"index | cookie | seq | phy_stat | frame_count | "
@@ -409,13 +405,11 @@ static ssize_t txstat_read_file(struct b
break;
i++;
}
-out_unlock:
- spin_unlock_irqrestore(&log->lock, flags);
+out:
return count;
}
-/* wl->irq_lock is locked */
static int restart_write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
@@ -556,12 +550,7 @@ static ssize_t b43_debugfs_read(struct f
goto out_unlock;
}
memset(buf, 0, bufsize);
- if (dfops->take_irqlock) {
- spin_lock_irq(&dev->wl->irq_lock);
- ret = dfops->read(dev, buf, bufsize);
- spin_unlock_irq(&dev->wl->irq_lock);
- } else
- ret = dfops->read(dev, buf, bufsize);
+ ret = dfops->read(dev, buf, bufsize);
if (ret <= 0) {
free_pages((unsigned long)buf, buforder);
err = ret;
@@ -623,12 +612,7 @@ static ssize_t b43_debugfs_write(struct
err = -EFAULT;
goto out_freepage;
}
- if (dfops->take_irqlock) {
- spin_lock_irq(&dev->wl->irq_lock);
- err = dfops->write(dev, buf, count);
- spin_unlock_irq(&dev->wl->irq_lock);
- } else
- err = dfops->write(dev, buf, count);
+ err = dfops->write(dev, buf, count);
if (err)
goto out_freepage;
@@ -641,7 +625,7 @@ out_unlock:
}
-#define B43_DEBUGFS_FOPS(name, _read, _write, _take_irqlock) \
+#define B43_DEBUGFS_FOPS(name, _read, _write) \
static struct b43_debugfs_fops fops_##name = { \
.read = _read, \
.write = _write, \
@@ -652,20 +636,19 @@ out_unlock:
}, \
.file_struct_offset = offsetof(struct b43_dfsentry, \
file_##name), \
- .take_irqlock = _take_irqlock, \
}
-B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file, 1);
-B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file, 1);
-B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file, 1);
-B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file, 1);
-B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1);
-B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1);
-B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1);
-B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1);
-B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0);
-B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1);
-B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0);
+B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file);
+B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file);
+B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file);
+B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file);
+B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file);
+B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file);
+B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file);
+B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file);
+B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL);
+B43_DEBUGFS_FOPS(restart, NULL, restart_write_file);
+B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL);
bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
@@ -738,7 +721,6 @@ void b43_debugfs_add_device(struct b43_w
return;
}
log->end = -1;
- spin_lock_init(&log->lock);
dev->dfsentry = e;
@@ -822,7 +804,6 @@ void b43_debugfs_remove_device(struct b4
kfree(e);
}
-/* Called with IRQs disabled. */
void b43_debugfs_log_txstat(struct b43_wldev *dev,
const struct b43_txstatus *status)
{
@@ -834,14 +815,12 @@ void b43_debugfs_log_txstat(struct b43_w
if (!e)
return;
log = &e->txstatlog;
- spin_lock(&log->lock); /* IRQs are already disabled. */
i = log->end + 1;
if (i == B43_NR_LOGGED_TXSTATUS)
i = 0;
log->end = i;
cur = &(log->log[i]);
memcpy(cur, status, sizeof(*cur));
- spin_unlock(&log->lock);
}
void b43_debugfs_init(void)
Index: wireless-testing/drivers/net/wireless/b43/main.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/main.c 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/main.c 2009-09-04 22:17:06.000000000 +0200
@@ -291,7 +291,7 @@ static struct ieee80211_supported_band b
static void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(struct b43_wldev *dev);
-static void b43_wireless_core_stop(struct b43_wldev *dev);
+static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
static int b43_wireless_core_start(struct b43_wldev *dev);
static int b43_ratelimit(struct b43_wl *wl)
@@ -685,16 +685,6 @@ static void b43_short_slot_timing_disabl
b43_set_slot_time(dev, 20);
}
-/* Synchronize IRQ top- and bottom-half.
- * IRQs must be masked before calling this.
- * This must not be called with the irq_lock held.
- */
-static void b43_synchronize_irq(struct b43_wldev *dev)
-{
- synchronize_irq(dev->dev->irq);
- tasklet_kill(&dev->isr_tasklet);
-}
-
/* DummyTransmission function, as documented on
* http://bcm-v4.sipsolutions.net/802.11/DummyTransmission
*/
@@ -720,8 +710,7 @@ void b43_dummy_transmission(struct b43_w
buffer[0] = 0x000B846E;
}
- spin_lock_irq(&wl->irq_lock);
- write_lock(&wl->tx_lock);
+ write_lock_irq(&wl->tx_lock);
for (i = 0; i < 5; i++)
b43_ram_write(dev, i * 4, buffer[i]);
@@ -779,8 +768,7 @@ void b43_dummy_transmission(struct b43_w
if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
b43_radio_write16(dev, 0x0051, 0x0037);
- write_unlock(&wl->tx_lock);
- spin_unlock_irq(&wl->irq_lock);
+ write_unlock_irq(&wl->tx_lock);
}
static void key_write(struct b43_wldev *dev,
@@ -1620,6 +1608,27 @@ static void handle_irq_beacon(struct b43
}
}
+static void b43_do_beacon_update_trigger_work(struct b43_wldev *dev)
+{
+ u32 old_irq_mask = dev->irq_mask;
+
+ /* update beacon right away or defer to irq */
+ handle_irq_beacon(dev);
+ if (old_irq_mask != dev->irq_mask) {
+ /* The handler updated the IRQ mask. */
+ B43_WARN_ON(!dev->irq_mask);
+ if (b43_read32(dev, B43_MMIO_GEN_IRQ_MASK)) {
+ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+ } else {
+ /* Device interrupts are currently disabled. That means
+ * we just ran the hardirq handler and scheduled the
+ * IRQ thread. The thread will write the IRQ mask when
+ * it finished, so there's nothing to do here. Writing
+ * the mask _here_ would incorrectly re-enable IRQs. */
+ }
+ }
+}
+
static void b43_beacon_update_trigger_work(struct work_struct *work)
{
struct b43_wl *wl = container_of(work, struct b43_wl,
@@ -1629,19 +1638,22 @@ static void b43_beacon_update_trigger_wo
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
- spin_lock_irq(&wl->irq_lock);
- /* update beacon right away or defer to irq */
- handle_irq_beacon(dev);
- /* The handler might have updated the IRQ mask. */
- b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
- mmiowb();
- spin_unlock_irq(&wl->irq_lock);
+ if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
+ /* wl->mutex is enough. */
+ b43_do_beacon_update_trigger_work(dev);
+ mmiowb();
+ } else {
+ spin_lock_irq(&wl->hardirq_lock);
+ b43_do_beacon_update_trigger_work(dev);
+ mmiowb();
+ spin_unlock_irq(&wl->hardirq_lock);
+ }
}
mutex_unlock(&wl->mutex);
}
/* Asynchronously update the packet templates in template RAM.
- * Locking: Requires wl->irq_lock to be locked. */
+ * Locking: Requires wl->mutex to be locked. */
static void b43_update_templates(struct b43_wl *wl)
{
struct sk_buff *beacon;
@@ -1778,18 +1790,15 @@ out:
B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK);
}
-/* Interrupt handler bottom-half */
-static void b43_interrupt_tasklet(struct b43_wldev *dev)
+static void b43_do_interrupt_thread(struct b43_wldev *dev)
{
u32 reason;
u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
u32 merged_dma_reason = 0;
int i;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->wl->irq_lock, flags);
- B43_WARN_ON(b43_status(dev) != B43_STAT_STARTED);
+ if (unlikely(b43_status(dev) != B43_STAT_STARTED))
+ return;
reason = dev->irq_reason;
for (i = 0; i < ARRAY_SIZE(dma_reason); i++) {
@@ -1822,8 +1831,6 @@ static void b43_interrupt_tasklet(struct
dma_reason[2], dma_reason[3],
dma_reason[4], dma_reason[5]);
b43_controller_restart(dev, "DMA error");
- mmiowb();
- spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
return;
}
if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
@@ -1867,47 +1874,36 @@ static void b43_interrupt_tasklet(struct
if (reason & B43_IRQ_TX_OK)
handle_irq_transmit_status(dev);
+ /* Re-enable interrupts on the device by restoring the current interrupt mask. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
- mmiowb();
- spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
}
-static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason)
+/* Interrupt thread handler. Handles device interrupts in thread context. */
+static irqreturn_t b43_interrupt_thread_handler(int irq, void *dev_id)
{
- b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason);
+ struct b43_wldev *dev = dev_id;
- b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]);
- b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]);
- b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
- b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
- b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
-/* Unused ring
- b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
-*/
+ mutex_lock(&dev->wl->mutex);
+ b43_do_interrupt_thread(dev);
+ mmiowb();
+ mutex_unlock(&dev->wl->mutex);
+
+ return IRQ_HANDLED;
}
-/* Interrupt handler top-half */
-static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
+static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
{
- irqreturn_t ret = IRQ_NONE;
- struct b43_wldev *dev = dev_id;
u32 reason;
- B43_WARN_ON(!dev);
+ /* This code runs under wl->hardirq_lock, but _only_ on non-SDIO busses.
+ * On SDIO, this runs under wl->mutex. */
- spin_lock(&dev->wl->irq_lock);
-
- if (unlikely(b43_status(dev) < B43_STAT_STARTED)) {
- /* This can only happen on shared IRQ lines. */
- goto out;
- }
reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
if (reason == 0xffffffff) /* shared IRQ */
- goto out;
- ret = IRQ_HANDLED;
+ return IRQ_NONE;
reason &= dev->irq_mask;
if (!reason)
- goto out;
+ return IRQ_HANDLED;
dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
& 0x0001DC00;
@@ -1924,15 +1920,38 @@ static irqreturn_t b43_interrupt_handler
& 0x0000DC00;
*/
- b43_interrupt_ack(dev, reason);
- /* disable all IRQs. They are enabled again in the bottom half. */
+ /* ACK the interrupt. */
+ b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason);
+ b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]);
+ b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]);
+ b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
+ b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
+ b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
+/* Unused ring
+ b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
+*/
+
+ /* Disable IRQs on the device. The IRQ thread handler will re-enable them. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
- /* save the reason code and call our bottom half. */
+ /* Save the reason bitmasks for the IRQ thread handler. */
dev->irq_reason = reason;
- tasklet_schedule(&dev->isr_tasklet);
-out:
+
+ return IRQ_WAKE_THREAD;
+}
+
+/* Interrupt handler top-half. This runs with interrupts disabled. */
+static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
+{
+ struct b43_wldev *dev = dev_id;
+ irqreturn_t ret;
+
+ if (unlikely(b43_status(dev) < B43_STAT_STARTED))
+ return IRQ_NONE;
+
+ spin_lock(&dev->wl->hardirq_lock);
+ ret = b43_do_interrupt(dev);
mmiowb();
- spin_unlock(&dev->wl->irq_lock);
+ spin_unlock(&dev->wl->hardirq_lock);
return ret;
}
@@ -3038,15 +3057,12 @@ static void b43_security_init(struct b43
static int b43_rng_read(struct hwrng *rng, u32 *data)
{
struct b43_wl *wl = (struct b43_wl *)rng->priv;
- unsigned long flags;
- /* Don't take wl->mutex here, as it could deadlock with
- * hwrng internal locking. It's not needed to take
- * wl->mutex here, anyway. */
+ /* FIXME: We need to take wl->mutex here to make sure the device
+ * is not going away from under our ass. However it could deadlock
+ * with hwrng internal locking. */
- spin_lock_irqsave(&wl->irq_lock, flags);
*data = b43_read16(wl->current_dev, B43_MMIO_RNG);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
return (sizeof(u16));
}
@@ -3283,22 +3299,20 @@ static int b43_op_get_tx_stats(struct ie
struct ieee80211_tx_queue_stats *stats)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
- struct b43_wldev *dev = wl->current_dev;
- unsigned long flags;
+ struct b43_wldev *dev;
int err = -ENODEV;
- if (!dev)
- goto out;
- spin_lock_irqsave(&wl->irq_lock, flags);
- if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (dev && b43_status(dev) >= B43_STAT_STARTED) {
if (b43_using_pio_transfers(dev))
b43_pio_get_tx_stats(dev, stats);
else
b43_dma_get_tx_stats(dev, stats);
err = 0;
}
- spin_unlock_irqrestore(&wl->irq_lock, flags);
-out:
+ mutex_unlock(&wl->mutex);
+
return err;
}
@@ -3306,11 +3320,10 @@ static int b43_op_get_stats(struct ieee8
struct ieee80211_low_level_stats *stats)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
- unsigned long flags;
- spin_lock_irqsave(&wl->irq_lock, flags);
+ mutex_lock(&wl->mutex);
memcpy(stats, &wl->ieee_stats, sizeof(*stats));
- spin_unlock_irqrestore(&wl->irq_lock, flags);
+ mutex_unlock(&wl->mutex);
return 0;
}
@@ -3322,7 +3335,6 @@ static u64 b43_op_get_tsf(struct ieee802
u64 tsf;
mutex_lock(&wl->mutex);
- spin_lock_irq(&wl->irq_lock);
dev = wl->current_dev;
if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
@@ -3330,7 +3342,6 @@ static u64 b43_op_get_tsf(struct ieee802
else
tsf = 0;
- spin_unlock_irq(&wl->irq_lock);
mutex_unlock(&wl->mutex);
return tsf;
@@ -3342,13 +3353,11 @@ static void b43_op_set_tsf(struct ieee80
struct b43_wldev *dev;
mutex_lock(&wl->mutex);
- spin_lock_irq(&wl->irq_lock);
dev = wl->current_dev;
if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
b43_tsf_write(dev, tsf);
- spin_unlock_irq(&wl->irq_lock);
mutex_unlock(&wl->mutex);
}
@@ -3434,7 +3443,7 @@ static int b43_switch_band(struct b43_wl
prev_status = b43_status(down_dev);
/* Shutdown the currently running core. */
if (prev_status >= B43_STAT_STARTED)
- b43_wireless_core_stop(down_dev);
+ down_dev = b43_wireless_core_stop(down_dev);
if (prev_status >= B43_STAT_INITIALIZED)
b43_wireless_core_exit(down_dev);
@@ -3498,7 +3507,6 @@ static int b43_op_config(struct ieee8021
struct b43_wldev *dev;
struct b43_phy *phy;
struct ieee80211_conf *conf = &hw->conf;
- unsigned long flags;
int antenna;
int err = 0;
@@ -3529,13 +3537,11 @@ static int b43_op_config(struct ieee8021
/* Adjust the desired TX power level. */
if (conf->power_level != 0) {
- spin_lock_irqsave(&wl->irq_lock, flags);
if (conf->power_level != phy->desired_txpower) {
phy->desired_txpower = conf->power_level;
b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME |
B43_TXPWR_IGNORE_TSSI);
}
- spin_unlock_irqrestore(&wl->irq_lock, flags);
}
/* Antennas for RX and management frame TX. */
@@ -3620,7 +3626,6 @@ static void b43_op_bss_info_changed(stru
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
- unsigned long flags;
mutex_lock(&wl->mutex);
@@ -3630,7 +3635,6 @@ static void b43_op_bss_info_changed(stru
B43_WARN_ON(wl->vif != vif);
- spin_lock_irqsave(&wl->irq_lock, flags);
if (changed & BSS_CHANGED_BSSID) {
if (conf->bssid)
memcpy(wl->bssid, conf->bssid, ETH_ALEN);
@@ -3648,7 +3652,6 @@ static void b43_op_bss_info_changed(stru
if (changed & BSS_CHANGED_BSSID)
b43_write_mac_bssid_templates(dev);
}
- spin_unlock_irqrestore(&wl->irq_lock, flags);
b43_mac_suspend(dev);
@@ -3683,18 +3686,15 @@ static int b43_op_set_key(struct ieee802
u8 algorithm;
u8 index;
int err;
+ unsigned long flags;
static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
if (modparam_nohwcrypt)
return -ENOSPC; /* User disabled HW-crypto */
mutex_lock(&wl->mutex);
- spin_lock_irq(&wl->irq_lock);
- write_lock(&wl->tx_lock);
- /* Why do we need all this locking here?
- * mutex -> Every config operation must take it.
- * irq_lock -> We modify the dev->key array, which is accessed
- * in the IRQ handlers.
+ write_lock_irqsave(&wl->tx_lock, flags);
+ /* mutex -> Every config operation must take it.
* tx_lock -> We modify the dev->key array, which is accessed
* in the TX handler.
*/
@@ -3789,8 +3789,7 @@ out_unlock:
sta ? sta->addr : bcast_addr);
b43_dump_keymemory(dev);
}
- write_unlock(&wl->tx_lock);
- spin_unlock_irq(&wl->irq_lock);
+ write_unlock_irqrestore(&wl->tx_lock, flags);
mutex_unlock(&wl->mutex);
return err;
@@ -3801,15 +3800,15 @@ static void b43_op_configure_filter(stru
u64 multicast)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
- struct b43_wldev *dev = wl->current_dev;
- unsigned long flags;
+ struct b43_wldev *dev;
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
if (!dev) {
*fflags = 0;
- return;
+ goto out_unlock;
}
- spin_lock_irqsave(&wl->irq_lock, flags);
*fflags &= FIF_PROMISC_IN_BSS |
FIF_ALLMULTI |
FIF_FCSFAIL |
@@ -3830,41 +3829,66 @@ static void b43_op_configure_filter(stru
if (changed && b43_status(dev) >= B43_STAT_INITIALIZED)
b43_adjust_opmode(dev);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+out_unlock:
+ mutex_unlock(&wl->mutex);
}
-/* Locking: wl->mutex */
-static void b43_wireless_core_stop(struct b43_wldev *dev)
+/* Locking: wl->mutex
+ * Returns the current dev. This might be different from the passed in dev,
+ * because the core might be gone away while we unlocked the mutex. */
+static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
- unsigned long flags;
+ struct b43_wldev *orig_dev;
- if (b43_status(dev) < B43_STAT_STARTED)
- return;
+redo:
+ if (!dev || b43_status(dev) < B43_STAT_STARTED)
+ return dev;
- /* Disable and sync interrupts. We must do this before than
- * setting the status to INITIALIZED, as the interrupt handler
- * won't care about IRQs then. */
- spin_lock_irqsave(&wl->irq_lock, flags);
- b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
- b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- b43_synchronize_irq(dev);
+ /* Disable periodic work. Unlock to avoid deadlocks. */
+ mutex_unlock(&wl->mutex);
+ cancel_delayed_work_sync(&dev->periodic_work);
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (!dev || b43_status(dev) < B43_STAT_STARTED) {
+ /* Whoops, aliens ate up the device while we were unlocked. */
+ return dev;
+ }
- write_lock_irqsave(&wl->tx_lock, flags);
+ /* Disable interrupts on the device. */
b43_set_status(dev, B43_STAT_INITIALIZED);
- write_unlock_irqrestore(&wl->tx_lock, flags);
-
- b43_pio_stop(dev);
+ if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
+ /* wl->mutex is locked. That is enough. */
+ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
+ b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
+ } else {
+ spin_lock_irq(&wl->hardirq_lock);
+ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
+ b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
+ spin_unlock_irq(&wl->hardirq_lock);
+ }
+ /* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */
+ orig_dev = dev;
mutex_unlock(&wl->mutex);
- /* Must unlock as it would otherwise deadlock. No races here.
- * Cancel the possibly running self-rearming periodic work. */
- cancel_delayed_work_sync(&dev->periodic_work);
+ synchronize_irq(dev->dev->irq);
mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (!dev)
+ return dev;
+ if (dev != orig_dev) {
+ if (b43_status(dev) >= B43_STAT_STARTED)
+ goto redo;
+ return dev;
+ }
+ B43_WARN_ON(b43_read32(dev, B43_MMIO_GEN_IRQ_MASK));
+ b43_pio_stop(dev);
b43_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
b43dbg(wl, "Wireless interface stopped\n");
+
+ return dev;
}
/* Locking: wl->mutex */
@@ -3875,8 +3899,9 @@ static int b43_wireless_core_start(struc
B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
drain_txstatus_queue(dev);
- err = request_irq(dev->dev->irq, b43_interrupt_handler,
- IRQF_SHARED, KBUILD_MODNAME, dev);
+ err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
+ b43_interrupt_thread_handler,
+ IRQF_SHARED, KBUILD_MODNAME, dev);
if (err) {
b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
goto out;
@@ -4155,8 +4180,8 @@ static void b43_wireless_core_exit(struc
{
u32 macctl;
- B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED);
- if (b43_status(dev) != B43_STAT_INITIALIZED)
+ B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED);
+ if (!dev || b43_status(dev) != B43_STAT_INITIALIZED)
return;
b43_set_status(dev, B43_STAT_UNINIT);
@@ -4309,7 +4334,6 @@ static int b43_op_add_interface(struct i
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
- unsigned long flags;
int err = -EOPNOTSUPP;
/* TODO: allow WDS/AP devices to coexist */
@@ -4333,12 +4357,10 @@ static int b43_op_add_interface(struct i
wl->if_type = conf->type;
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
- spin_lock_irqsave(&wl->irq_lock, flags);
b43_adjust_opmode(dev);
b43_set_pretbtt(dev);
b43_set_synth_pu_delay(dev, 0);
b43_upload_card_macaddress(dev);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
err = 0;
out_mutex_unlock:
@@ -4352,7 +4374,6 @@ static void b43_op_remove_interface(stru
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
- unsigned long flags;
b43dbg(wl, "Removing Interface type %d\n", conf->type);
@@ -4364,11 +4385,9 @@ static void b43_op_remove_interface(stru
wl->operating = 0;
- spin_lock_irqsave(&wl->irq_lock, flags);
b43_adjust_opmode(dev);
memset(wl->mac_addr, 0, ETH_ALEN);
b43_upload_card_macaddress(dev);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
mutex_unlock(&wl->mutex);
}
@@ -4428,10 +4447,15 @@ static void b43_op_stop(struct ieee80211
cancel_work_sync(&(wl->beacon_update_trigger));
mutex_lock(&wl->mutex);
- if (b43_status(dev) >= B43_STAT_STARTED)
- b43_wireless_core_stop(dev);
+ if (b43_status(dev) >= B43_STAT_STARTED) {
+ dev = b43_wireless_core_stop(dev);
+ if (!dev)
+ goto out_unlock;
+ }
b43_wireless_core_exit(dev);
wl->radio_enabled = 0;
+
+out_unlock:
mutex_unlock(&wl->mutex);
cancel_work_sync(&(wl->txpower_adjust_work));
@@ -4441,11 +4465,10 @@ static int b43_op_beacon_set_tim(struct
struct ieee80211_sta *sta, bool set)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
- unsigned long flags;
- spin_lock_irqsave(&wl->irq_lock, flags);
+ mutex_lock(&wl->mutex);
b43_update_templates(wl);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
+ mutex_unlock(&wl->mutex);
return 0;
}
@@ -4526,8 +4549,13 @@ static void b43_chip_reset(struct work_s
prev_status = b43_status(dev);
/* Bring the device down... */
- if (prev_status >= B43_STAT_STARTED)
- b43_wireless_core_stop(dev);
+ if (prev_status >= B43_STAT_STARTED) {
+ dev = b43_wireless_core_stop(dev);
+ if (!dev) {
+ err = -ENODEV;
+ goto out;
+ }
+ }
if (prev_status >= B43_STAT_INITIALIZED)
b43_wireless_core_exit(dev);
@@ -4742,9 +4770,6 @@ static int b43_one_core_attach(struct ss
wldev->wl = wl;
b43_set_status(wldev, B43_STAT_UNINIT);
wldev->bad_frames_preempt = modparam_bad_frames_preempt;
- tasklet_init(&wldev->isr_tasklet,
- (void (*)(unsigned long))b43_interrupt_tasklet,
- (unsigned long)wldev);
INIT_LIST_HEAD(&wldev->list);
err = b43_wireless_core_attach(wldev);
@@ -4841,11 +4866,11 @@ static int b43_wireless_init(struct ssb_
/* Initialize struct b43_wl */
wl->hw = hw;
- spin_lock_init(&wl->irq_lock);
rwlock_init(&wl->tx_lock);
spin_lock_init(&wl->leds_lock);
spin_lock_init(&wl->shm_lock);
mutex_init(&wl->mutex);
+ spin_lock_init(&wl->hardirq_lock);
INIT_LIST_HEAD(&wl->devlist);
INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
@@ -4946,8 +4971,8 @@ static int b43_suspend(struct ssb_device
wldev->suspend_in_progress = true;
wldev->suspend_init_status = b43_status(wldev);
if (wldev->suspend_init_status >= B43_STAT_STARTED)
- b43_wireless_core_stop(wldev);
- if (wldev->suspend_init_status >= B43_STAT_INITIALIZED)
+ wldev = b43_wireless_core_stop(wldev);
+ if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED)
b43_wireless_core_exit(wldev);
mutex_unlock(&wl->mutex);
Index: wireless-testing/drivers/net/wireless/b43/phy_common.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/phy_common.c 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/phy_common.c 2009-09-04 22:15:32.000000000 +0200
@@ -347,7 +347,6 @@ void b43_phy_txpower_adjust_work(struct
mutex_unlock(&wl->mutex);
}
-/* Called with wl->irq_lock locked */
void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
{
struct b43_phy *phy = &dev->phy;
Index: wireless-testing/drivers/net/wireless/b43/phy_common.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/phy_common.h 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/phy_common.h 2009-09-04 22:15:32.000000000 +0200
@@ -131,7 +131,7 @@ enum b43_txpwr_result {
* If the parameter "ignore_tssi" is true, the TSSI values should
* be ignored and a recalculation of the power settings should be
* done even if the TSSI values did not change.
- * This callback is called with wl->irq_lock held and must not sleep.
+ * This function may sleep, but should not.
* Must not be NULL.
* @adjust_txpower: Write the previously calculated TX power settings
* (from @recalc_txpower) to the hardware.
@@ -379,7 +379,6 @@ void b43_software_rfkill(struct b43_wlde
*
* Compare the current TX power output to the desired power emission
* and schedule an adjustment in case it mismatches.
- * Requires wl->irq_lock locked.
*
* @flags: OR'ed enum b43_phy_txpower_check_flags flags.
* See the docs below.
Index: wireless-testing/drivers/net/wireless/b43/phy_g.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/phy_g.c 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/phy_g.c 2009-09-04 22:15:32.000000000 +0200
@@ -2823,8 +2823,6 @@ static void b43_gphy_op_adjust_txpower(s
b43_mac_suspend(dev);
- spin_lock_irq(&dev->wl->irq_lock);
-
/* Calculate the new attenuation values. */
bbatt = gphy->bbatt.att;
bbatt += gphy->bbatt_delta;
@@ -2864,11 +2862,6 @@ static void b43_gphy_op_adjust_txpower(s
gphy->rfatt.att = rfatt;
gphy->bbatt.att = bbatt;
- /* We drop the lock early, so we can sleep during hardware
- * adjustment. Possible races with op_recalc_txpower are harmless,
- * as we will be called once again in case we raced. */
- spin_unlock_irq(&dev->wl->irq_lock);
-
if (b43_debug(dev, B43_DBG_XMITPOWER))
b43dbg(dev->wl, "Adjusting TX power\n");
Index: wireless-testing/drivers/net/wireless/b43/phy_g.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/phy_g.h 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/phy_g.h 2009-09-04 22:15:32.000000000 +0200
@@ -141,8 +141,7 @@ struct b43_phy_g {
int tgt_idle_tssi;
/* Current idle TSSI */
int cur_idle_tssi;
- /* The current average TSSI.
- * Needs irq_lock, as it's updated in the IRQ path. */
+ /* The current average TSSI. */
u8 average_tssi;
/* Current TX power level attenuation control values */
struct b43_bbatt bbatt;
Index: wireless-testing/drivers/net/wireless/b43/sysfs.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/sysfs.c 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/sysfs.c 2009-09-04 22:15:32.000000000 +0200
@@ -94,7 +94,6 @@ static ssize_t b43_attr_interfmode_store
const char *buf, size_t count)
{
struct b43_wldev *wldev = dev_to_b43_wldev(dev);
- unsigned long flags;
int err;
int mode;
@@ -120,7 +119,6 @@ static ssize_t b43_attr_interfmode_store
}
mutex_lock(&wldev->wl->mutex);
- spin_lock_irqsave(&wldev->wl->irq_lock, flags);
if (wldev->phy.ops->interf_mitigation) {
err = wldev->phy.ops->interf_mitigation(wldev, mode);
@@ -132,7 +130,6 @@ static ssize_t b43_attr_interfmode_store
err = -ENOSYS;
mmiowb();
- spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
mutex_unlock(&wldev->wl->mutex);
return err ? err : count;
Index: wireless-testing/drivers/net/wireless/b43/dma.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/dma.c 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/dma.c 2009-09-04 22:15:32.000000000 +0200
@@ -1387,7 +1387,6 @@ out_unlock:
return err;
}
-/* Called with IRQs disabled. */
void b43_dma_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status)
{
@@ -1402,7 +1401,7 @@ void b43_dma_handle_txstatus(struct b43_
if (unlikely(!ring))
return;
- spin_lock(&ring->lock); /* IRQs are already disabled. */
+ spin_lock_irq(&ring->lock);
B43_WARN_ON(!ring->tx);
ops = ring->ops;
@@ -1463,7 +1462,7 @@ void b43_dma_handle_txstatus(struct b43_
}
}
- spin_unlock(&ring->lock);
+ spin_unlock_irq(&ring->lock);
}
void b43_dma_get_tx_stats(struct b43_wldev *dev,
Index: wireless-testing/drivers/net/wireless/b43/pio.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/pio.c 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/pio.c 2009-09-04 22:15:32.000000000 +0200
@@ -570,7 +570,6 @@ out_unlock:
return err;
}
-/* Called with IRQs disabled. */
void b43_pio_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status)
{
@@ -584,7 +583,7 @@ void b43_pio_handle_txstatus(struct b43_
return;
B43_WARN_ON(!pack);
- spin_lock(&q->lock); /* IRQs are already disabled. */
+ spin_lock_irq(&q->lock);
info = IEEE80211_SKB_CB(pack->skb);
@@ -604,7 +603,7 @@ void b43_pio_handle_txstatus(struct b43_
q->stopped = 0;
}
- spin_unlock(&q->lock);
+ spin_unlock_irq(&q->lock);
}
void b43_pio_get_tx_stats(struct b43_wldev *dev,
Index: wireless-testing/drivers/net/wireless/b43/debugfs.h
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43/debugfs.h 2009-09-04 22:15:30.000000000 +0200
+++ wireless-testing/drivers/net/wireless/b43/debugfs.h 2009-09-04 22:15:32.000000000 +0200
@@ -23,9 +23,10 @@ struct dentry;
#define B43_NR_LOGGED_TXSTATUS 100
struct b43_txstatus_log {
+ /* This structure is protected by wl->mutex */
+
struct b43_txstatus *log;
int end;
- spinlock_t lock;
};
struct b43_dfs_file {
--
Greetings, Michael.
^ permalink raw reply
* [PATCH 0/5] b43: Prepare driver for sleeping busses
From: Michael Buesch @ 2009-09-04 20:47 UTC (permalink / raw)
To: John Linville; +Cc: Broadcom Wireless, linux-wireless, Albert Herranz
This patchset is the first series to remove atomic sections
from the b43 driver to allow running b43 on a slow bus like
SDIO that needs to sleep for register accesses.
--
Greetings, Michael.
^ permalink raw reply
* Re: Atheros Linux wireless drivers home page - and two new driver projects
From: Luis R. Rodriguez @ 2009-09-04 16:51 UTC (permalink / raw)
To: Xavier Bestel, Dan Williams, Witold Sowa
Cc: Pavel Roskin, linux-kernel, devel, Len Widra, Jouni Malinen,
linux-wireless, Werner Almesberger, Stefan Lippers-Hollmann,
Nick Kossifidis, Bob Copeland, Greg KH, rshlinux, b_yogesh_snowy,
Michael Renzmann, Stephen Chen, Paul Fertser, Harald Welte
In-Reply-To: <1252081080.31087.7.camel@skunk>
On Fri, Sep 4, 2009 at 9:18 AM, Xavier Bestel<xavier.bestel@free.fr> wrote:
>
> On Fri, 2009-09-04 at 12:06 -0400, Pavel Roskin wrote:
>> On Fri, 2009-09-04 at 13:53 +0200, Xavier Bestel wrote:
>> > On Thu, 2009-09-03 at 15:54 -0700, Luis R. Rodriguez wrote:
>> > > I'm pleased to announce the new home page to Atheros Linux wireless drivers:
>> > >
>> > > http://wireless.kernel.org/en/users/Drivers/Atheros
>> >
>> > ath5k is marked as not master-mode capable. I thought this had been
>> > fixed for 2.6.31 ?
>>
>> The above page makes no such statements. I have fixed
>> http://wireless.kernel.org/en/users/Drivers/ath5k
>
> Right, thanks.
>
>> https://madwifi-project.org/wiki/UserDocs/ath5kAccessPoint still needs a
>> lot of work, or maybe it should be removed as obsolete.
>
> Yes, I miss access-point functionality in NetworkManager :)
BTW a GSoC project this year was to add AP support to Network Manager.
As far I can tell the Witold Sowa finished this so you should be able
to test this.
Witold, can you update the wiki page on this project with details as
to how people can test this?
http://wireless.kernel.org/en/developers/GSoC/2009/Add_AP_Support_to_Network_Manager
Luis
^ permalink raw reply
* Re: Atheros Linux wireless drivers home page - and two new driver projects
From: Xavier Bestel @ 2009-09-04 16:18 UTC (permalink / raw)
To: Pavel Roskin
Cc: Luis R. Rodriguez, linux-kernel, devel, Len Widra, Jouni Malinen,
linux-wireless, Werner Almesberger, Stefan Lippers-Hollmann,
Nick Kossifidis, Bob Copeland, Greg KH, rshlinux, b_yogesh_snowy,
Michael Renzmann, Stephen Chen, Paul Fertser, Harald Welte
In-Reply-To: <1252080405.24673.11.camel@mj>
On Fri, 2009-09-04 at 12:06 -0400, Pavel Roskin wrote:
> On Fri, 2009-09-04 at 13:53 +0200, Xavier Bestel wrote:
> > On Thu, 2009-09-03 at 15:54 -0700, Luis R. Rodriguez wrote:
> > > I'm pleased to announce the new home page to Atheros Linux wireless drivers:
> > >
> > > http://wireless.kernel.org/en/users/Drivers/Atheros
> >
> > ath5k is marked as not master-mode capable. I thought this had been
> > fixed for 2.6.31 ?
>
> The above page makes no such statements. I have fixed
> http://wireless.kernel.org/en/users/Drivers/ath5k
Right, thanks.
> https://madwifi-project.org/wiki/UserDocs/ath5kAccessPoint still needs a
> lot of work, or maybe it should be removed as obsolete.
Yes, I miss access-point functionality in NetworkManager :)
Xav
^ permalink raw reply
* Re: Atheros Linux wireless drivers home page - and two new driver projects
From: Pavel Roskin @ 2009-09-04 16:06 UTC (permalink / raw)
To: Xavier Bestel
Cc: Luis R. Rodriguez, linux-kernel, devel, Len Widra, Jouni Malinen,
linux-wireless, Werner Almesberger, Stefan Lippers-Hollmann,
Nick Kossifidis, Bob Copeland, Greg KH, rshlinux, b_yogesh_snowy,
Michael Renzmann, Stephen Chen, Paul Fertser, Harald Welte
In-Reply-To: <1252065236.14338.179.camel@skunk>
On Fri, 2009-09-04 at 13:53 +0200, Xavier Bestel wrote:
> On Thu, 2009-09-03 at 15:54 -0700, Luis R. Rodriguez wrote:
> > I'm pleased to announce the new home page to Atheros Linux wireless drivers:
> >
> > http://wireless.kernel.org/en/users/Drivers/Atheros
>
> ath5k is marked as not master-mode capable. I thought this had been
> fixed for 2.6.31 ?
The above page makes no such statements. I have fixed
http://wireless.kernel.org/en/users/Drivers/ath5k
https://madwifi-project.org/wiki/UserDocs/ath5kAccessPoint still needs a
lot of work, or maybe it should be removed as obsolete.
--
Regards,
Pavel Roskin
^ permalink raw reply
* Re: Atheros Linux wireless drivers home page - and two new driver projects
From: Xavier Bestel @ 2009-09-04 11:53 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: linux-kernel, devel, Len Widra, Jouni Malinen, linux-wireless,
Werner Almesberger, Stefan Lippers-Hollmann, Nick Kossifidis,
Bob Copeland, Greg KH, rshlinux, b_yogesh_snowy, Michael Renzmann,
Stephen Chen, Paul Fertser, Harald Welte
In-Reply-To: <43e72e890909031554v1343bcfdu8ed6e23d0b1df832@mail.gmail.com>
On Thu, 2009-09-03 at 15:54 -0700, Luis R. Rodriguez wrote:
> I'm pleased to announce the new home page to Atheros Linux wireless drivers:
>
> http://wireless.kernel.org/en/users/Drivers/Atheros
ath5k is marked as not master-mode capable. I thought this had been
fixed for 2.6.31 ?
Thanks,
Xav
^ permalink raw reply
* Re: [PATCH] cfg80211: clear cfg80211_inform_bss() from kmemleak reports
From: Catalin Marinas @ 2009-09-04 8:25 UTC (permalink / raw)
To: Johannes Berg
Cc: Luis R. Rodriguez, Luis Rodriguez, linux-kernel@vger.kernel.org,
linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <1252040671.9336.10.camel@johannes.local>
On Fri, 2009-09-04 at 07:04 +0200, Johannes Berg wrote:
> On Thu, 2009-09-03 at 13:43 -0700, Luis R. Rodriguez wrote:
> > On Thu, Sep 03, 2009 at 11:17:17AM -0700, Johannes Berg wrote:
> > > On Thu, 2009-09-03 at 11:13 -0700, Luis R. Rodriguez wrote:
> > >
> > > > What I meant is it gobbles it up and spits another thing out. When it
> > > > gobbles it up the routine then uses kref_put().
> > > >
> > > > > Why can it not track this?
> > > >
> > > > It probably can, just not sure if it follows kref_put(), I was under
> > > > the impression here it doesn't and because of it we were getting false
> > > > positives. Catalin, can you confirm?
> > >
> > > Ah I'd think that if it can't track it then that's because we use a
> > > pointer to the middle of the struct to keep track of it much of the
> > > time.
> >
> > So you agree with the patch but not the commit log entry?
>
> I'm not sure -- I think kmemleak should be able to figure it out, and if
> you were using IBSS then we actually have a leak that we need to plug,
> but otherwise I'd prefer to get some more input from Catalin first.
First of all, kmemleak_ignore() is not the right function to mark a
false positive as it completely ignores an object even though it may
have pointers to others. The kmemleak_not_leak() function should be
used. However, there are only two places in the kernel where this was
actually needed (one of them is a real leak but we ignore it as it makes
the code more complicated).
So, I think we should try to figure out why kmemleak reports it. There
are a few common cases:
1. transient false positive - this should disappear after a few
scans
2. a pointer leading to the reported object is stored in an area of
memory not scanned by kmemleak - most commonly pages allocated
explicitly (alloc_pages etc.) as kmemleak doesn't track these.
The preferred solution is to inform kmemleak about such page
(kmemleak_alloc/kmemleak_free) rather than marking the false
positive
3. a pointer leading to the reported object isn't actually pointing
to anywhere inside the structure (i.e. using the physical
address). Here we would use kmemleak_not_leak()
> Catalin, is it conceivable that kmemleak reports false positives if we
> use a struct like
>
> struct pubbss {
> ...
> };
>
> struct bss {
> ...
> struct pubbss pub;
> };
>
> and then keep track of &bss->pub; pointers instead of bss directly?
It should not report false positive here. That's a pretty common case
with struct list_head, struct device etc. and kmemleak handles them
properly - if there is a memory location pointing to *anywhere* inside a
structure, the object is considered referenced and not reported.
--
Catalin
^ permalink raw reply
* AP: ath5k + hostapd occasionally sulks
From: Jon Fairbairn @ 2009-09-04 8:05 UTC (permalink / raw)
To: linux-wireless
I'm running hostapd 0.6.9 and currently compat-wireless-2009-08-22.
This seems to work most of the time, but occasionally (usually days
between occurrences) stops accepting connexions. Usually there's no
indication of this in the logs, but when clients try to associate they
eventually time out.
However, the most recent time this happened was when I was downloading a
large amount of data to one of the clients. I got a lot of
ath5k phy0: no further txbuf available, dropping packet
in the log and then the connexion died and wouldn't come back until I
restarted hostapd (I reloaded ath5k for good measure; I should probably
have tried without doing that...)
I have two questions:
(1) is that buffer message something that might have been addressed
since 2009-08-22, and
(2) What can I do to track down something that happens this
infrequently? I'm running hostapd with -d, but that doesn't log anything
different when it happens.
--
Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk
^ permalink raw reply
* Re: [PATCH] cfg80211: clear cfg80211_inform_bss() from kmemleak reports
From: Johannes Berg @ 2009-09-04 5:04 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: Luis Rodriguez, Catalin Marinas, linux-kernel@vger.kernel.org,
linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <20090903204319.GC3701@mosca>
[-- Attachment #1: Type: text/plain, Size: 1274 bytes --]
On Thu, 2009-09-03 at 13:43 -0700, Luis R. Rodriguez wrote:
> On Thu, Sep 03, 2009 at 11:17:17AM -0700, Johannes Berg wrote:
> > On Thu, 2009-09-03 at 11:13 -0700, Luis R. Rodriguez wrote:
> >
> > > What I meant is it gobbles it up and spits another thing out. When it
> > > gobbles it up the routine then uses kref_put().
> > >
> > > > Why can it not track this?
> > >
> > > It probably can, just not sure if it follows kref_put(), I was under
> > > the impression here it doesn't and because of it we were getting false
> > > positives. Catalin, can you confirm?
> >
> > Ah I'd think that if it can't track it then that's because we use a
> > pointer to the middle of the struct to keep track of it much of the
> > time.
>
> So you agree with the patch but not the commit log entry?
I'm not sure -- I think kmemleak should be able to figure it out, and if
you were using IBSS then we actually have a leak that we need to plug,
but otherwise I'd prefer to get some more input from Catalin first.
Catalin, is it conceivable that kmemleak reports false positives if we
use a struct like
struct pubbss {
...
};
struct bss {
...
struct pubbss pub;
};
and then keep track of &bss->pub; pointers instead of bss directly?
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH V2] nl80211 connect API support
From: Zhu Yi @ 2009-09-04 3:21 UTC (permalink / raw)
To: Jouni Malinen
Cc: hostap@lists.shmoo.com, linux-wireless@vger.kernel.org,
Johannes Berg, Samuel Ortiz
In-Reply-To: <20090903184459.GA11492@jm.kir.nu>
On Fri, 2009-09-04 at 02:44 +0800, Jouni Malinen wrote:
> It looks like there is still some misunderstanding regarding the SME
> design in wpa_supplicant. It was designed to be used when the driver
> does provide the separate authentication and association commands. There
> is not much point in trying to convert the SME implementation to work
> with the case where connect command is used. It is just duplicating
> functionality that is already present in the old associate
> (pre-auth/assoc SME case) operation.
I searched WPA_DRIVER_FLAGS_SME is set only by driver_nl80211. So I
thought you might also want the connect API more visible for the whole
wpa_supplicant. But it turns I was wrong.
> I took about half of the patch, i.e., the changes to add driver
> capability query, connect events, and actual connect/disconnect
> functions. Instead of the changes in sme.c and driver interface, I glued
> the new functions together within driver_nl80211.c since rest of
> wpa_supplicant do not really need to (nor should) know about yet another
> driver operation for connecting in a single step. The driver
> capabilities are used to select which functions to use within
> driver_nl80211.c. Since the WPA_DRIVER_FLAGS_SME is now set based on
> driver capabilities, core wpa_supplicant code is able to switch between
> the SME (separate auth/assoc calls) and single associate ("connect" in
> nl80211 terminology) call.
>
> I did not go through the details of sme_connect() function, but I would
> expect that it was providing the same conversion from configuration to
> driver parameters that was already done in wpa_supplicant.c. If there
> was something else there, it should be added to the version in
> wpa_supplicant.c instead of introducing a new, duplicated function.
>
> It looks like the end result works fine at least with mac80211_hwsim
> (with hardcoded driver capability detection that does not find the
> separate authenticate command). This version is now in my git repository
> and it would be good if you could verify that it works with your driver,
> too.
I confirm it also works for iwmc3200wifi. Tested for WEP, PSK and EAP.
Thanks,
-yi
^ permalink raw reply
* Re: [PATCH 2/2] ath9k: Fix channelFlags for 2GHZ
From: Sujith @ 2009-09-04 3:27 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: Pavel Roskin, linville@tuxdriver.com,
linux-wireless@vger.kernel.org
In-Reply-To: <43e72e890909031128k4ce1f7b5i5c42ebaa73498c70@mail.gmail.com>
Luis R. Rodriguez wrote:
> I should mention ath9k_update_ichannel() was the last thing I intended
> on porting for the new regulatory changes we did on ath9k, when we
> ditched the old regulatory code, but I left it as it did involve quite
> a lot more changes in the code. When I reviewed this it seemed we
> could just rely on the hw->conf.channel->band for many things but in
> some cases we needed some defines for hw.
>
> So -- I'd personally welcome this change as a better alternative needs
> better planning, and more testing.
Agreed.
Sujith
^ permalink raw reply
* Re: [PATCH 2/2] ath9k: Fix channelFlags for 2GHZ
From: Sujith @ 2009-09-04 3:25 UTC (permalink / raw)
To: Pavel Roskin; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <1251991187.6521.22.camel@mj>
Pavel Roskin wrote:
> My impression is that's a workaround for a bug that lies elsewhere. I
> don't think we should apply such patches.
The internal channelFlags/related macros are extremely messy.
The ugliness arose from the requirement for differentiating between
modes (11a, 11g, 11ng etc..) and legacy cruft. mac80211 has no concept of modes,
it has bands instead. I do understand your concern though. But fixing
this cleanly would mean that we rewrite the entire channel handling
mechanism, any band-aid can only be a hack at best.
But yes, maybe we can hold this until everything is cleaned up.
And this has been in the ath9k TODO page for quite some time. :)
Sujith
^ permalink raw reply
* Re: Atheros Linux wireless drivers home page - and two new driver projects
From: Luis R. Rodriguez @ 2009-09-04 1:05 UTC (permalink / raw)
To: Christian Lamparter
Cc: Gábor Stefanik, linux-kernel, devel, Len Widra,
Jouni Malinen, linux-wireless, Werner Almesberger,
Stefan Lippers-Hollmann, Nick Kossifidis, Bob Copeland, Greg KH,
rshlinux, b_yogesh_snowy, Michael Renzmann, Stephen Chen,
Paul Fertser, Harald Welte
In-Reply-To: <200909040250.20632.chunkeey@googlemail.com>
2009/9/3 Christian Lamparter <chunkeey@googlemail.com>:
> On Friday 04 September 2009 01:34:19 Gábor Stefanik wrote:
>>
>> About ar9271: is this device already in the market, or the chip itself
>> is also still in development?
>>
> yes, ar9271 devices are available in Europe.
> (e.g: TP-Link TL-WN721N (about 12 euros))
Thanks I've added this to the wiki on a new supported products page --
if others are aware of other devices please feel free to add them
there.
Luis
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox