Search Linux Wireless

[PATCH] wireless: at76c50x: fix multithread access to hex2str

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The original hex2str uses finite array of buffers to keep output data. It's a wrong approach, because we can't say at compile time how many threads will be used.

This patch introduces one buffer and global mutex to access this function. All
calls of it are wrapped by locking this mutex. It saves some memory as a side
effect.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
Cc: "John W. Linville" <linville@xxxxxxxxxxxxx>
---
 drivers/net/wireless/at76c50x-usb.c |   23 +++++++++++++++++++----
 1 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 39322d4..af043f6 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -498,15 +498,14 @@ exit:
 	return ret;
 }
 
-#define HEX2STR_BUFFERS 4
 #define HEX2STR_MAX_LEN 64
 
+static DEFINE_MUTEX(hex2str_mutex);
+
 /* Convert binary data into hex string */
 static char *hex2str(void *buf, size_t len)
 {
-	static atomic_t a = ATOMIC_INIT(0);
-	static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1];
-	char *ret = bufs[atomic_inc_return(&a) & (HEX2STR_BUFFERS - 1)];
+	static char ret[3 * HEX2STR_MAX_LEN + 1];
 	char *obuf = ret;
 	u8 *ibuf = buf;
 
@@ -1003,10 +1002,13 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv)
 	key_len = (m->encryption_level == 1) ?
 	    WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;
 
+	mutex_lock(&hex2str_mutex);
 	for (i = 0; i < WEP_KEYS; i++)
 		at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: key %d: %s",
 			 wiphy_name(priv->hw->wiphy), i,
 			 hex2str(m->wep_default_keyvalue[i], key_len));
+	mutex_unlock(&hex2str_mutex);
+
 exit:
 	kfree(m);
 }
@@ -1028,6 +1030,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
 		goto exit;
 	}
 
+	mutex_lock(&hex2str_mutex);
 	at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration "
 		 "%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d "
 		 "CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d "
@@ -1045,6 +1048,8 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
 		 m->current_bss_type, m->power_mgmt_mode, m->ibss_change,
 		 m->res, m->multi_domain_capability_implemented,
 		 m->multi_domain_capability_enabled, m->country_string);
+	mutex_unlock(&hex2str_mutex);
+
 exit:
 	kfree(m);
 }
@@ -1064,6 +1069,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
 		goto exit;
 	}
 
+	mutex_lock(&hex2str_mutex);
 	at76_dbg(DBG_MIB, "%s: MIB MAC: max_tx_msdu_lifetime %d "
 		 "max_rx_lifetime %d frag_threshold %d rts_threshold %d "
 		 "cwmin %d cwmax %d short_retry_time %d long_retry_time %d "
@@ -1082,6 +1088,8 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
 		 le16_to_cpu(m->listen_interval),
 		 hex2str(m->desired_ssid, IW_ESSID_MAX_SIZE),
 		 m->desired_bssid, m->desired_bsstype);
+	mutex_unlock(&hex2str_mutex);
+
 exit:
 	kfree(m);
 }
@@ -1160,6 +1168,8 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv)
 		goto exit;
 	}
 
+	mutex_lock(&hex2str_mutex);
+
 	at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s",
 		 wiphy_name(priv->hw->wiphy),
 		 hex2str(m->channel_list, sizeof(m->channel_list)));
@@ -1167,6 +1177,8 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv)
 	at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: tx_powerlevel %s",
 		 wiphy_name(priv->hw->wiphy),
 		 hex2str(m->tx_powerlevel, sizeof(m->tx_powerlevel)));
+
+	mutex_unlock(&hex2str_mutex);
 exit:
 	kfree(m);
 }
@@ -1368,6 +1380,7 @@ static int at76_startup_device(struct at76_priv *priv)
 	struct at76_card_config *ccfg = &priv->card_config;
 	int ret;
 
+	mutex_lock(&hex2str_mutex);
 	at76_dbg(DBG_PARAMS,
 		 "%s param: ssid %.*s (%s) mode %s ch %d wep %s key %d "
 		 "keylen %d", wiphy_name(priv->hw->wiphy), priv->essid_size,
@@ -1375,6 +1388,8 @@ static int at76_startup_device(struct at76_priv *priv)
 		 priv->iw_mode == IW_MODE_ADHOC ? "adhoc" : "infra",
 		 priv->channel, priv->wep_enabled ? "enabled" : "disabled",
 		 priv->wep_key_id, priv->wep_keys_len[priv->wep_key_id]);
+	mutex_unlock(&hex2str_mutex);
+
 	at76_dbg(DBG_PARAMS,
 		 "%s param: preamble %s rts %d retry %d frag %d "
 		 "txrate %s auth_mode %d", wiphy_name(priv->hw->wiphy),
-- 
1.7.6.3

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux