[mac80211]: add add new firmware support and additional fixes for wl18xx
[15.05/openwrt.git] / package / kernel / mac80211 / patches / 905-wlcore-wl12xx-wl18xx-simplify-fw_status-handling.patch
1 Instead of splitting the fw_status into 2 and using some
2 complex calculations, read the fw status and let each low-level
3 driver (wl12xx/wl18xx) convert it into a common struct.
4
5 This is required for the upcoming fw api changes, which
6 break the current logic anyway.
7
8 Signed-off-by: Eliad Peller <eliad@wizery.com>
9
10 ---
11 drivers/net/wireless/ti/wl12xx/main.c     | 35 ++++++++++-
12  drivers/net/wireless/ti/wl12xx/wl12xx.h   | 50 ++++++++++++++++
13  drivers/net/wireless/ti/wl18xx/main.c     | 39 ++++++++++++-
14  drivers/net/wireless/ti/wl18xx/tx.c       |  4 +-
15  drivers/net/wireless/ti/wl18xx/wl18xx.h   | 53 +++++++++++++++++
16  drivers/net/wireless/ti/wlcore/cmd.c      | 11 +++-
17  drivers/net/wireless/ti/wlcore/hw_ops.h   |  9 +++
18  drivers/net/wireless/ti/wlcore/main.c     | 96 +++++++++++++++----------------
19  drivers/net/wireless/ti/wlcore/rx.c       |  2 +-
20  drivers/net/wireless/ti/wlcore/rx.h       |  2 +-
21  drivers/net/wireless/ti/wlcore/wlcore.h   |  7 ++-
22  drivers/net/wireless/ti/wlcore/wlcore_i.h | 72 ++++++++++-------------
23  12 files changed, 277 insertions(+), 103 deletions(-)
24
25 --- a/drivers/net/wireless/ti/wl12xx/main.c
26 +++ b/drivers/net/wireless/ti/wl12xx/main.c
27 @@ -1378,7 +1378,7 @@ static u32 wl12xx_get_rx_packet_len(stru
28  
29  static int wl12xx_tx_delayed_compl(struct wl1271 *wl)
30  {
31 -       if (wl->fw_status_1->tx_results_counter ==
32 +       if (wl->fw_status->tx_results_counter ==
33             (wl->tx_results_count & 0xff))
34                 return 0;
35  
36 @@ -1438,6 +1438,37 @@ out:
37         return ret;
38  }
39  
40 +static void wl12xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
41 +                                    struct wl_fw_status *fw_status)
42 +{
43 +       struct wl12xx_fw_status *int_fw_status = raw_fw_status;
44 +
45 +       fw_status->intr = le32_to_cpu(int_fw_status->intr);
46 +       fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
47 +       fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
48 +       fw_status->tx_results_counter = int_fw_status->tx_results_counter;
49 +       fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
50 +
51 +       fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
52 +       fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
53 +       fw_status->link_fast_bitmap =
54 +                       le32_to_cpu(int_fw_status->link_fast_bitmap);
55 +       fw_status->total_released_blks =
56 +                       le32_to_cpu(int_fw_status->total_released_blks);
57 +       fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
58 +
59 +       fw_status->counters.tx_released_pkts =
60 +                       int_fw_status->counters.tx_released_pkts;
61 +       fw_status->counters.tx_lnk_free_pkts =
62 +                       int_fw_status->counters.tx_lnk_free_pkts;
63 +       fw_status->counters.tx_voice_released_blks =
64 +                       int_fw_status->counters.tx_voice_released_blks;
65 +       fw_status->counters.tx_last_rate =
66 +                       int_fw_status->counters.tx_last_rate;
67 +
68 +       fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
69 +}
70 +
71  static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
72                                        struct wl12xx_vif *wlvif)
73  {
74 @@ -1677,6 +1708,7 @@ static struct wlcore_ops wl12xx_ops = {
75         .tx_delayed_compl       = wl12xx_tx_delayed_compl,
76         .hw_init                = wl12xx_hw_init,
77         .init_vif               = NULL,
78 +       .convert_fw_status      = wl12xx_convert_fw_status,
79         .sta_get_ap_rate_mask   = wl12xx_sta_get_ap_rate_mask,
80         .get_pg_ver             = wl12xx_get_pg_ver,
81         .get_mac                = wl12xx_get_mac,
82 @@ -1725,6 +1757,7 @@ static int wl12xx_setup(struct wl1271 *w
83         wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
84         wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
85         wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
86 +       wl->fw_status_len = sizeof(struct wl12xx_fw_status);
87         wl->fw_status_priv_len = 0;
88         wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics);
89         wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap);
90 --- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
91 +++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
92 @@ -79,4 +79,54 @@ struct wl12xx_priv {
93         struct wl127x_rx_mem_pool_addr *rx_mem_addr;
94  };
95  
96 +struct wl12xx_fw_packet_counters {
97 +       /* Cumulative counter of released packets per AC */
98 +       u8 tx_released_pkts[NUM_TX_QUEUES];
99 +
100 +       /* Cumulative counter of freed packets per HLID */
101 +       u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
102 +
103 +       /* Cumulative counter of released Voice memory blocks */
104 +       u8 tx_voice_released_blks;
105 +
106 +       /* Tx rate of the last transmitted packet */
107 +       u8 tx_last_rate;
108 +
109 +       u8 padding[2];
110 +} __packed;
111 +
112 +/* FW status registers */
113 +struct wl12xx_fw_status {
114 +       __le32 intr;
115 +       u8  fw_rx_counter;
116 +       u8  drv_rx_counter;
117 +       u8  reserved;
118 +       u8  tx_results_counter;
119 +       __le32 rx_pkt_descs[WL12XX_NUM_RX_DESCRIPTORS];
120 +
121 +       __le32 fw_localtime;
122 +
123 +       /*
124 +        * A bitmap (where each bit represents a single HLID)
125 +        * to indicate if the station is in PS mode.
126 +        */
127 +       __le32 link_ps_bitmap;
128 +
129 +       /*
130 +        * A bitmap (where each bit represents a single HLID) to indicate
131 +        * if the station is in Fast mode
132 +        */
133 +       __le32 link_fast_bitmap;
134 +
135 +       /* Cumulative counter of total released mem blocks since FW-reset */
136 +       __le32 total_released_blks;
137 +
138 +       /* Size (in Memory Blocks) of TX pool */
139 +       __le32 tx_total;
140 +
141 +       struct wl12xx_fw_packet_counters counters;
142 +
143 +       __le32 log_start_addr;
144 +} __packed;
145 +
146  #endif /* __WL12XX_PRIV_H__ */
147 --- a/drivers/net/wireless/ti/wl18xx/main.c
148 +++ b/drivers/net/wireless/ti/wl18xx/main.c
149 @@ -1133,6 +1133,39 @@ static int wl18xx_hw_init(struct wl1271
150         return ret;
151  }
152  
153 +static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
154 +                                    struct wl_fw_status *fw_status)
155 +{
156 +       struct wl18xx_fw_status *int_fw_status = raw_fw_status;
157 +
158 +       fw_status->intr = le32_to_cpu(int_fw_status->intr);
159 +       fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
160 +       fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
161 +       fw_status->tx_results_counter = int_fw_status->tx_results_counter;
162 +       fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
163 +
164 +       fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
165 +       fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
166 +       fw_status->link_fast_bitmap =
167 +                       le32_to_cpu(int_fw_status->link_fast_bitmap);
168 +       fw_status->total_released_blks =
169 +                       le32_to_cpu(int_fw_status->total_released_blks);
170 +       fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
171 +
172 +       fw_status->counters.tx_released_pkts =
173 +                       int_fw_status->counters.tx_released_pkts;
174 +       fw_status->counters.tx_lnk_free_pkts =
175 +                       int_fw_status->counters.tx_lnk_free_pkts;
176 +       fw_status->counters.tx_voice_released_blks =
177 +                       int_fw_status->counters.tx_voice_released_blks;
178 +       fw_status->counters.tx_last_rate =
179 +                       int_fw_status->counters.tx_last_rate;
180 +
181 +       fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
182 +
183 +       fw_status->priv = &int_fw_status->priv;
184 +}
185 +
186  static void wl18xx_set_tx_desc_csum(struct wl1271 *wl,
187                                     struct wl1271_tx_hw_descr *desc,
188                                     struct sk_buff *skb)
189 @@ -1572,7 +1605,7 @@ static bool wl18xx_lnk_high_prio(struct
190  {
191         u8 thold;
192         struct wl18xx_fw_status_priv *status_priv =
193 -               (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
194 +               (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
195         u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
196  
197         /* suspended links are never high priority */
198 @@ -1594,7 +1627,7 @@ static bool wl18xx_lnk_low_prio(struct w
199  {
200         u8 thold;
201         struct wl18xx_fw_status_priv *status_priv =
202 -               (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
203 +               (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
204         u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
205  
206         if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
207 @@ -1632,6 +1665,7 @@ static struct wlcore_ops wl18xx_ops = {
208         .tx_immediate_compl = wl18xx_tx_immediate_completion,
209         .tx_delayed_compl = NULL,
210         .hw_init        = wl18xx_hw_init,
211 +       .convert_fw_status = wl18xx_convert_fw_status,
212         .set_tx_desc_csum = wl18xx_set_tx_desc_csum,
213         .get_pg_ver     = wl18xx_get_pg_ver,
214         .set_rx_csum = wl18xx_set_rx_csum,
215 @@ -1726,6 +1760,7 @@ static int wl18xx_setup(struct wl1271 *w
216         wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
217         wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
218         wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
219 +       wl->fw_status_len = sizeof(struct wl18xx_fw_status);
220         wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv);
221         wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics);
222         wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv);
223 --- a/drivers/net/wireless/ti/wl18xx/tx.c
224 +++ b/drivers/net/wireless/ti/wl18xx/tx.c
225 @@ -32,7 +32,7 @@ static
226  void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
227                              struct ieee80211_tx_rate *rate)
228  {
229 -       u8 fw_rate = wl->fw_status_2->counters.tx_last_rate;
230 +       u8 fw_rate = wl->fw_status->counters.tx_last_rate;
231  
232         if (fw_rate > CONF_HW_RATE_INDEX_MAX) {
233                 wl1271_error("last Tx rate invalid: %d", fw_rate);
234 @@ -139,7 +139,7 @@ static void wl18xx_tx_complete_packet(st
235  void wl18xx_tx_immediate_complete(struct wl1271 *wl)
236  {
237         struct wl18xx_fw_status_priv *status_priv =
238 -               (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
239 +               (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
240         struct wl18xx_priv *priv = wl->priv;
241         u8 i;
242  
243 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
244 +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
245 @@ -109,6 +109,59 @@ struct wl18xx_fw_status_priv {
246         u8 padding[3];
247  };
248  
249 +struct wl18xx_fw_packet_counters {
250 +       /* Cumulative counter of released packets per AC */
251 +       u8 tx_released_pkts[NUM_TX_QUEUES];
252 +
253 +       /* Cumulative counter of freed packets per HLID */
254 +       u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
255 +
256 +       /* Cumulative counter of released Voice memory blocks */
257 +       u8 tx_voice_released_blks;
258 +
259 +       /* Tx rate of the last transmitted packet */
260 +       u8 tx_last_rate;
261 +
262 +       u8 padding[2];
263 +} __packed;
264 +
265 +/* FW status registers */
266 +struct wl18xx_fw_status {
267 +       __le32 intr;
268 +       u8  fw_rx_counter;
269 +       u8  drv_rx_counter;
270 +       u8  reserved;
271 +       u8  tx_results_counter;
272 +       __le32 rx_pkt_descs[WL18XX_NUM_RX_DESCRIPTORS];
273 +
274 +       __le32 fw_localtime;
275 +
276 +       /*
277 +        * A bitmap (where each bit represents a single HLID)
278 +        * to indicate if the station is in PS mode.
279 +        */
280 +       __le32 link_ps_bitmap;
281 +
282 +       /*
283 +        * A bitmap (where each bit represents a single HLID) to indicate
284 +        * if the station is in Fast mode
285 +        */
286 +       __le32 link_fast_bitmap;
287 +
288 +       /* Cumulative counter of total released mem blocks since FW-reset */
289 +       __le32 total_released_blks;
290 +
291 +       /* Size (in Memory Blocks) of TX pool */
292 +       __le32 tx_total;
293 +
294 +       struct wl18xx_fw_packet_counters counters;
295 +
296 +       __le32 log_start_addr;
297 +
298 +       /* Private status to be used by the lower drivers */
299 +       struct wl18xx_fw_status_priv priv;
300 +} __packed;
301 +
302  #define WL18XX_PHY_VERSION_MAX_LEN 20
303  
304  struct wl18xx_static_data_priv {
305 --- a/drivers/net/wireless/ti/wlcore/cmd.c
306 +++ b/drivers/net/wireless/ti/wlcore/cmd.c
307 @@ -324,9 +324,14 @@ int wl12xx_allocate_link(struct wl1271 *
308         __set_bit(link, wlvif->links_map);
309         spin_unlock_irqrestore(&wl->wl_lock, flags);
310  
311 -       /* take the last "freed packets" value from the current FW status */
312 -       wl->links[link].prev_freed_pkts =
313 -                       wl->fw_status_2->counters.tx_lnk_free_pkts[link];
314 +       /*
315 +        * take the last "freed packets" value from the current FW status.
316 +        * on recovery, we might not have fw_status yet, and
317 +        * tx_lnk_free_pkts will be NULL. check for it.
318 +        */
319 +       if (wl->fw_status->counters.tx_lnk_free_pkts)
320 +               wl->links[link].prev_freed_pkts =
321 +                       wl->fw_status->counters.tx_lnk_free_pkts[link];
322         wl->links[link].wlvif = wlvif;
323  
324         /*
325 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h
326 +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
327 @@ -106,6 +106,15 @@ wlcore_hw_init_vif(struct wl1271 *wl, st
328         return 0;
329  }
330  
331 +static inline void
332 +wlcore_hw_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
333 +                           struct wl_fw_status *fw_status)
334 +{
335 +       BUG_ON(!wl->ops->convert_fw_status);
336 +
337 +       wl->ops->convert_fw_status(wl, raw_fw_status, fw_status);
338 +}
339 +
340  static inline u32
341  wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif)
342  {
343 --- a/drivers/net/wireless/ti/wlcore/main.c
344 +++ b/drivers/net/wireless/ti/wlcore/main.c
345 @@ -357,12 +357,12 @@ static void wl12xx_irq_ps_regulate_link(
346  
347  static void wl12xx_irq_update_links_status(struct wl1271 *wl,
348                                            struct wl12xx_vif *wlvif,
349 -                                          struct wl_fw_status_2 *status)
350 +                                          struct wl_fw_status *status)
351  {
352         u32 cur_fw_ps_map;
353         u8 hlid;
354  
355 -       cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
356 +       cur_fw_ps_map = status->link_ps_bitmap;
357         if (wl->ap_fw_ps_map != cur_fw_ps_map) {
358                 wl1271_debug(DEBUG_PSM,
359                              "link ps prev 0x%x cur 0x%x changed 0x%x",
360 @@ -377,41 +377,38 @@ static void wl12xx_irq_update_links_stat
361                                             wl->links[hlid].allocated_pkts);
362  }
363  
364 -static int wlcore_fw_status(struct wl1271 *wl,
365 -                           struct wl_fw_status_1 *status_1,
366 -                           struct wl_fw_status_2 *status_2)
367 +static int wlcore_fw_status(struct wl1271 *wl, struct wl_fw_status *status)
368  {
369         struct wl12xx_vif *wlvif;
370         struct timespec ts;
371         u32 old_tx_blk_count = wl->tx_blocks_available;
372         int avail, freed_blocks;
373         int i;
374 -       size_t status_len;
375         int ret;
376         struct wl1271_link *lnk;
377  
378 -       status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
379 -               sizeof(*status_2) + wl->fw_status_priv_len;
380 -
381 -       ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1,
382 -                                  status_len, false);
383 +       ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR,
384 +                                  wl->raw_fw_status,
385 +                                  wl->fw_status_len, false);
386         if (ret < 0)
387                 return ret;
388  
389 +       wlcore_hw_convert_fw_status(wl, wl->raw_fw_status, wl->fw_status);
390 +
391         wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
392                      "drv_rx_counter = %d, tx_results_counter = %d)",
393 -                    status_1->intr,
394 -                    status_1->fw_rx_counter,
395 -                    status_1->drv_rx_counter,
396 -                    status_1->tx_results_counter);
397 +                    status->intr,
398 +                    status->fw_rx_counter,
399 +                    status->drv_rx_counter,
400 +                    status->tx_results_counter);
401  
402         for (i = 0; i < NUM_TX_QUEUES; i++) {
403                 /* prevent wrap-around in freed-packets counter */
404                 wl->tx_allocated_pkts[i] -=
405 -                               (status_2->counters.tx_released_pkts[i] -
406 +                               (status->counters.tx_released_pkts[i] -
407                                 wl->tx_pkts_freed[i]) & 0xff;
408  
409 -               wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i];
410 +               wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i];
411         }
412  
413  
414 @@ -420,29 +417,28 @@ static int wlcore_fw_status(struct wl127
415                 lnk = &wl->links[i];
416  
417                 /* prevent wrap-around in freed-packets counter */
418 -               diff = (status_2->counters.tx_lnk_free_pkts[i] -
419 +               diff = (status->counters.tx_lnk_free_pkts[i] -
420                        lnk->prev_freed_pkts) & 0xff;
421  
422                 if (diff == 0)
423                         continue;
424  
425                 lnk->allocated_pkts -= diff;
426 -               lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i];
427 +               lnk->prev_freed_pkts = status->counters.tx_lnk_free_pkts[i];
428  
429                 /* accumulate the prev_freed_pkts counter */
430                 lnk->total_freed_pkts += diff;
431         }
432  
433         /* prevent wrap-around in total blocks counter */
434 -       if (likely(wl->tx_blocks_freed <=
435 -                  le32_to_cpu(status_2->total_released_blks)))
436 -               freed_blocks = le32_to_cpu(status_2->total_released_blks) -
437 +       if (likely(wl->tx_blocks_freed <= status->total_released_blks))
438 +               freed_blocks = status->total_released_blks -
439                                wl->tx_blocks_freed;
440         else
441                 freed_blocks = 0x100000000LL - wl->tx_blocks_freed +
442 -                              le32_to_cpu(status_2->total_released_blks);
443 +                              status->total_released_blks;
444  
445 -       wl->tx_blocks_freed = le32_to_cpu(status_2->total_released_blks);
446 +       wl->tx_blocks_freed = status->total_released_blks;
447  
448         wl->tx_allocated_blocks -= freed_blocks;
449  
450 @@ -458,7 +454,7 @@ static int wlcore_fw_status(struct wl127
451                         cancel_delayed_work(&wl->tx_watchdog_work);
452         }
453  
454 -       avail = le32_to_cpu(status_2->tx_total) - wl->tx_allocated_blocks;
455 +       avail = status->tx_total - wl->tx_allocated_blocks;
456  
457         /*
458          * The FW might change the total number of TX memblocks before
459 @@ -477,15 +473,15 @@ static int wlcore_fw_status(struct wl127
460  
461         /* for AP update num of allocated TX blocks per link and ps status */
462         wl12xx_for_each_wlvif_ap(wl, wlvif) {
463 -               wl12xx_irq_update_links_status(wl, wlvif, status_2);
464 +               wl12xx_irq_update_links_status(wl, wlvif, status);
465         }
466  
467         /* update the host-chipset time offset */
468         getnstimeofday(&ts);
469         wl->time_offset = (timespec_to_ns(&ts) >> 10) -
470 -               (s64)le32_to_cpu(status_2->fw_localtime);
471 +               (s64)(status->fw_localtime);
472  
473 -       wl->fw_fast_lnk_map = le32_to_cpu(status_2->link_fast_bitmap);
474 +       wl->fw_fast_lnk_map = status->link_fast_bitmap;
475  
476         return 0;
477  }
478 @@ -549,13 +545,13 @@ static int wlcore_irq_locked(struct wl12
479                 clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
480                 smp_mb__after_clear_bit();
481  
482 -               ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2);
483 +               ret = wlcore_fw_status(wl, wl->fw_status);
484                 if (ret < 0)
485                         goto out;
486  
487                 wlcore_hw_tx_immediate_compl(wl);
488  
489 -               intr = le32_to_cpu(wl->fw_status_1->intr);
490 +               intr = wl->fw_status->intr;
491                 intr &= WLCORE_ALL_INTR_MASK;
492                 if (!intr) {
493                         done = true;
494 @@ -584,7 +580,7 @@ static int wlcore_irq_locked(struct wl12
495                 if (likely(intr & WL1271_ACX_INTR_DATA)) {
496                         wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
497  
498 -                       ret = wlcore_rx(wl, wl->fw_status_1);
499 +                       ret = wlcore_rx(wl, wl->fw_status);
500                         if (ret < 0)
501                                 goto out;
502  
503 @@ -843,11 +839,11 @@ static void wl12xx_read_fwlog_panic(stru
504                 wl12xx_cmd_stop_fwlog(wl);
505  
506         /* Read the first memory block address */
507 -       ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2);
508 +       ret = wlcore_fw_status(wl, wl->fw_status);
509         if (ret < 0)
510                 goto out;
511  
512 -       addr = le32_to_cpu(wl->fw_status_2->log_start_addr);
513 +       addr = wl->fw_status->log_start_addr;
514         if (!addr)
515                 goto out;
516  
517 @@ -990,23 +986,23 @@ static int wlcore_fw_wakeup(struct wl127
518  
519  static int wl1271_setup(struct wl1271 *wl)
520  {
521 -       wl->fw_status_1 = kzalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
522 -                                 sizeof(*wl->fw_status_2) +
523 -                                 wl->fw_status_priv_len, GFP_KERNEL);
524 -       if (!wl->fw_status_1)
525 -               return -ENOMEM;
526 +       wl->raw_fw_status = kzalloc(wl->fw_status_len, GFP_KERNEL);
527 +       if (!wl->raw_fw_status)
528 +               goto err;
529  
530 -       wl->fw_status_2 = (struct wl_fw_status_2 *)
531 -                               (((u8 *) wl->fw_status_1) +
532 -                               WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc));
533 +       wl->fw_status = kzalloc(sizeof(*wl->fw_status), GFP_KERNEL);
534 +       if (!wl->fw_status)
535 +               goto err;
536  
537         wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
538 -       if (!wl->tx_res_if) {
539 -               kfree(wl->fw_status_1);
540 -               return -ENOMEM;
541 -       }
542 +       if (!wl->tx_res_if)
543 +               goto err;
544  
545         return 0;
546 +err:
547 +       kfree(wl->fw_status);
548 +       kfree(wl->raw_fw_status);
549 +       return -ENOMEM;
550  }
551  
552  static int wl12xx_set_power_on(struct wl1271 *wl)
553 @@ -1952,9 +1948,10 @@ static void wlcore_op_stop_locked(struct
554  
555         wl1271_debugfs_reset(wl);
556  
557 -       kfree(wl->fw_status_1);
558 -       wl->fw_status_1 = NULL;
559 -       wl->fw_status_2 = NULL;
560 +       kfree(wl->raw_fw_status);
561 +       wl->raw_fw_status = NULL;
562 +       kfree(wl->fw_status);
563 +       wl->fw_status = NULL;
564         kfree(wl->tx_res_if);
565         wl->tx_res_if = NULL;
566         kfree(wl->target_mem_map);
567 @@ -6058,7 +6055,8 @@ int wlcore_free_hw(struct wl1271 *wl)
568         kfree(wl->nvs);
569         wl->nvs = NULL;
570  
571 -       kfree(wl->fw_status_1);
572 +       kfree(wl->raw_fw_status);
573 +       kfree(wl->fw_status);
574         kfree(wl->tx_res_if);
575         destroy_workqueue(wl->freezable_wq);
576  
577 --- a/drivers/net/wireless/ti/wlcore/rx.c
578 +++ b/drivers/net/wireless/ti/wlcore/rx.c
579 @@ -203,7 +203,7 @@ static int wl1271_rx_handle_data(struct
580         return is_data;
581  }
582  
583 -int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
584 +int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status)
585  {
586         unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
587         u32 buf_size;
588 --- a/drivers/net/wireless/ti/wlcore/rx.h
589 +++ b/drivers/net/wireless/ti/wlcore/rx.h
590 @@ -142,7 +142,7 @@ struct wl1271_rx_descriptor {
591         u8  reserved;
592  } __packed;
593  
594 -int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status);
595 +int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status);
596  u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
597  int wl1271_rx_filter_enable(struct wl1271 *wl,
598                             int index, bool enable,
599 --- a/drivers/net/wireless/ti/wlcore/wlcore.h
600 +++ b/drivers/net/wireless/ti/wlcore/wlcore.h
601 @@ -73,6 +73,8 @@ struct wlcore_ops {
602         void (*tx_immediate_compl)(struct wl1271 *wl);
603         int (*hw_init)(struct wl1271 *wl);
604         int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
605 +       void (*convert_fw_status)(struct wl1271 *wl, void *raw_fw_status,
606 +                                 struct wl_fw_status *fw_status);
607         u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl,
608                                     struct wl12xx_vif *wlvif);
609         int (*get_pg_ver)(struct wl1271 *wl, s8 *ver);
610 @@ -348,8 +350,8 @@ struct wl1271 {
611         u32 buffer_cmd;
612         u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
613  
614 -       struct wl_fw_status_1 *fw_status_1;
615 -       struct wl_fw_status_2 *fw_status_2;
616 +       void *raw_fw_status;
617 +       struct wl_fw_status *fw_status;
618         struct wl1271_tx_hw_res_if *tx_res_if;
619  
620         /* Current chipset configuration */
621 @@ -450,6 +452,7 @@ struct wl1271 {
622         struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS];
623  
624         /* size of the private FW status data */
625 +       size_t fw_status_len;
626         size_t fw_status_priv_len;
627  
628         /* RX Data filter rule state - enabled/disabled */
629 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
630 +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
631 @@ -120,70 +120,58 @@ struct wl1271_chip {
632  
633  #define AP_MAX_STATIONS            8
634  
635 -struct wl_fw_packet_counters {
636 -       /* Cumulative counter of released packets per AC */
637 -       u8 tx_released_pkts[NUM_TX_QUEUES];
638 -
639 -       /* Cumulative counter of freed packets per HLID */
640 -       u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
641 -
642 -       /* Cumulative counter of released Voice memory blocks */
643 -       u8 tx_voice_released_blks;
644 -
645 -       /* Tx rate of the last transmitted packet */
646 -       u8 tx_last_rate;
647 -
648 -       u8 padding[2];
649 -} __packed;
650 -
651 -/* FW status registers */
652 -struct wl_fw_status_1 {
653 -       __le32 intr;
654 +struct wl_fw_status {
655 +       u32 intr;
656         u8  fw_rx_counter;
657         u8  drv_rx_counter;
658 -       u8  reserved;
659         u8  tx_results_counter;
660 -       __le32 rx_pkt_descs[0];
661 -} __packed;
662 -
663 -/*
664 - * Each HW arch has a different number of Rx descriptors.
665 - * The length of the status depends on it, since it holds an array
666 - * of descriptors.
667 - */
668 -#define WLCORE_FW_STATUS_1_LEN(num_rx_desc) \
669 -               (sizeof(struct wl_fw_status_1) + \
670 -               (sizeof(((struct wl_fw_status_1 *)0)->rx_pkt_descs[0])) * \
671 -               num_rx_desc)
672 +       __le32 *rx_pkt_descs;
673  
674 -struct wl_fw_status_2 {
675 -       __le32 fw_localtime;
676 +       u32 fw_localtime;
677  
678         /*
679          * A bitmap (where each bit represents a single HLID)
680          * to indicate if the station is in PS mode.
681          */
682 -       __le32 link_ps_bitmap;
683 +       u32 link_ps_bitmap;
684  
685         /*
686          * A bitmap (where each bit represents a single HLID) to indicate
687          * if the station is in Fast mode
688          */
689 -       __le32 link_fast_bitmap;
690 +       u32 link_fast_bitmap;
691  
692         /* Cumulative counter of total released mem blocks since FW-reset */
693 -       __le32 total_released_blks;
694 +       u32 total_released_blks;
695  
696         /* Size (in Memory Blocks) of TX pool */
697 -       __le32 tx_total;
698 +       u32 tx_total;
699  
700 -       struct wl_fw_packet_counters counters;
701 +       struct {
702 +               /*
703 +                * Cumulative counter of released packets per AC
704 +                * (length of the array is NUM_TX_QUEUES)
705 +                */
706 +               u8 *tx_released_pkts;
707 +
708 +               /*
709 +                * Cumulative counter of freed packets per HLID
710 +                * (length of the array is WL12XX_MAX_LINKS)
711 +                */
712 +               u8 *tx_lnk_free_pkts;
713 +
714 +               /* Cumulative counter of released Voice memory blocks */
715 +               u8 tx_voice_released_blks;
716 +
717 +               /* Tx rate of the last transmitted packet */
718 +               u8 tx_last_rate;
719 +       } counters;
720  
721 -       __le32 log_start_addr;
722 +       u32 log_start_addr;
723  
724         /* Private status to be used by the lower drivers */
725 -       u8 priv[0];
726 -} __packed;
727 +       void *priv;
728 +};
729  
730  #define WL1271_MAX_CHANNELS 64
731  struct wl1271_scan {