From: Larry Finger <Larry.Finger@lwfinger.net>
To: "Gábor Stefanik" <netrolller.3d@gmail.com>
Cc: John W Linville <linville@tuxdriver.com>,
Michael Buesch <mb@bu3sch.de>,
Johannes Berg <johannes@sipsolutions.net>,
linux-wireless@vger.kernel.org
Subject: Re: [PATCH] b43: Work around mac80211 race condition that may transmit one packet after queue is stopped
Date: Wed, 29 Jul 2009 10:42:02 -0500 [thread overview]
Message-ID: <4A706DCA.3060805@lwfinger.net> (raw)
In-Reply-To: <69e28c910907290543t7532bd07g2ffdc2a04973a6f8@mail.gmail.com>
Gábor Stefanik wrote:
> On Wed, Jul 29, 2009 at 3:21 AM, Larry Finger<Larry.Finger@lwfinger.net> wrote:
>> As shown in http://thread.gmane.org/gmane.linux.kernel.wireless.general/36497,
>> mac80211 has a bug that allows a call to the TX routine after the queues have
>> been stopped. This situation will only occur under extreme stress. Although
>> b43 does not crash when this condition occurs, it does generate a WARN_ON and
>> also logs a queue overrun message. This patch recognizes b43 is not at fault
>> and logs a message only when the most verbose debugging mode is enabled. In
>> the unlikely event that the queue is not stopped when the DMA queue becomes
>> full, then a warning is issued.
>>
>> During testing of this patch with one output stream running repeated tcpperf
>> writes and a second running a flood ping, this routine was entered with
>> the DMA ring stopped about once per hour. The condition where the DMA queue is
>> full but the ring has not been stopped has never been seen by me.
>>
>> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
>> ---
>>
>> John,
>>
>> This patch is 2.6.32 material.
>>
>> Larry
>> ---
>>
>> Index: wireless-testing/drivers/net/wireless/b43/dma.c
>> ===================================================================
>> --- wireless-testing.orig/drivers/net/wireless/b43/dma.c
>> +++ wireless-testing/drivers/net/wireless/b43/dma.c
>> @@ -1334,13 +1334,23 @@ int b43_dma_tx(struct b43_wldev *dev, st
>> spin_lock_irqsave(&ring->lock, flags);
>>
>> B43_WARN_ON(!ring->tx);
>> - /* Check if the queue was stopped in mac80211,
>> - * but we got called nevertheless.
>> - * That would be a mac80211 bug. */
>> - B43_WARN_ON(ring->stopped);
>> +
>> + if (unlikely(ring->stopped)) {
>> + /* We get here only because of a bug in mac80211.
>> + * Because of a race, one packet may be queued after
>> + * the queue is stopped, thus we got called when we shouldn't.
>> + * For now, just refuse the transmit. */
>> + if (b43_debug(dev, B43_DBG_DMAVERBOSE))
>> + b43err(dev->wl, "Packet after queue stopped\n");
>> + err = -ENOSPC;
>> + goto out_unlock;
>> + }
>>
>> if (unlikely(free_slots(ring) < TX_SLOTS_PER_FRAME)) {
>> - b43warn(dev->wl, "DMA queue overflow\n");
>> + /* If we get here, we have a real error with the queue
>> + * full, but queues not stopped. */
>> + b43err(dev->wl, "DMA queue overflow\n");
>> + WARN_ON(1);
>
> Is this really the best way to do this? Any reason why not have the
> WARN_ON in the if-condition?
I did it this way because my preference is to see the text saying why
there was a warning before the traceback part of the warning; however,
as I do not expect to ever see this warning, I will resubmit. The
argument for putting the WARN_ON in the if statement is that the size
of the object code is decreased by 7 bytes and one line is removed
from the source. The important thing is that the x86_64 code for the
expected branch is exactly the same for the two cases.
One interesting thing is that gcc 4.3.2 for x86_64 does not seem to
pay any attention to the "unlikely" hint. The compiled code is the
same for "if(cond)" and "if(unlikely(cond))".
Larry
prev parent reply other threads:[~2009-07-29 15:41 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-07-29 1:21 [PATCH] b43: Work around mac80211 race condition that may transmit one packet after queue is stopped Larry Finger
2009-07-29 9:00 ` Michael Buesch
2009-07-29 12:43 ` Gábor Stefanik
2009-07-29 15:42 ` Larry Finger [this message]
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=4A706DCA.3060805@lwfinger.net \
--to=larry.finger@lwfinger.net \
--cc=johannes@sipsolutions.net \
--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;
as well as URLs for NNTP newsgroup(s).