All of lore.kernel.org
 help / color / mirror / Atom feed
From: Larry Finger <Larry.Finger@lwfinger.net>
To: Michael Buesch <mb@bu3sch.de>, zajec5@gmail.com
Cc: isedev@gmail.com, b43-dev@lists.infradead.org,
	linux-wireless@vger.kernel.org
Subject: [RFC/RFT] b43: A fix for DMA transmission sequence errors
Date: Thu, 14 Mar 2013 13:46:19 -0500	[thread overview]
Message-ID: <51421afb.xUa3KbaBuvmUk4RG%Larry.Finger@lwfinger.net> (raw)

From: Iestyn C. Elfick <isedev@gmail.com>

Intermittently, b43 will report "Out of order TX status report on DMA ring".
When this happens, the driver must be reset before communication can resume.
The cause of the problem is believed to be an error in the closed-source
firmware; however, all versions of the firmware are affected.

This change uses the observation that the expected status is always 2 less
than the observed value, and supplies a fake status report to skip one
header/data pair.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Stable <stable@vger.kernel.org>
---

Although this is a hack, it seems to work for the OP. It should not cause any
ill effects on any device that does not have the problem.

It does need a lot more testing, particularly on systems prone to the out-of-order
status report problem.

If anyone can think of a cleaner, less intrusive solution, please let us know.

Thanks,

Larry
---

Index: wireless-testing-rebased/drivers/net/wireless/b43/dma.c
===================================================================
--- wireless-testing-rebased.orig/drivers/net/wireless/b43/dma.c
+++ wireless-testing-rebased/drivers/net/wireless/b43/dma.c
@@ -1487,8 +1487,11 @@ void b43_dma_handle_txstatus(struct b43_
 	const struct b43_dma_ops *ops;
 	struct b43_dmaring *ring;
 	struct b43_dmadesc_meta *meta;
+	static const struct b43_txstatus fake; /* filled with 0 */
+	const struct b43_txstatus *txstat;
 	int slot, firstused;
 	bool frame_succeed;
+	int skip;
 
 	ring = parse_cookie(dev, status->cookie, &slot);
 	if (unlikely(!ring))
@@ -1501,13 +1504,26 @@ void b43_dma_handle_txstatus(struct b43_
 	firstused = ring->current_slot - ring->used_slots + 1;
 	if (firstused < 0)
 		firstused = ring->nr_slots + firstused;
+
+	skip = 0;
 	if (unlikely(slot != firstused)) {
 		/* This possibly is a firmware bug and will result in
-		 * malfunction, memory leaks and/or stall of DMA functionality. */
+		 * malfunction, memory leaks and/or stall of DMA functionality.
+		 */
 		b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. "
 		       "Expected %d, but got %d\n",
 		       ring->index, firstused, slot);
-		return;
+		if (slot == firstused + 2) {
+			/* If a single header/data pair was missed, skip over
+			 * the first two slots in an attempt to recover.
+			 */
+			slot = firstused;
+			skip = 2;
+			b43dbg(dev->wl, "Skip on DMA ring %d slot %d.\n",
+			       ring->index, slot);
+		} else {
+			return;
+		}
 	}
 
 	ops = ring->ops;
@@ -1522,11 +1538,13 @@ void b43_dma_handle_txstatus(struct b43_
 			       slot, firstused, ring->index);
 			break;
 		}
+
 		if (meta->skb) {
 			struct b43_private_tx_info *priv_info =
-				b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
+			     b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
 
-			unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 meta->skb->len, 1);
 			kfree(priv_info->bouncebuffer);
 			priv_info->bouncebuffer = NULL;
 		} else {
@@ -1538,8 +1556,9 @@ void b43_dma_handle_txstatus(struct b43_
 			struct ieee80211_tx_info *info;
 
 			if (unlikely(!meta->skb)) {
-				/* This is a scatter-gather fragment of a frame, so
-				 * the skb pointer must not be NULL. */
+				/* This is a scatter-gather fragment of a frame,
+				 * so the skb pointer must not be NULL.
+				 */
 				b43dbg(dev->wl, "TX status unexpected NULL skb "
 				       "at slot %d (first=%d) on ring %d\n",
 				       slot, firstused, ring->index);
@@ -1550,9 +1569,18 @@ void b43_dma_handle_txstatus(struct b43_
 
 			/*
 			 * Call back to inform the ieee80211 subsystem about
-			 * the status of the transmission.
+			 * the status of the transmission. When skipping over
+			 * a missed TX status report, use a status structure
+			 * filled with zeros to indicate that the frame was not
+			 * sent (frame_count 0) and not acknowledged
 			 */
-			frame_succeed = b43_fill_txstatus_report(dev, info, status);
+			if (unlikely(!skip))
+				txstat = status;
+			else
+				txstat = &fake;
+
+			frame_succeed = b43_fill_txstatus_report(dev, info,
+								 txstat);
 #ifdef CONFIG_B43_DEBUG
 			if (frame_succeed)
 				ring->nr_succeed_tx_packets++;
@@ -1580,12 +1608,14 @@ void b43_dma_handle_txstatus(struct b43_
 		/* Everything unmapped and free'd. So it's not used anymore. */
 		ring->used_slots--;
 
-		if (meta->is_last_fragment) {
+		if (meta->is_last_fragment && !skip) {
 			/* This is the last scatter-gather
 			 * fragment of the frame. We are done. */
 			break;
 		}
 		slot = next_slot(ring, slot);
+		if (skip > 0)
+			--skip;
 	}
 	if (ring->stopped) {
 		B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);

             reply	other threads:[~2013-03-14 18:46 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-14 18:46 Larry Finger [this message]
2013-03-14 18:55 ` [RFC/RFT] b43: A fix for DMA transmission sequence errors Michael Büsch
2013-03-14 18:55   ` Michael Büsch
2013-03-14 20:17 ` Rafał Miłecki
2013-03-14 20:17   ` Rafał Miłecki
2013-03-15  6:37   ` Rafał Miłecki
2013-03-15  6:37     ` Rafał Miłecki
2013-03-15 16:48     ` Larry Finger
2013-03-15 16:48       ` Larry Finger
2013-03-20 11:26       ` ISE Development
2013-03-20 11:26         ` ISE Development
2013-03-20 13:43         ` Chris Vine
2013-03-20 13:43           ` Chris Vine
2013-03-20 14:53         ` Larry Finger
2013-03-20 14:53           ` Larry Finger
2013-03-20 15:04           ` ISE Development
2013-03-20 15:04             ` ISE Development
2013-03-20 16:10             ` Chris Vine
2013-03-20 16:10               ` Chris Vine
2013-03-15  0:09 ` ISE Development
2013-03-15  0:09   ` ISE Development
2013-03-15  2:07   ` Larry Finger
2013-03-15  2:07     ` Larry Finger

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=51421afb.xUa3KbaBuvmUk4RG%Larry.Finger@lwfinger.net \
    --to=larry.finger@lwfinger.net \
    --cc=b43-dev@lists.infradead.org \
    --cc=isedev@gmail.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=mb@bu3sch.de \
    --cc=zajec5@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.