p54: fix oops on faulty devices
This patch fixes an oops when the devices suddenly starts to receive martian data frames. bug reference: http://marc.info/?l=linux-wireless&m=122872280317635&w=2 Signed-off-by: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
b7a530d82c
commit
59651e8918
1 changed files with 16 additions and 3 deletions
|
@ -540,6 +540,14 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
|
|||
size_t header_len = sizeof(*hdr);
|
||||
u32 tsf32;
|
||||
|
||||
/*
|
||||
* If the device is in a unspecified state we have to
|
||||
* ignore all data frames. Else we could end up with a
|
||||
* nasty crash.
|
||||
*/
|
||||
if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
|
||||
return 0;
|
||||
|
||||
if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) {
|
||||
if (priv->filter_flags & FIF_FCSFAIL)
|
||||
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
|
@ -608,6 +616,12 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
|
|||
if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* don't try to free an already unlinked skb
|
||||
*/
|
||||
if (unlikely((!skb->next) || (!skb->prev)))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_queue.lock, flags);
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
range = (void *)info->rate_driver_data;
|
||||
|
@ -1695,19 +1709,18 @@ static void p54_stop(struct ieee80211_hw *dev)
|
|||
struct sk_buff *skb;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
|
||||
del_timer(&priv->stats_timer);
|
||||
p54_free_skb(dev, priv->cached_stats);
|
||||
priv->cached_stats = NULL;
|
||||
if (priv->cached_beacon)
|
||||
p54_tx_cancel(dev, priv->cached_beacon);
|
||||
|
||||
priv->stop(dev);
|
||||
while ((skb = skb_dequeue(&priv->tx_queue)))
|
||||
kfree_skb(skb);
|
||||
|
||||
priv->cached_beacon = NULL;
|
||||
priv->stop(dev);
|
||||
priv->tsf_high32 = priv->tsf_low32 = 0;
|
||||
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue