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);
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,
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)
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)
/* 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);
*/
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;
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);
{
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);
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;
{
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,
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
{
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;
}
}
*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;
}
/* 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) &&
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.
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);
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,