From af0950786e9cd65db7bf7f75b8ac7935829ccdb4 Mon Sep 17 00:00:00 2001
From: Peter Denison <openwrt@marshadder.org>
Date: Sun, 1 Jul 2007 17:45:47 +0000
Subject: [PATCH] Update bcm43xx-mac80211 to latest git pull, mostly debugging
 improvements

SVN-Revision: 7830
---
 .../src/bcm43xx/bcm43xx_debugfs.c             |  1 +
 .../src/bcm43xx/bcm43xx_debugfs.h             |  1 +
 .../src/bcm43xx/bcm43xx_dma.c                 | 58 +++++++++++--------
 .../src/bcm43xx/bcm43xx_main.c                | 47 +++++----------
 .../src/bcm43xx/bcm43xx_xmit.c                | 25 +++++++-
 5 files changed, 75 insertions(+), 57 deletions(-)

diff --git a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_debugfs.c b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_debugfs.c
index 3ea9d08a27..e623cfd05e 100644
--- a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_debugfs.c
+++ b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_debugfs.c
@@ -437,6 +437,7 @@ static void bcm43xx_add_dynamic_debug(struct bcm43xx_wldev *dev)
 
 	add_dyn_dbg("debug_xmitpower", BCM43xx_DBG_XMITPOWER, 0);
 	add_dyn_dbg("debug_dmaoverflow", BCM43xx_DBG_DMAOVERFLOW, 0);
+	add_dyn_dbg("debug_dmaverbose", BCM43xx_DBG_DMAVERBOSE, 0);
 	add_dyn_dbg("debug_pwork_fast", BCM43xx_DBG_PWORK_FAST, 0);
 	add_dyn_dbg("debug_pwork_stop", BCM43xx_DBG_PWORK_STOP, 0);
 
diff --git a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_debugfs.h b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_debugfs.h
index 892299d550..bf31754b0c 100644
--- a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_debugfs.h
+++ b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_debugfs.h
@@ -7,6 +7,7 @@ struct bcm43xx_txstatus;
 enum bcm43xx_dyndbg { /* Dynamic debugging features */
 	BCM43xx_DBG_XMITPOWER,
 	BCM43xx_DBG_DMAOVERFLOW,
+	BCM43xx_DBG_DMAVERBOSE,
 	BCM43xx_DBG_PWORK_FAST,
 	BCM43xx_DBG_PWORK_STOP,
 	__BCM43xx_NR_DYNDBG,
diff --git a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_dma.c b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_dma.c
index c8b5cddc3b..814e1ad075 100644
--- a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_dma.c
+++ b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_dma.c
@@ -259,6 +259,28 @@ static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot)
 	return slot - 1;
 }
 
+#ifdef CONFIG_BCM43XX_MAC80211_DEBUG
+static void update_max_used_slots(struct bcm43xx_dmaring *ring,
+				  int current_used_slots)
+{
+	if (current_used_slots <= ring->max_used_slots)
+		return;
+	ring->max_used_slots = current_used_slots;
+	if (bcm43xx_debug(ring->dev, BCM43xx_DBG_DMAVERBOSE)) {
+		dprintk(KERN_DEBUG PFX
+			"max_used_slots increased to %d on %s ring %d\n",
+			ring->max_used_slots,
+			ring->tx ? "TX" : "RX",
+			ring->index);
+	}
+}
+#else
+static inline
+void update_max_used_slots(struct bcm43xx_dmaring *ring,
+			   int current_used_slots)
+{ }
+#endif /* DEBUG */
+
 /* Request a slot for usage. */
 static inline
 int request_slot(struct bcm43xx_dmaring *ring)
@@ -273,23 +295,11 @@ int request_slot(struct bcm43xx_dmaring *ring)
 	ring->current_slot = slot;
 	ring->used_slots++;
 
-#ifdef CONFIG_BCM43XX_MAC80211_DEBUG
-	if (ring->used_slots > ring->max_used_slots)
-		ring->max_used_slots = ring->used_slots;
-#endif /* CONFIG_BCM43XX_MAC80211_DEBUG*/
+	update_max_used_slots(ring, ring->used_slots);
 
 	return slot;
 }
 
-/* Return a slot to the free slots. */
-static inline
-void return_slot(struct bcm43xx_dmaring *ring, int slot)
-{
-	assert(ring->tx);
-
-	ring->used_slots--;
-}
-
 /* Mac80211-queue to bcm43xx-ring mapping */
 static struct bcm43xx_dmaring * priority_to_txring(struct bcm43xx_wldev *dev,
 						   int queue_priority)
@@ -1254,6 +1264,10 @@ int bcm43xx_dma_tx(struct bcm43xx_wldev *dev,
 		/* This TX ring is full. */
 		ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring));
 		ring->stopped = 1;
+		if (bcm43xx_debug(dev, BCM43xx_DBG_DMAVERBOSE)) {
+			dprintk(KERN_DEBUG PFX "Stopped TX ring %d\n",
+				ring->index);
+		}
 	}
 out_unlock:
 	spin_unlock_irqrestore(&ring->lock, flags);
@@ -1305,10 +1319,9 @@ void bcm43xx_dma_handle_txstatus(struct bcm43xx_wldev *dev,
 			 */
 			assert(meta->skb == NULL);
 		}
-		/* Everything belonging to the slot is unmapped
-		 * and freed, so we can return it.
-		 */
-		return_slot(ring, slot);
+
+		/* Everything unmapped and free'd. So it's not used anymore. */
+		ring->used_slots--;
 
 		if (meta->is_last_fragment)
 			break;
@@ -1319,6 +1332,10 @@ void bcm43xx_dma_handle_txstatus(struct bcm43xx_wldev *dev,
 		assert(free_slots(ring) >= SLOTS_PER_PACKET);
 		ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring));
 		ring->stopped = 0;
+		if (bcm43xx_debug(dev, BCM43xx_DBG_DMAVERBOSE)) {
+			dprintk(KERN_DEBUG PFX "Woke up TX ring %d\n",
+				ring->index);
+		}
 	}
 
 	spin_unlock(&ring->lock);
@@ -1445,9 +1462,7 @@ void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
 {
 	const struct bcm43xx_dma_ops *ops = ring->ops;
 	int slot, current_slot;
-#ifdef CONFIG_BCM43XX_MAC80211_DEBUG
 	int used_slots = 0;
-#endif
 
 	assert(!ring->tx);
 	current_slot = ops->get_current_rxslot(ring);
@@ -1456,10 +1471,7 @@ void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
 	slot = ring->current_slot;
 	for ( ; slot != current_slot; slot = next_slot(ring, slot)) {
 		dma_rx(ring, &slot);
-#ifdef CONFIG_BCM43XX_MAC80211_DEBUG
-		if (++used_slots > ring->max_used_slots)
-			ring->max_used_slots = used_slots;
-#endif
+		update_max_used_slots(ring, ++used_slots);
 	}
 	ops->set_current_rxslot(ring, slot);
 	ring->current_slot = slot;
diff --git a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_main.c b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_main.c
index 5b7ff9293d..e13c1168ef 100644
--- a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_main.c
+++ b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_main.c
@@ -1080,21 +1080,13 @@ static void bcm43xx_write_probe_resp_plcp(struct bcm43xx_wldev *dev,
 {
 	struct bcm43xx_plcp_hdr4 plcp;
 	u32 tmp;
-	u16 packet_time;
+	__le16 dur;
 
 	plcp.data = 0;
 	bcm43xx_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
-	/*
-	 * 144 + 48 + 10 = preamble + PLCP + SIFS,
-	 * taken from mac80211 timings calculation.
-	 *
-	 * FIXME: long preamble assumed!
-	 *
-	 */
-	packet_time = 202 + (size + FCS_LEN) * 16 / rate;
-	if ((size + FCS_LEN) * 16 % rate >= rate / 2)
-		++packet_time;
-
+	dur = ieee80211_generic_frame_duration(dev->wl->hw,
+					       size,
+					       BCM43xx_RATE_TO_BASE100KBPS(rate));
 	/* Write PLCP in two parts and timing for packet transfer */
 	tmp = le32_to_cpu(plcp.data);
 	bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, shm_offset,
@@ -1102,7 +1094,7 @@ static void bcm43xx_write_probe_resp_plcp(struct bcm43xx_wldev *dev,
 	bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, shm_offset + 2,
 			    tmp >> 16);
 	bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, shm_offset + 6,
-			    packet_time);
+			    le16_to_cpu(dur));
 }
 
 /* Instead of using custom probe response template, this function
@@ -1116,7 +1108,9 @@ static u8 * bcm43xx_generate_probe_resp(struct bcm43xx_wldev *dev,
 {
 	const u8 *src_data;
 	u8 *dest_data;
-	u16 src_size, elem_size, src_pos, dest_pos, tmp;
+	u16 src_size, elem_size, src_pos, dest_pos;
+	__le16 dur;
+	struct ieee80211_hdr *hdr;
 
 	assert(dev->cached_beacon);
 	src_size = dev->cached_beacon->len;
@@ -1146,26 +1140,15 @@ static u8 * bcm43xx_generate_probe_resp(struct bcm43xx_wldev *dev,
 		}
 	}
 	*dest_size = dest_pos;
+	hdr = (struct ieee80211_hdr *)dest_data;
 
 	/* Set the frame control. */
-	dest_data[0] = (IEEE80211_FTYPE_MGMT |
-			IEEE80211_STYPE_PROBE_RESP);
-	dest_data[1] = 0;
-
-	/* Set the duration field.
-	 *
-	 * 144 + 48 + 10 = preamble + PLCP + SIFS,
-	 * taken from mac80211 timings calculation.
-	 *
-	 * FIXME: long preamble assumed!
-	 *
-	 */
-	tmp = 202 + (14 + FCS_LEN) * 16 / rate;
-	if ((14 + FCS_LEN) * 16 % rate >= rate / 2)
-		++tmp;
-
-	dest_data[2] = tmp & 0xFF;
-	dest_data[3] = (tmp >> 8) & 0xFF;
+	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					 IEEE80211_STYPE_PROBE_RESP);
+	dur = ieee80211_generic_frame_duration(dev->wl->hw,
+					       *dest_size,
+					       BCM43xx_RATE_TO_BASE100KBPS(rate));
+	hdr->duration_id = dur;
 
 	return dest_data;
 }
diff --git a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_xmit.c b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_xmit.c
index 8ad39386cf..a15196b1ff 100644
--- a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_xmit.c
+++ b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_xmit.c
@@ -466,12 +466,19 @@ void bcm43xx_rx(struct bcm43xx_wldev *dev,
 
 	/* Skip PLCP and padding */
 	padding = (macstat & BCM43xx_RX_MAC_PADDING) ? 2 : 0;
+	if (unlikely(skb->len < (sizeof(struct bcm43xx_plcp_hdr6) + padding))) {
+		dprintkl(KERN_DEBUG PFX "RX: Packet size underrun (1)\n");
+		goto drop;
+	}
 	plcp = (struct bcm43xx_plcp_hdr6 *)(skb->data + padding);
 	skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6) + padding);
 	/* The skb contains the Wireless Header + payload data now */
+	if (unlikely(skb->len < (2+2+6/*minimum hdr*/ + FCS_LEN))) {
+		dprintkl(KERN_DEBUG PFX "RX: Packet size underrun (2)\n");
+		goto drop;
+	}
 	wlhdr = (struct ieee80211_hdr *)(skb->data);
 	fctl = le16_to_cpu(wlhdr->frame_control);
-
 	skb_trim(skb, skb->len - FCS_LEN);
 
 	if ((macstat & BCM43xx_RX_MAC_DEC) &&
@@ -496,6 +503,11 @@ void bcm43xx_rx(struct bcm43xx_wldev *dev,
 			wlhdr->frame_control = cpu_to_le16(fctl);
 
 			wlhdr_len = ieee80211_get_hdrlen(fctl);
+			if (unlikely(skb->len < (wlhdr_len + 3))) {
+				dprintkl(KERN_DEBUG PFX
+					 "RX: Packet size underrun (3)\n");
+				goto drop;
+			}
 			if (skb->data[wlhdr_len + 3] & (1 << 5)) {
 				/* The Ext-IV Bit is set in the "KeyID"
 				 * octet of the IV.
@@ -506,7 +518,11 @@ void bcm43xx_rx(struct bcm43xx_wldev *dev,
 				iv_len = 4;
 				icv_len = 4;
 			}
-
+			if (unlikely(skb->len < (wlhdr_len + iv_len + icv_len))) {
+				dprintkl(KERN_DEBUG PFX
+					 "RX: Packet size underrun (4)\n");
+				goto drop;
+			}
 			/* Remove the IV */
 			memmove(skb->data + iv_len, skb->data, wlhdr_len);
 			skb_pull(skb, iv_len);
@@ -553,6 +569,11 @@ void bcm43xx_rx(struct bcm43xx_wldev *dev,
 
 	dev->stats.last_rx = jiffies;
 	ieee80211_rx_irqsafe(dev->wl->hw, skb, &status);
+
+	return;
+drop:
+	dprintkl(KERN_DEBUG PFX "RX: Packet dropped\n");
+	dev_kfree_skb_any(skb);
 }
 
 void bcm43xx_handle_txstatus(struct bcm43xx_wldev *dev,
-- 
2.30.2