Commit c8579c82 authored by Larry Finger's avatar Larry Finger Committed by Greg Kroah-Hartman

rtl8187: Fix lockups due to concurrent access to config routine

With the rtl8187 driver, the config routine is not protected against
access before a previous call has completed. When this happens, the
TX loopback that is needed to change channels may cause the chip to
be locked with a reset needed to restore communications. This patch
entered mainline as commit 7dcdd073.

The problem was found by Herton Ronaldo Krzesinski <herton@mandriva.com.br>,
who also suggested this type of fix.
Signed-off-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Acked-by: default avatarHerton Ronaldo Krzesinski <herton@mandriva.com.br>
Acked-by: default avatarHin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent f733cd4d
...@@ -67,6 +67,10 @@ struct rtl8187_priv { ...@@ -67,6 +67,10 @@ struct rtl8187_priv {
const struct rtl818x_rf_ops *rf; const struct rtl818x_rf_ops *rf;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
int mode; int mode;
/* The mutex protects the TX loopback state.
* Any attempt to set channels concurrently locks the device.
*/
struct mutex conf_mutex;
/* rtl8187 specific */ /* rtl8187 specific */
struct ieee80211_channel channels[14]; struct ieee80211_channel channels[14];
......
...@@ -580,6 +580,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) ...@@ -580,6 +580,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
struct rtl8187_priv *priv = dev->priv; struct rtl8187_priv *priv = dev->priv;
u32 reg; u32 reg;
mutex_lock(&priv->conf_mutex);
reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
/* Enable TX loopback on MAC level to avoid TX during channel /* Enable TX loopback on MAC level to avoid TX during channel
* changes, as this has be seen to causes problems and the * changes, as this has be seen to causes problems and the
...@@ -610,6 +611,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) ...@@ -610,6 +611,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
mutex_unlock(&priv->conf_mutex);
return 0; return 0;
} }
...@@ -814,6 +816,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, ...@@ -814,6 +816,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
printk(KERN_ERR "rtl8187: Cannot register device\n"); printk(KERN_ERR "rtl8187: Cannot register device\n");
goto err_free_dev; goto err_free_dev;
} }
mutex_init(&priv->conf_mutex);
printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n", printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n",
wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment