diff options
author | Roland Vossen <rvossen@broadcom.com> | 2011-03-10 05:35:06 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-03-14 14:44:02 -0400 |
commit | 0bf97bb1cff7204111c479c899dae30823314761 (patch) | |
tree | 377f4588342d49b0ef533827e7ae8fa9d10eab48 /drivers | |
parent | 0789b0033112e301f086f99bd15c7d67c051a51e (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')
-rw-r--r-- | drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c | 34 |
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 7f8790d9b81..26dd9b6a875 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, | |||
900 | 900 | ||
901 | tx_info = IEEE80211_SKB_CB(p); | 901 | tx_info = IEEE80211_SKB_CB(p); |
902 | ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU); | 902 | ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU); |
903 | ASSERT(scb); | ||
904 | ASSERT(scb->magic == SCB_MAGIC); | ||
905 | ASSERT(txs->status & TX_STATUS_AMPDU); | 903 | ASSERT(txs->status & TX_STATUS_AMPDU); |
906 | scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb); | ||
907 | ASSERT(scb_ampdu); | ||
908 | ini = SCB_AMPDU_INI(scb_ampdu, p->priority); | ||
909 | ASSERT(ini->scb == scb); | ||
910 | 904 | ||
911 | /* BMAC_NOTE: For the split driver, second level txstatus comes later | 905 | /* BMAC_NOTE: For the split driver, second level txstatus comes later |
912 | * So if the ACK was received then wait for the second level else just | 906 | * 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, | |||
930 | s2 = R_REG(&wlc->regs->frmtxstatus2); | 924 | s2 = R_REG(&wlc->regs->frmtxstatus2); |
931 | } | 925 | } |
932 | 926 | ||
933 | wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2); | 927 | if (likely(scb)) { |
928 | ASSERT(scb->magic == SCB_MAGIC); | ||
929 | scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb); | ||
930 | ASSERT(scb_ampdu); | ||
931 | ini = SCB_AMPDU_INI(scb_ampdu, p->priority); | ||
932 | ASSERT(ini->scb == scb); | ||
933 | wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2); | ||
934 | } else { | ||
935 | /* loop through all pkts and free */ | ||
936 | u8 queue = txs->frameid & TXFID_QUEUE_MASK; | ||
937 | d11txh_t *txh; | ||
938 | u16 mcl; | ||
939 | while (p) { | ||
940 | tx_info = IEEE80211_SKB_CB(p); | ||
941 | txh = (d11txh_t *) p->data; | ||
942 | mcl = le16_to_cpu(txh->MacTxControlLow); | ||
943 | ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU); | ||
944 | pkt_buf_free_skb(p); | ||
945 | /* break out if last packet of ampdu */ | ||
946 | if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) == | ||
947 | TXC_AMPDU_LAST) | ||
948 | break; | ||
949 | p = GETNEXTTXP(wlc, queue); | ||
950 | ASSERT(p != NULL); | ||
951 | } | ||
952 | wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight); | ||
953 | } | ||
934 | wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini); | 954 | wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini); |
935 | } | 955 | } |
936 | 956 | ||