kernel: backport ssb changes from 4.4-rc1
[openwrt/staging/yousong.git] / package / kernel / mac80211 / patches / 600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch
1 From dcfe3dd46242050f100162dce2bcad24d2c942c6 Mon Sep 17 00:00:00 2001
2 From: Gabor Juhos <juhosg@openwrt.org>
3 Date: Sat, 17 Aug 2013 19:31:42 +0200
4 Subject: [PATCH] rt2x00: rt2800lib: fix beacon generation on RT3593
5
6 On the RT3593 chipset, the beacon registers are located
7 in the high 8KB part of the shared memory.
8
9 The high part of the shared memory is only accessible
10 if it is explicitly selected. Add a helper function
11 in order to be able to control the SHR_MSEL bit in
12 the PBF_SYS_CTRL register. Also add a few more helper
13 functions and use those to select the correct part of
14 the shared memory before and after accessing the beacon
15 registers.
16
17 The base addresses of the beacon registers are also
18 different from the actually used values, so fix the
19 'rt2800_hw_beacon_base' function to return the correct
20 values.
21
22 Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
23 ---
24 Changes since v1: ---
25 ---
26 drivers/net/wireless/rt2x00/rt2800.h | 3 +++
27 drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++
28 2 files changed, 47 insertions(+)
29
30 --- a/drivers/net/wireless/rt2x00/rt2800.h
31 +++ b/drivers/net/wireless/rt2x00/rt2800.h
32 @@ -574,6 +574,7 @@
33 #define PBF_SYS_CTRL 0x0400
34 #define PBF_SYS_CTRL_READY FIELD32(0x00000080)
35 #define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000)
36 +#define PBF_SYS_CTRL_SHR_MSEL FIELD32(0x00080000)
37
38 /*
39 * HOST-MCU shared memory
40 @@ -2026,6 +2027,8 @@ struct mac_iveiv_entry {
41 (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
42 (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
43
44 +#define HW_BEACON_BASE_HIGH(__index) (0x4000 + (__index) * 512)
45 +
46 #define BEACON_BASE_TO_OFFSET(_base) (((_base) - 0x4000) / 64)
47
48 /*
49 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
50 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
51 @@ -82,6 +82,39 @@ static inline bool rt2800_is_305x_soc(st
52 return false;
53 }
54
55 +static inline void rt2800_shared_mem_select(struct rt2x00_dev *rt2x00dev,
56 + bool high)
57 +{
58 + u32 reg;
59 +
60 + if (WARN_ON_ONCE(!rt2800_has_high_shared_mem(rt2x00dev)))
61 + return;
62 +
63 + rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
64 + rt2x00_set_field32(&reg, PBF_SYS_CTRL_SHR_MSEL, high);
65 + rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
66 +}
67 +
68 +static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev)
69 +{
70 + if (rt2x00_rt(rt2x00dev, RT3593))
71 + return true;
72 +
73 + return false;
74 +}
75 +
76 +static inline void rt2800_select_beacon_mem(struct rt2x00_dev *rt2x00dev)
77 +{
78 + if (rt2800_beacon_uses_high_mem(rt2x00dev))
79 + rt2800_shared_mem_select(rt2x00dev, true);
80 +}
81 +
82 +static inline void rt2800_deselect_beacon_mem(struct rt2x00_dev *rt2x00dev)
83 +{
84 + if (rt2800_beacon_uses_high_mem(rt2x00dev))
85 + rt2800_shared_mem_select(rt2x00dev, false);
86 +}
87 +
88 static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
89 const unsigned int word, const u8 value)
90 {
91 @@ -948,6 +981,9 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
92 static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
93 unsigned int index)
94 {
95 + if (rt2x00_rt(rt2x00dev, RT3593))
96 + return HW_BEACON_BASE_HIGH(index);
97 +
98 return HW_BEACON_BASE(index);
99 }
100
101 @@ -1046,8 +1082,12 @@ void rt2800_write_beacon(struct queue_en
102 beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
103
104 rt2800_shared_mem_lock(rt2x00dev);
105 +
106 + rt2800_select_beacon_mem(rt2x00dev);
107 rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
108 entry->skb->len + padding_len);
109 + rt2800_deselect_beacon_mem(rt2x00dev);
110 +
111 rt2800_shared_mem_unlock(rt2x00dev);
112 __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
113
114 @@ -1080,6 +1120,8 @@ static inline void rt2800_clear_beacon_r
115
116 rt2800_shared_mem_lock(rt2x00dev);
117
118 + rt2800_select_beacon_mem(rt2x00dev);
119 +
120 /*
121 * For the Beacon base registers we only need to clear
122 * the whole TXWI which (when set to 0) will invalidate
123 @@ -1088,6 +1130,8 @@ static inline void rt2800_clear_beacon_r
124 for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
125 rt2800_register_write(rt2x00dev, beacon_base + i, 0);
126
127 + rt2800_deselect_beacon_mem(rt2x00dev);
128 +
129 rt2800_shared_mem_unlock(rt2x00dev);
130 }
131