Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59651e89 authored by Christian Lamparter's avatar Christian Lamparter Committed by John W. Linville
Browse files

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: default avatarChristian Lamparter <chunkeey@web.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b7a530d8
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -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);
}