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>
This commit is contained in:
Roland Vossen 2011-03-10 11:35:06 +01:00 committed by Greg Kroah-Hartman
parent 0789b00331
commit 0bf97bb1cf

View file

@ -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);
}