Subject: [PATCH 19/32] rt2x00: Fix panics in interrupt handlers

From: Ivo van Doorn <[email-masked]>
Date: Fri, 28 Apr 2006 00:03:11 +0200

From: Ivo van Doorn <[email-masked]>

Fix panics when the interrupt handlers are being
run while the ring is empty.
During the interrupt handling break the loop
correctly when an error has been detected,
more work is being done after the loop.

Signed-off-by: Ivo van Doorn <[email-masked]>

diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c	2006-04-27 21:50:36.000000000 +0200
@@ -844,7 +844,7 @@ rt2400pci_rxdone(void *data)
 		&& !rt2x00_get_field32(rxd->word0, RXD_W0_PHYSICAL_ERROR)) {
 			skb = dev_alloc_skb(size + NET_IP_ALIGN);
 			if (!skb)
-				return;
+				break;
 
 			skb_reserve(skb, NET_IP_ALIGN);
 
@@ -859,7 +859,7 @@ rt2400pci_rxdone(void *data)
 
 		rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
 
-		rt2x00_ring_index_inc(&rt2x00pci->rx);
+		rt2x00_ring_index_inc(ring);
 	}
 
 	/*
@@ -879,7 +879,7 @@ rt2400pci_txdone(void *data)
 	int			tx_status;
 	int			ack;
 
-	do {
+	 while (!rt2x00_ring_empty(ring)) {
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = entry->desc_addr;
 
@@ -925,7 +925,7 @@ rt2400pci_txdone(void *data)
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
-	} while (!rt2x00_ring_empty(ring));
+	}
 
 	/*
 	 * Check if we are waiting on an empty queue
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c	2006-04-27 21:50:36.000000000 +0200
@@ -926,7 +926,7 @@ rt2500pci_rxdone(void *data)
 		&& !rt2x00_get_field32(rxd->word0, RXD_W0_PHYSICAL_ERROR)) {
 			skb = dev_alloc_skb(size + NET_IP_ALIGN);
 			if (!skb)
-				return;
+				break;
 
 			skb_reserve(skb, NET_IP_ALIGN);
 
@@ -943,7 +943,7 @@ rt2500pci_rxdone(void *data)
 		}
 		rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
 
-		rt2x00_ring_index_inc(&rt2x00pci->rx);
+		rt2x00_ring_index_inc(ring);
 	}
 
 	/*
@@ -964,7 +964,7 @@ rt2500pci_txdone(void *data)
 	int			tx_status;
 	int			ack;
 
-	do {
+	 while (!rt2x00_ring_empty(ring)) {
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = entry->desc_addr;
 
@@ -1010,7 +1010,7 @@ rt2500pci_txdone(void *data)
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
-	} while (!rt2x00_ring_empty(ring));
+	}
 
 	/*
 	 * Check if we are waiting on an empty queue
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c	2006-04-27 21:50:36.000000000 +0200
@@ -808,7 +808,7 @@ rt2500usb_txdone(void *data)
 	struct txd		*txd;
 	int			ack;
 
-	do {
+	 while (!rt2x00_ring_empty(ring)) {
 		entry = rt2x00_get_data_entry_done(ring);
 		txd = entry->desc_addr;
 
@@ -843,7 +843,7 @@ rt2500usb_txdone(void *data)
 		entry->skb = NULL;
 	
 		rt2x00_ring_index_done_inc(entry->ring);
-	} while (!rt2x00_ring_empty(ring));
+	}
 
 	/*
 	 * Check if we are waiting on an empty queue