diff options
author | Herton Ronaldo Krzesinski <herton@mandriva.com.br> | 2008-12-14 13:18:09 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-12-19 15:23:20 -0500 |
commit | d85882273367e98aecb9ff11a9d76515a6d37131 (patch) | |
tree | fd9afecba19c3765ba77455b498b1af5c3241286 /drivers/net/wireless/rtl818x | |
parent | 0a5ec96ad68516582023a877aceff9db7636d141 (diff) |
rtl8187: Fix crash on unload when using SLUB debug
Reported-by: Hin-Tak Leung <htl10@users.sourceforge.net>
After the code was modified to use urb anchors ("rtl8187: Use usb anchor
facilities to manage urbs"), rtl8187 began generating an intermittent GPF
on shutdown when using SLUB with debugging enabled. Furthermore, rebooting
the system with a ping running caused a GPF every time. There are two problems:
(1) incorrect locking in the rtl8187_rx_cb() routine, a pre-existing bug that
apparently had not been triggered before, and (2) duplicate freeing of receive
skbs that was probably introduced with the change to anchors.
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Tested-by: Hin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtl818x')
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8187_dev.c | 12 |
1 files changed, 4 insertions, 8 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 3900c479b4e7..00ce3ef39abe 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -294,15 +294,16 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
294 | int rate, signal; | 294 | int rate, signal; |
295 | u32 flags; | 295 | u32 flags; |
296 | u32 quality; | 296 | u32 quality; |
297 | unsigned long f; | ||
297 | 298 | ||
298 | spin_lock(&priv->rx_queue.lock); | 299 | spin_lock_irqsave(&priv->rx_queue.lock, f); |
299 | if (skb->next) | 300 | if (skb->next) |
300 | __skb_unlink(skb, &priv->rx_queue); | 301 | __skb_unlink(skb, &priv->rx_queue); |
301 | else { | 302 | else { |
302 | spin_unlock(&priv->rx_queue.lock); | 303 | spin_unlock_irqrestore(&priv->rx_queue.lock, f); |
303 | return; | 304 | return; |
304 | } | 305 | } |
305 | spin_unlock(&priv->rx_queue.lock); | 306 | spin_unlock_irqrestore(&priv->rx_queue.lock, f); |
306 | skb_put(skb, urb->actual_length); | 307 | skb_put(skb, urb->actual_length); |
307 | 308 | ||
308 | if (unlikely(urb->status)) { | 309 | if (unlikely(urb->status)) { |
@@ -942,7 +943,6 @@ static int rtl8187_start(struct ieee80211_hw *dev) | |||
942 | static void rtl8187_stop(struct ieee80211_hw *dev) | 943 | static void rtl8187_stop(struct ieee80211_hw *dev) |
943 | { | 944 | { |
944 | struct rtl8187_priv *priv = dev->priv; | 945 | struct rtl8187_priv *priv = dev->priv; |
945 | struct rtl8187_rx_info *info; | ||
946 | struct sk_buff *skb; | 946 | struct sk_buff *skb; |
947 | u32 reg; | 947 | u32 reg; |
948 | 948 | ||
@@ -961,10 +961,6 @@ static void rtl8187_stop(struct ieee80211_hw *dev) | |||
961 | rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); | 961 | rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); |
962 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 962 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
963 | 963 | ||
964 | while ((skb = skb_dequeue(&priv->rx_queue))) { | ||
965 | info = (struct rtl8187_rx_info *)skb->cb; | ||
966 | kfree_skb(skb); | ||
967 | } | ||
968 | while ((skb = skb_dequeue(&priv->b_tx_status.queue))) | 964 | while ((skb = skb_dequeue(&priv->b_tx_status.queue))) |
969 | dev_kfree_skb_any(skb); | 965 | dev_kfree_skb_any(skb); |
970 | 966 | ||