On Wednesday 13 Mar 2013 21:37:52 Larry Finger wrote:
> On 03/13/2013 08:06 PM, ISE Development wrote:
> 
> >
> > I've hacked the driver to 'skip' one header and data frame if receiving an 
> > interrupt for the first slot + 2. It's not pretty and I have literally no 
> > idea if it will causes other problems, but it has allowed me to keep the 
> > Wifi connection up for a little over 3 hours now (as compared to the 45 
> > seconds previously). It does not appear to be corrupting the data stream 
> > (checked by download large signed binaries and verifying the signature) and 
> > as far as my limited knowledge can tell, it should not be causing a memory 
> > leak.
> >
> > The patch is listed below, for reference. However, I do not claim that it 
> > is valid, safe or even reasonsable. It does provide me with much needed 
> > relief though.
> >
> > The diff is against the current head of linville/wireless-testing.git 
> > (d41d9c7419e3ac9c81841f43bbd7639dd0a5819e).
> >
> 
> I am testing the patch on BCM4312 and other cards.
> 
> Larry
> 

Here's a slighted cleaner version, with comments, in case you are considering 
integrating it.

diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 38bc5a7..edc759d 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1489,6 +1489,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
        struct b43_dmadesc_meta *meta;
        int slot, firstused;
        bool frame_succeed;
+       int skip;
 
        ring = parse_cookie(dev, status->cookie, &slot);
        if (unlikely(!ring))
@@ -1501,13 +1502,22 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
        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. 
*/
                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;
+               } else {
+                       return;
+               }
        }
 
        ops = ring->ops;
@@ -1522,6 +1532,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                               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));
@@ -1552,7 +1563,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                         * Call back to inform the ieee80211 subsystem about
                         * the status of the transmission.
                         */
-                       frame_succeed = b43_fill_txstatus_report(dev, info, 
status);
+                       if(!skip)
+                       {
+                               frame_succeed = b43_fill_txstatus_report(dev, 
info, status);
+                       }
+                       else
+                       {
+                           /* When skipping over a missed TX status report, 
use a status
+                            * structure which indicates that the frame was not 
sent
+                            * (frame_count 0) and not acknowledged */
+                               struct b43_txstatus fake = B43_FAKE_TXSTATUS;
+                               frame_succeed = b43_fill_txstatus_report(dev, 
info, &fake);
+                       }
 #ifdef CONFIG_B43_DEBUG
                        if (frame_succeed)
                                ring->nr_succeed_tx_packets++;
@@ -1580,12 +1602,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                /* 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);
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index 98d9074..eae730c 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -218,6 +218,9 @@ struct b43_txstatus {
        u8 acked;               /* Wireless ACK received */
 };
 
+/* This needs to match the b43_txstatus structure above, all zeroed-out */
+#define B43_FAKE_TXSTATUS { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+
 /* txstatus supp_reason values */
 enum {
        B43_TXST_SUPP_NONE,     /* Not suppressed */


-- 
-- isedev

_______________________________________________
b43-dev mailing list
b43-dev@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/b43-dev

Reply via email to