From: Linus Torvalds <torvalds@linux-foundation.org>
To: Michael Buesch <mb@bu3sch.de>
Cc: "Larry Finger" <Larry.Finger@lwfinger.net>,
"Gábor Stefanik" <netrolller.3d@gmail.com>,
"John W. Linville" <linville@tuxdriver.com>,
"David S. Miller" <davem@davemloft.net>,
wireless <linux-wireless@vger.kernel.org>,
"Greg Kroah-Hartman" <gregkh@suse.de>
Subject: Re: Make b43 driver fall back gracefully to PIO mode after fatal DMA errors
Date: Sat, 27 Feb 2010 10:31:11 -0800 (PST) [thread overview]
Message-ID: <alpine.LFD.2.00.1002271016330.4513@localhost.localdomain> (raw)
In-Reply-To: <201002271559.20531.mb@bu3sch.de>
On Sat, 27 Feb 2010, Michael Buesch wrote:
>
> However, did you add the udelay to b43_write()? Please try to add it
> further down in the callchain into the lowlevel SSB read and write functions.
> drivers/ssb/pci.c
Well, I don't know what that would help from a timing standpoint, since
the delay gets done either way, but looking at it, I do note that the
locking for the writes is very very wrong.
For example, look at
static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
{
struct ssb_bus *bus = dev->bus;
if (unlikely(ssb_pci_assert_buspower(bus)))
return 0xFFFFFFFF;
if (unlikely(bus->mapped_device != dev)) {
**** race 1 ****
if (unlikely(ssb_pci_switch_core(bus, dev)))
return 0xFFFFFFFF;
}
**** race 2 ****
return ioread32(bus->mmio + offset);
}
and notice how it's doing that 'mapped_device' read with no locks held.
The actual ssb_pci_switch_core() function will take a lock, but it's too
late by then: if you have these things happening in an interrupt, you
might have another access happening either before or after the
mapped_device has been read or written. So the mmio access could easily go
to the wrong core.
That said, I assume that 'mapped_device' almost never actually changes in
practice, so the race presumably doesn't really matter. I don't know how
these "devices" even work - is there a separate "device" for different SSB
functions (ie power management vs DMA vs wireless radio), or is there
multiple devices only if you actually have multiple radio's?
So for all I know, it's possible that in my case there is always just one
device, and the race really fundamentally cannot ever happen. Or maybe
there are multiple ones, but in practice you never have concurrent
accesses (perhaps due to locking at a higher level) so again the locking
bug is hidden.
Anyway, quite frankly, from a design standpoint it looks like any user of
ssb_pci_switch_core() is fundamentally buggered. The lock should be taken
by the caller, ie the locking _should_ have been around the whole
mapped_device test _and_ the actual ioread32() too, something like
u32 retval = 0xffffffff;
spin_lock_irqsave(&dev->core_lock, flags);
if (bus->mapped_device == dev || !ssb_pci_switch_core(bus, dev))
retval = ioread32(bus->mmio + offset);
spin_lock_irqrestore(&dev->core_lock, flags);
return retval;
and that assert_buspower thing should probably be done inside the core
switching (set "mapped_device" to NULL when powering it down, and either
refuse to switch cores or power it up dynamically).
I can write a patch and test whether it matters, but I'd like to know if
my chip even _has_ multiple cores behind the ssb bridge. If people tell me
that there is only one core on that chip, and that the race can never
happen, then I won't bother.
Linus
next prev parent reply other threads:[~2010-02-27 18:32 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <alpine.LFD.2.00.1002261034140.4513@localhost.localdomain>
2010-02-26 19:09 ` Make b43 driver fall back gracefully to PIO mode after fatal DMA errors Larry Finger
2010-02-26 19:13 ` Linus Torvalds
2010-02-26 20:06 ` Linus Torvalds
2010-02-26 20:09 ` Gábor Stefanik
2010-02-26 20:50 ` Linus Torvalds
2010-02-26 21:01 ` Larry Finger
2010-02-26 21:45 ` Linus Torvalds
2010-02-26 21:50 ` Linus Torvalds
2010-02-26 22:08 ` Gábor Stefanik
2010-02-26 22:46 ` Linus Torvalds
2010-02-26 22:54 ` Gábor Stefanik
2010-02-27 15:04 ` Michael Buesch
2010-02-27 14:59 ` Michael Buesch
2010-02-27 18:31 ` Linus Torvalds [this message]
2010-02-27 18:51 ` Michael Buesch
2010-02-26 19:59 ` Michael Buesch
2010-02-26 20:07 ` Linus Torvalds
2010-02-26 20:20 ` Michael Buesch
2010-02-26 20:33 ` Linus Torvalds
2010-02-26 20:42 ` Linus Torvalds
2010-02-27 14:44 ` Michael Buesch
2010-02-27 14:49 ` Michael Buesch
2010-02-27 17:36 ` Michael Buesch
2010-02-27 20:12 ` Nathan Schulte
2010-02-27 21:08 ` Linus Torvalds
2010-02-27 21:43 ` Michael Buesch
2010-02-27 22:12 ` Linus Torvalds
2010-02-26 20:46 Nathan Schulte
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.LFD.2.00.1002271016330.4513@localhost.localdomain \
--to=torvalds@linux-foundation.org \
--cc=Larry.Finger@lwfinger.net \
--cc=davem@davemloft.net \
--cc=gregkh@suse.de \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
--cc=mb@bu3sch.de \
--cc=netrolller.3d@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox