From c8579c82a2404274193ac75fe27d68bf112b908c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 5 Aug 2008 23:20:56 -0500 Subject: [PATCH] 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 7dcdd073bf78bb6958bbc12a1a47754a0f3c4721. The problem was found by Herton Ronaldo Krzesinski , who also suggested this type of fix. Signed-off-by: Larry Finger Acked-by: Herton Ronaldo Krzesinski Acked-by: Hin-Tak Leung Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtl8187.h | 4 ++++ drivers/net/wireless/rtl8187_dev.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h index 076d88b6db0e..aefd4f67307c 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl8187.h @@ -67,6 +67,10 @@ struct rtl8187_priv { const struct rtl818x_rf_ops *rf; struct ieee80211_vif *vif; int mode; + /* The mutex protects the TX loopback state. + * Any attempt to set channels concurrently locks the device. + */ + struct mutex conf_mutex; /* rtl8187 specific */ struct ieee80211_channel channels[14]; diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 9223ada5f00e..d49d1c6960a2 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -580,6 +580,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) struct rtl8187_priv *priv = dev->priv; u32 reg; + mutex_lock(&priv->conf_mutex); reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); /* Enable TX loopback on MAC level to avoid TX during channel * 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) rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100); + mutex_unlock(&priv->conf_mutex); return 0; } @@ -814,6 +816,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, printk(KERN_ERR "rtl8187: Cannot register device\n"); goto err_free_dev; } + mutex_init(&priv->conf_mutex); printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n", wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), -- 2.39.5