236e7ee239
Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 41016
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);
|
|
}
|
|
|
|
/*
|
|
@@ -4898,14 +4931,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);
|
|
}
|
|
|
|
/*
|
|
@@ -5031,8 +5069,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++) {
|
|
@@ -6728,11 +6768,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);
|
|
|
|
/*
|
|
@@ -7738,6 +7786,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;
|
|
@@ -7817,8 +7867,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 = {
|