mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-04 06:54:27 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			532 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			532 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 250a1b520cd7fdc0df4fc3fedea9066913f49ecf Mon Sep 17 00:00:00 2001
 | 
						|
From: Gabor Juhos <juhosg@openwrt.org>
 | 
						|
Date: Sat, 17 Aug 2013 19:31:42 +0200
 | 
						|
Subject: [PATCH] rt2x00: rt2800: serialize shared memory access
 | 
						|
 | 
						|
The shared memory of the rt2800 devices is accessible
 | 
						|
through the register offset range between 0x4000 and
 | 
						|
0x8000. The size of this range is 16KB only and on
 | 
						|
devices which have more than 16KB of shared memory either
 | 
						|
the low or the high part of the memory is accessible at a
 | 
						|
time.
 | 
						|
 | 
						|
Serialize all accesses to the shared memory by a mutex,
 | 
						|
in order to avoid concurrent use of that.
 | 
						|
 | 
						|
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 | 
						|
---
 | 
						|
Changes since v1: ---
 | 
						|
---
 | 
						|
 drivers/net/wireless/rt2x00/rt2800lib.c  |   55 +++++++++++++++++++++++++++++-
 | 
						|
 drivers/net/wireless/rt2x00/rt2800lib.h  |   32 +++++++++++++++++
 | 
						|
 drivers/net/wireless/rt2x00/rt2800mmio.c |   26 ++++++++++++++
 | 
						|
 drivers/net/wireless/rt2x00/rt2800mmio.h |    4 +++
 | 
						|
 drivers/net/wireless/rt2x00/rt2800pci.c  |   14 ++++++++
 | 
						|
 drivers/net/wireless/rt2x00/rt2800soc.c  |    3 ++
 | 
						|
 drivers/net/wireless/rt2x00/rt2800usb.c  |   31 +++++++++++++++++
 | 
						|
 7 files changed, 164 insertions(+), 1 deletion(-)
 | 
						|
 | 
						|
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 | 
						|
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
 | 
						|
@@ -451,11 +451,13 @@ void rt2800_mcu_request(struct rt2x00_de
 | 
						|
 		rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token);
 | 
						|
 		rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0);
 | 
						|
 		rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1);
 | 
						|
+		rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 		rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);
 | 
						|
 
 | 
						|
 		reg = 0;
 | 
						|
 		rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command);
 | 
						|
 		rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);
 | 
						|
+		rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	mutex_unlock(&rt2x00dev->csr_mutex);
 | 
						|
@@ -674,7 +676,9 @@ int rt2800_load_firmware(struct rt2x00_d
 | 
						|
 	 * Wait for device to stabilize.
 | 
						|
 	 */
 | 
						|
 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 | 
						|
+		rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 		rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®);
 | 
						|
+		rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 		if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
 | 
						|
 			break;
 | 
						|
 		msleep(1);
 | 
						|
@@ -694,10 +698,16 @@ int rt2800_load_firmware(struct rt2x00_d
 | 
						|
 	/*
 | 
						|
 	 * Initialize firmware.
 | 
						|
 	 */
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 | 
						|
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
+
 | 
						|
 	if (rt2x00_is_usb(rt2x00dev)) {
 | 
						|
+		rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
 | 
						|
+		rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
+
 | 
						|
 		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
 | 
						|
 	}
 | 
						|
 	msleep(1);
 | 
						|
@@ -1035,8 +1045,10 @@ void rt2800_write_beacon(struct queue_en
 | 
						|
 
 | 
						|
 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
 | 
						|
 
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 | 
						|
 				   entry->skb->len + padding_len);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 	__set_bit(ENTRY_BCN_ENABLED, &entry->flags);
 | 
						|
 
 | 
						|
 	/*
 | 
						|
@@ -1066,6 +1078,8 @@ static inline void rt2800_clear_beacon_r
 | 
						|
 
 | 
						|
 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
 | 
						|
 
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
+
 | 
						|
 	/*
 | 
						|
 	 * For the Beacon base registers we only need to clear
 | 
						|
 	 * the whole TXWI which (when set to 0) will invalidate
 | 
						|
@@ -1073,6 +1087,8 @@ static inline void rt2800_clear_beacon_r
 | 
						|
 	 */
 | 
						|
 	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
 | 
						|
 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
 | 
						|
+
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 }
 | 
						|
 
 | 
						|
 void rt2800_clear_beacon(struct queue_entry *entry)
 | 
						|
@@ -1261,7 +1277,9 @@ static void rt2800_delete_wcid_attr(stru
 | 
						|
 {
 | 
						|
 	u32 offset;
 | 
						|
 	offset = MAC_WCID_ATTR_ENTRY(wcid);
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2800_register_write(rt2x00dev, offset, 0);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 }
 | 
						|
 
 | 
						|
 static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
 | 
						|
@@ -1274,11 +1292,13 @@ static void rt2800_config_wcid_attr_bssi
 | 
						|
 	 * The BSS Idx numbers is split in a main value of 3 bits,
 | 
						|
 	 * and a extended field for adding one additional bit to the value.
 | 
						|
 	 */
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2800_register_read(rt2x00dev, offset, ®);
 | 
						|
 	rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
 | 
						|
 	rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
 | 
						|
 			   (bssidx & 0x8) >> 3);
 | 
						|
 	rt2800_register_write(rt2x00dev, offset, reg);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 }
 | 
						|
 
 | 
						|
 static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
 | 
						|
@@ -1291,6 +1311,7 @@ static void rt2800_config_wcid_attr_ciph
 | 
						|
 
 | 
						|
 	offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
 | 
						|
 
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	if (crypto->cmd == SET_KEY) {
 | 
						|
 		rt2800_register_read(rt2x00dev, offset, ®);
 | 
						|
 		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB,
 | 
						|
@@ -1315,6 +1336,7 @@ static void rt2800_config_wcid_attr_ciph
 | 
						|
 		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
 | 
						|
 		rt2800_register_write(rt2x00dev, offset, reg);
 | 
						|
 	}
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
 | 
						|
 
 | 
						|
@@ -1324,8 +1346,11 @@ static void rt2800_config_wcid_attr_ciph
 | 
						|
 	    (crypto->cipher == CIPHER_AES))
 | 
						|
 		iveiv_entry.iv[3] |= 0x20;
 | 
						|
 	iveiv_entry.iv[3] |= key->keyidx << 6;
 | 
						|
+
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2800_register_multiwrite(rt2x00dev, offset,
 | 
						|
 				      &iveiv_entry, sizeof(iveiv_entry));
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 }
 | 
						|
 
 | 
						|
 int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
 | 
						|
@@ -1348,8 +1373,11 @@ int rt2800_config_shared_key(struct rt2x
 | 
						|
 		       sizeof(key_entry.rx_mic));
 | 
						|
 
 | 
						|
 		offset = SHARED_KEY_ENTRY(key->hw_key_idx);
 | 
						|
+
 | 
						|
+		rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 		rt2800_register_multiwrite(rt2x00dev, offset,
 | 
						|
 					      &key_entry, sizeof(key_entry));
 | 
						|
+		rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	/*
 | 
						|
@@ -1364,10 +1392,12 @@ int rt2800_config_shared_key(struct rt2x
 | 
						|
 
 | 
						|
 	offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
 | 
						|
 
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2800_register_read(rt2x00dev, offset, ®);
 | 
						|
 	rt2x00_set_field32(®, field,
 | 
						|
 			   (crypto->cmd == SET_KEY) * crypto->cipher);
 | 
						|
 	rt2800_register_write(rt2x00dev, offset, reg);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	/*
 | 
						|
 	 * Update WCID information
 | 
						|
@@ -1437,8 +1467,11 @@ int rt2800_config_pairwise_key(struct rt
 | 
						|
 		       sizeof(key_entry.rx_mic));
 | 
						|
 
 | 
						|
 		offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
 | 
						|
+
 | 
						|
+		rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 		rt2800_register_multiwrite(rt2x00dev, offset,
 | 
						|
 					      &key_entry, sizeof(key_entry));
 | 
						|
+		rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	/*
 | 
						|
@@ -4901,14 +4934,19 @@ static int rt2800_init_registers(struct 
 | 
						|
 	/*
 | 
						|
 	 * ASIC will keep garbage value after boot, clear encryption keys.
 | 
						|
 	 */
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	for (i = 0; i < 4; i++)
 | 
						|
 		rt2800_register_write(rt2x00dev,
 | 
						|
 					 SHARED_KEY_MODE_ENTRY(i), 0);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	for (i = 0; i < 256; i++) {
 | 
						|
 		rt2800_config_wcid(rt2x00dev, NULL, i);
 | 
						|
 		rt2800_delete_wcid_attr(rt2x00dev, i);
 | 
						|
+
 | 
						|
+		rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 		rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
 | 
						|
+		rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	/*
 | 
						|
@@ -5034,8 +5072,10 @@ static int rt2800_wait_bbp_ready(struct 
 | 
						|
 	 * BBP was enabled after firmware was loaded,
 | 
						|
 	 * but we need to reactivate it now.
 | 
						|
 	 */
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 | 
						|
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 	msleep(1);
 | 
						|
 
 | 
						|
 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 | 
						|
@@ -6731,11 +6771,19 @@ int rt2800_enable_radio(struct rt2x00_de
 | 
						|
 	/*
 | 
						|
 	 * Send signal during boot time to initialize firmware.
 | 
						|
 	 */
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 | 
						|
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 | 
						|
-	if (rt2x00_is_usb(rt2x00dev))
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
+
 | 
						|
+	if (rt2x00_is_usb(rt2x00dev)) {
 | 
						|
+		rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
 | 
						|
+		rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
+	}
 | 
						|
+
 | 
						|
 	rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
 | 
						|
+
 | 
						|
 	msleep(1);
 | 
						|
 
 | 
						|
 	/*
 | 
						|
@@ -7744,6 +7792,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 | 
						|
 	int retval;
 | 
						|
 	u32 reg;
 | 
						|
 
 | 
						|
+	rt2800_shared_mem_init_lock(rt2x00dev);
 | 
						|
+
 | 
						|
 	retval = rt2800_probe_rt(rt2x00dev);
 | 
						|
 	if (retval)
 | 
						|
 		return retval;
 | 
						|
@@ -7823,8 +7873,11 @@ void rt2800_get_tkip_seq(struct ieee8021
 | 
						|
 	u32 offset;
 | 
						|
 
 | 
						|
 	offset = MAC_IVEIV_ENTRY(hw_key_idx);
 | 
						|
+
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2800_register_multiread(rt2x00dev, offset,
 | 
						|
 				      &iveiv_entry, sizeof(iveiv_entry));
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16));
 | 
						|
 	memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32));
 | 
						|
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
 | 
						|
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
 | 
						|
@@ -35,6 +35,11 @@ struct rt2800_drv_data {
 | 
						|
 	unsigned int tbtt_tick;
 | 
						|
 
 | 
						|
 	unsigned long rt2800_flags;
 | 
						|
+
 | 
						|
+	union {
 | 
						|
+		spinlock_t spin;
 | 
						|
+		struct mutex mutex;
 | 
						|
+	} shmem_lock;
 | 
						|
 };
 | 
						|
 
 | 
						|
 struct rt2800_ops {
 | 
						|
@@ -65,6 +70,10 @@ struct rt2800_ops {
 | 
						|
 				  const u8 *data, const size_t len);
 | 
						|
 	int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
 | 
						|
 	__le32 *(*drv_get_txwi)(struct queue_entry *entry);
 | 
						|
+
 | 
						|
+	void (*shmem_init_lock)(struct rt2x00_dev *rt2x00dev);
 | 
						|
+	void (*shmem_lock)(struct rt2x00_dev *rt2x00dev);
 | 
						|
+	void (*shmem_unlock)(struct rt2x00_dev *rt2x00dev);
 | 
						|
 };
 | 
						|
 
 | 
						|
 static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
 | 
						|
@@ -74,6 +83,29 @@ static inline bool rt2800_has_high_share
 | 
						|
 	return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
 | 
						|
 }
 | 
						|
 
 | 
						|
+static inline void rt2800_shared_mem_init_lock(struct rt2x00_dev *rt2x00dev)
 | 
						|
+{
 | 
						|
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 | 
						|
+
 | 
						|
+	rt2800ops->shmem_init_lock(rt2x00dev);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void rt2800_shared_mem_lock(struct rt2x00_dev *rt2x00dev)
 | 
						|
+{
 | 
						|
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 | 
						|
+
 | 
						|
+	if (rt2800_has_high_shared_mem(rt2x00dev))
 | 
						|
+		rt2800ops->shmem_lock(rt2x00dev);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void rt2800_shared_mem_unlock(struct rt2x00_dev *rt2x00dev)
 | 
						|
+{
 | 
						|
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 | 
						|
+
 | 
						|
+	if (rt2800_has_high_shared_mem(rt2x00dev))
 | 
						|
+		rt2800ops->shmem_unlock(rt2x00dev);
 | 
						|
+}
 | 
						|
+
 | 
						|
 static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
 | 
						|
 					const unsigned int offset,
 | 
						|
 					u32 *value)
 | 
						|
--- a/drivers/net/wireless/rt2x00/rt2800mmio.c
 | 
						|
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.c
 | 
						|
@@ -820,8 +820,10 @@ int rt2800mmio_init_registers(struct rt2
 | 
						|
 	rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1);
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
 | 
						|
 
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	if (rt2x00_is_pcie(rt2x00dev) &&
 | 
						|
 	    (rt2x00_rt(rt2x00dev, RT3090) ||
 | 
						|
@@ -865,6 +867,30 @@ int rt2800mmio_enable_radio(struct rt2x0
 | 
						|
 }
 | 
						|
 EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
 | 
						|
 
 | 
						|
+void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev)
 | 
						|
+{
 | 
						|
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
 | 
						|
+
 | 
						|
+	spin_lock_init(&drv_data->shmem_lock.spin);
 | 
						|
+}
 | 
						|
+EXPORT_SYMBOL_GPL(rt2800mmio_shmem_init_lock);
 | 
						|
+
 | 
						|
+void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev)
 | 
						|
+{
 | 
						|
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
 | 
						|
+
 | 
						|
+	spin_lock_bh(&drv_data->shmem_lock.spin);
 | 
						|
+}
 | 
						|
+EXPORT_SYMBOL_GPL(rt2800mmio_shmem_lock);
 | 
						|
+
 | 
						|
+void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev)
 | 
						|
+{
 | 
						|
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
 | 
						|
+
 | 
						|
+	spin_unlock_bh(&drv_data->shmem_lock.spin);
 | 
						|
+}
 | 
						|
+EXPORT_SYMBOL_GPL(rt2800mmio_shmem_unlock);
 | 
						|
+
 | 
						|
 MODULE_AUTHOR(DRV_PROJECT);
 | 
						|
 MODULE_VERSION(DRV_VERSION);
 | 
						|
 MODULE_DESCRIPTION("rt2800 MMIO library");
 | 
						|
--- a/drivers/net/wireless/rt2x00/rt2800mmio.h
 | 
						|
+++ b/drivers/net/wireless/rt2x00/rt2800mmio.h
 | 
						|
@@ -160,4 +160,8 @@ int rt2800mmio_init_registers(struct rt2
 | 
						|
 /* Device state switch handlers. */
 | 
						|
 int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev);
 | 
						|
 
 | 
						|
+void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev);
 | 
						|
+void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev);
 | 
						|
+void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev);
 | 
						|
+
 | 
						|
 #endif /* RT2800MMIO_H */
 | 
						|
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
 | 
						|
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
 | 
						|
@@ -69,7 +69,9 @@ static void rt2800pci_mcu_status(struct 
 | 
						|
 		return;
 | 
						|
 
 | 
						|
 	for (i = 0; i < 200; i++) {
 | 
						|
+		rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 		rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, ®);
 | 
						|
+		rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 		if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
 | 
						|
 		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
 | 
						|
@@ -83,8 +85,10 @@ static void rt2800pci_mcu_status(struct 
 | 
						|
 	if (i == 200)
 | 
						|
 		rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");
 | 
						|
 
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 }
 | 
						|
 
 | 
						|
 static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
 | 
						|
@@ -184,6 +188,8 @@ static int rt2800pci_write_firmware(stru
 | 
						|
 	 */
 | 
						|
 	reg = 0;
 | 
						|
 	rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
 | 
						|
+
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
 | 
						|
 
 | 
						|
 	/*
 | 
						|
@@ -197,6 +203,7 @@ static int rt2800pci_write_firmware(stru
 | 
						|
 
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
@@ -213,8 +220,10 @@ static int rt2800pci_enable_radio(struct
 | 
						|
 		return retval;
 | 
						|
 
 | 
						|
 	/* After resume MCU_BOOT_SIGNAL will trash these. */
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 | 
						|
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
 | 
						|
 	rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
 | 
						|
@@ -233,10 +242,12 @@ static int rt2800pci_set_state(struct rt
 | 
						|
 				   0, 0x02);
 | 
						|
 		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
 | 
						|
 	} else if (state == STATE_SLEEP) {
 | 
						|
+		rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 		rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
 | 
						|
 					  0xffffffff);
 | 
						|
 		rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID,
 | 
						|
 					  0xffffffff);
 | 
						|
+		rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
 | 
						|
 				   0xff, 0x01);
 | 
						|
 	}
 | 
						|
@@ -337,6 +348,9 @@ static const struct rt2800_ops rt2800pci
 | 
						|
 	.drv_write_firmware	= rt2800pci_write_firmware,
 | 
						|
 	.drv_init_registers	= rt2800mmio_init_registers,
 | 
						|
 	.drv_get_txwi		= rt2800mmio_get_txwi,
 | 
						|
+	.shmem_init_lock	= rt2800mmio_shmem_init_lock,
 | 
						|
+	.shmem_lock		= rt2800mmio_shmem_lock,
 | 
						|
+	.shmem_unlock		= rt2800mmio_shmem_unlock,
 | 
						|
 };
 | 
						|
 
 | 
						|
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 | 
						|
--- a/drivers/net/wireless/rt2x00/rt2800soc.c
 | 
						|
+++ b/drivers/net/wireless/rt2x00/rt2800soc.c
 | 
						|
@@ -176,6 +176,9 @@ static const struct rt2800_ops rt2800soc
 | 
						|
 	.drv_write_firmware	= rt2800soc_write_firmware,
 | 
						|
 	.drv_init_registers	= rt2800mmio_init_registers,
 | 
						|
 	.drv_get_txwi		= rt2800mmio_get_txwi,
 | 
						|
+	.shmem_init_lock	= rt2800mmio_shmem_init_lock,
 | 
						|
+	.shmem_lock		= rt2800mmio_shmem_lock,
 | 
						|
+	.shmem_unlock		= rt2800mmio_shmem_unlock,
 | 
						|
 };
 | 
						|
 
 | 
						|
 static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
 | 
						|
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
 | 
						|
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
 | 
						|
@@ -51,6 +51,27 @@ static bool rt2800usb_hwcrypt_disabled(s
 | 
						|
 	return modparam_nohwcrypt;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static void rt2800usb_shmem_init_lock(struct rt2x00_dev *rt2x00dev)
 | 
						|
+{
 | 
						|
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
 | 
						|
+
 | 
						|
+	mutex_init(&drv_data->shmem_lock.mutex);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void rt2800usb_shmem_lock(struct rt2x00_dev *rt2x00dev)
 | 
						|
+{
 | 
						|
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
 | 
						|
+
 | 
						|
+	mutex_lock(&drv_data->shmem_lock.mutex);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void rt2800usb_shmem_unlock(struct rt2x00_dev *rt2x00dev)
 | 
						|
+{
 | 
						|
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
 | 
						|
+
 | 
						|
+	mutex_unlock(&drv_data->shmem_lock.mutex);
 | 
						|
+}
 | 
						|
+
 | 
						|
 /*
 | 
						|
  * Queue handlers.
 | 
						|
  */
 | 
						|
@@ -294,8 +315,10 @@ static int rt2800usb_write_firmware(stru
 | 
						|
 					      data + offset, length);
 | 
						|
 	}
 | 
						|
 
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
 | 
						|
 	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	/*
 | 
						|
 	 * Send firmware request to device to load firmware,
 | 
						|
@@ -310,7 +333,10 @@ static int rt2800usb_write_firmware(stru
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	msleep(10);
 | 
						|
+
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
@@ -328,8 +354,10 @@ static int rt2800usb_init_registers(stru
 | 
						|
 	if (rt2800_wait_csr_ready(rt2x00dev))
 | 
						|
 		return -EBUSY;
 | 
						|
 
 | 
						|
+	rt2800_shared_mem_lock(rt2x00dev);
 | 
						|
 	rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®);
 | 
						|
 	rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
 | 
						|
+	rt2800_shared_mem_unlock(rt2x00dev);
 | 
						|
 
 | 
						|
 	reg = 0;
 | 
						|
 	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1);
 | 
						|
@@ -859,6 +887,9 @@ static const struct rt2800_ops rt2800usb
 | 
						|
 	.drv_write_firmware	= rt2800usb_write_firmware,
 | 
						|
 	.drv_init_registers	= rt2800usb_init_registers,
 | 
						|
 	.drv_get_txwi		= rt2800usb_get_txwi,
 | 
						|
+	.shmem_init_lock	= rt2800usb_shmem_init_lock,
 | 
						|
+	.shmem_lock		= rt2800usb_shmem_lock,
 | 
						|
+	.shmem_unlock		= rt2800usb_shmem_unlock,
 | 
						|
 };
 | 
						|
 
 | 
						|
 static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 |