summaryrefslogtreecommitdiff
path: root/drivers/staging/brcm80211
diff options
context:
space:
mode:
authorRoland Vossen <rvossen@broadcom.com>2011-03-10 11:35:06 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2011-03-14 11:44:02 -0700
commit0bf97bb1cff7204111c479c899dae30823314761 (patch)
tree377f4588342d49b0ef533827e7ae8fa9d10eab48 /drivers/staging/brcm80211
parent0789b0033112e301f086f99bd15c7d67c051a51e (diff)
staging: brcm80211: bugfix for NULL scb ptr dereference
The driver uses a struct called 'scb', this struct is primarily used for AMPDU functionality and is embedded in struct ieee80211_sta. To increase driver robustness, the case in which this scb pointer is NULL is now handled graceful. This paves the way for the next patch in this series. Signed-off-by: Roland Vossen <rvossen@broadcom.com> Reviewed-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/brcm80211')
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
index 7f8790d9b817..26dd9b6a8757 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
@@ -900,13 +900,7 @@ wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
tx_info = IEEE80211_SKB_CB(p);
ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
- ASSERT(scb);
- ASSERT(scb->magic == SCB_MAGIC);
ASSERT(txs->status & TX_STATUS_AMPDU);
- scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
- ASSERT(scb_ampdu);
- ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
- ASSERT(ini->scb == scb);
/* BMAC_NOTE: For the split driver, second level txstatus comes later
* So if the ACK was received then wait for the second level else just
@@ -930,7 +924,33 @@ wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
s2 = R_REG(&wlc->regs->frmtxstatus2);
}
- wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
+ if (likely(scb)) {
+ ASSERT(scb->magic == SCB_MAGIC);
+ scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+ ASSERT(scb_ampdu);
+ ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
+ ASSERT(ini->scb == scb);
+ wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
+ } else {
+ /* loop through all pkts and free */
+ u8 queue = txs->frameid & TXFID_QUEUE_MASK;
+ d11txh_t *txh;
+ u16 mcl;
+ while (p) {
+ tx_info = IEEE80211_SKB_CB(p);
+ txh = (d11txh_t *) p->data;
+ mcl = le16_to_cpu(txh->MacTxControlLow);
+ ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
+ pkt_buf_free_skb(p);
+ /* break out if last packet of ampdu */
+ if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+ TXC_AMPDU_LAST)
+ break;
+ p = GETNEXTTXP(wlc, queue);
+ ASSERT(p != NULL);
+ }
+ wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
+ }
wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
}