aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2008-12-09 15:07:50 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-12-12 14:02:15 -0500
commit59651e89187293e88863891b821c7379391ef75c (patch)
tree1551075914e98552269c83c25ef15be30f59c651 /drivers/net/wireless/p54
parentb7a530d82cb36bb43901c196039b0fccee3ffcc3 (diff)
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>
Diffstat (limited to 'drivers/net/wireless/p54')
-rw-r--r--drivers/net/wireless/p54/p54common.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index fac6b416e9e9..a4e99b02af02 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -540,6 +540,14 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
540 size_t header_len = sizeof(*hdr); 540 size_t header_len = sizeof(*hdr);
541 u32 tsf32; 541 u32 tsf32;
542 542
543 /*
544 * If the device is in a unspecified state we have to
545 * ignore all data frames. Else we could end up with a
546 * nasty crash.
547 */
548 if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
549 return 0;
550
543 if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) { 551 if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) {
544 if (priv->filter_flags & FIF_FCSFAIL) 552 if (priv->filter_flags & FIF_FCSFAIL)
545 rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; 553 rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
@@ -608,6 +616,12 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
608 if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue))) 616 if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
609 return; 617 return;
610 618
619 /*
620 * don't try to free an already unlinked skb
621 */
622 if (unlikely((!skb->next) || (!skb->prev)))
623 return;
624
611 spin_lock_irqsave(&priv->tx_queue.lock, flags); 625 spin_lock_irqsave(&priv->tx_queue.lock, flags);
612 info = IEEE80211_SKB_CB(skb); 626 info = IEEE80211_SKB_CB(skb);
613 range = (void *)info->rate_driver_data; 627 range = (void *)info->rate_driver_data;
@@ -1695,19 +1709,18 @@ static void p54_stop(struct ieee80211_hw *dev)
1695 struct sk_buff *skb; 1709 struct sk_buff *skb;
1696 1710
1697 mutex_lock(&priv->conf_mutex); 1711 mutex_lock(&priv->conf_mutex);
1712 priv->mode = NL80211_IFTYPE_UNSPECIFIED;
1698 del_timer(&priv->stats_timer); 1713 del_timer(&priv->stats_timer);
1699 p54_free_skb(dev, priv->cached_stats); 1714 p54_free_skb(dev, priv->cached_stats);
1700 priv->cached_stats = NULL; 1715 priv->cached_stats = NULL;
1701 if (priv->cached_beacon) 1716 if (priv->cached_beacon)
1702 p54_tx_cancel(dev, priv->cached_beacon); 1717 p54_tx_cancel(dev, priv->cached_beacon);
1703 1718
1719 priv->stop(dev);
1704 while ((skb = skb_dequeue(&priv->tx_queue))) 1720 while ((skb = skb_dequeue(&priv->tx_queue)))
1705 kfree_skb(skb); 1721 kfree_skb(skb);
1706
1707 priv->cached_beacon = NULL; 1722 priv->cached_beacon = NULL;
1708 priv->stop(dev);
1709 priv->tsf_high32 = priv->tsf_low32 = 0; 1723 priv->tsf_high32 = priv->tsf_low32 = 0;
1710 priv->mode = NL80211_IFTYPE_UNSPECIFIED;
1711 mutex_unlock(&priv->conf_mutex); 1724 mutex_unlock(&priv->conf_mutex);
1712} 1725}
1713 1726