add chaos_calmer branch
[15.05/openwrt.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