diff options
Diffstat (limited to 'package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch')
-rw-r--r-- | package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch b/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch new file mode 100644 index 0000000..b8c1914 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch @@ -0,0 +1,131 @@ +From dcfe3dd46242050f100162dce2bcad24d2c942c6 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: rt2800lib: fix beacon generation on RT3593 + +On the RT3593 chipset, the beacon registers are located +in the high 8KB part of the shared memory. + +The high part of the shared memory is only accessible +if it is explicitly selected. Add a helper function +in order to be able to control the SHR_MSEL bit in +the PBF_SYS_CTRL register. Also add a few more helper +functions and use those to select the correct part of +the shared memory before and after accessing the beacon +registers. + +The base addresses of the beacon registers are also +different from the actually used values, so fix the +'rt2800_hw_beacon_base' function to return the correct +values. + +Signed-off-by: Gabor Juhos <juhosg@openwrt.org> +--- +Changes since v1: --- +--- + drivers/net/wireless/rt2x00/rt2800.h | 3 +++ + drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++ + 2 files changed, 47 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -574,6 +574,7 @@ + #define PBF_SYS_CTRL 0x0400 + #define PBF_SYS_CTRL_READY FIELD32(0x00000080) + #define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) ++#define PBF_SYS_CTRL_SHR_MSEL FIELD32(0x00080000) + + /* + * HOST-MCU shared memory +@@ -2026,6 +2027,8 @@ struct mac_iveiv_entry { + (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) + ++#define HW_BEACON_BASE_HIGH(__index) (0x4000 + (__index) * 512) ++ + #define BEACON_BASE_TO_OFFSET(_base) (((_base) - 0x4000) / 64) + + /* +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -82,6 +82,39 @@ static inline bool rt2800_is_305x_soc(st + return false; + } + ++static inline void rt2800_shared_mem_select(struct rt2x00_dev *rt2x00dev, ++ bool high) ++{ ++ u32 reg; ++ ++ if (WARN_ON_ONCE(!rt2800_has_high_shared_mem(rt2x00dev))) ++ return; ++ ++ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); ++ rt2x00_set_field32(®, PBF_SYS_CTRL_SHR_MSEL, high); ++ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg); ++} ++ ++static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev) ++{ ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ return true; ++ ++ return false; ++} ++ ++static inline void rt2800_select_beacon_mem(struct rt2x00_dev *rt2x00dev) ++{ ++ if (rt2800_beacon_uses_high_mem(rt2x00dev)) ++ rt2800_shared_mem_select(rt2x00dev, true); ++} ++ ++static inline void rt2800_deselect_beacon_mem(struct rt2x00_dev *rt2x00dev) ++{ ++ if (rt2800_beacon_uses_high_mem(rt2x00dev)) ++ rt2800_shared_mem_select(rt2x00dev, false); ++} ++ + static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) + { +@@ -948,6 +981,9 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry); + static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, + unsigned int index) + { ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ return HW_BEACON_BASE_HIGH(index); ++ + return HW_BEACON_BASE(index); + } + +@@ -1046,8 +1082,12 @@ void rt2800_write_beacon(struct queue_en + beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx); + + rt2800_shared_mem_lock(rt2x00dev); ++ ++ rt2800_select_beacon_mem(rt2x00dev); + rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, + entry->skb->len + padding_len); ++ rt2800_deselect_beacon_mem(rt2x00dev); ++ + rt2800_shared_mem_unlock(rt2x00dev); + __set_bit(ENTRY_BCN_ENABLED, &entry->flags); + +@@ -1080,6 +1120,8 @@ static inline void rt2800_clear_beacon_r + + rt2800_shared_mem_lock(rt2x00dev); + ++ rt2800_select_beacon_mem(rt2x00dev); ++ + /* + * For the Beacon base registers we only need to clear + * the whole TXWI which (when set to 0) will invalidate +@@ -1088,6 +1130,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_deselect_beacon_mem(rt2x00dev); ++ + rt2800_shared_mem_unlock(rt2x00dev); + } + |