diff options
author | John Crispin <john@openwrt.org> | 2014-04-23 07:52:18 +0000 |
---|---|---|
committer | John Crispin <john@openwrt.org> | 2014-04-23 07:52:18 +0000 |
commit | 8be12510c972e15690b4e4c0cf78d6ea5f233ed2 (patch) | |
tree | 9596c36ce80b99f16b11fb6e1b27f85a138a5e11 /package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch | |
parent | 720a0a1df14d377832a627591a947432cbb6ab35 (diff) | |
download | upstream-8be12510c972e15690b4e4c0cf78d6ea5f233ed2.tar.gz upstream-8be12510c972e15690b4e4c0cf78d6ea5f233ed2.tar.bz2 upstream-8be12510c972e15690b4e4c0cf78d6ea5f233ed2.zip |
mac80211: rt2x00: add support for the RT3662/RT3883 SoCs
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
SVN-Revision: 40558
Diffstat (limited to 'package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch')
-rw-r--r-- | package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch | 531 |
1 files changed, 531 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch new file mode 100644 index 0000000000..879b4cc9e7 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch @@ -0,0 +1,531 @@ +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); +@@ -1001,8 +1011,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); + + /* + * Enable beaconing again. +@@ -1027,6 +1039,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 +@@ -1034,6 +1048,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) +@@ -1217,7 +1233,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, +@@ -1230,11 +1248,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, +@@ -1247,6 +1267,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, +@@ -1271,6 +1292,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); + +@@ -1280,8 +1302,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, +@@ -1304,8 +1329,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); + } + + /* +@@ -1320,10 +1348,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 +@@ -1393,8 +1423,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); + } + + /* +@@ -4876,14 +4909,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); + } + + /* +@@ -5009,8 +5047,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++) { +@@ -6706,11 +6746,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); + + /* +@@ -7716,6 +7764,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; +@@ -7795,8 +7845,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. + */ +@@ -260,8 +281,10 @@ static int rt2800usb_write_firmware(stru + rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, + 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, +@@ -276,7 +299,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; + } +@@ -294,8 +320,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); +@@ -810,6 +838,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 = { |