aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2014-02-10 06:47:21 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-13 15:20:15 -0500
commit75fb4df7f804229372e073977615a149a4a28dc0 (patch)
treebd88a8d0778a94e69add3613996f6ad825e3841f /drivers/net/wireless/ti
parent7a536265b0b470893c13dc0f094e3078521818e2 (diff)
wlcore/wl12xx/wl18xx: simplify fw_status handling
Instead of splitting the fw_status into 2 and using some complex calculations, read the fw status and let each low-level driver (wl12xx/wl18xx) convert it into a common struct. This is required for the upcoming fw api changes, which break the current logic anyway. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ti')
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c35
-rw-r--r--drivers/net/wireless/ti/wl12xx/wl12xx.h50
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c39
-rw-r--r--drivers/net/wireless/ti/wl18xx/tx.c4
-rw-r--r--drivers/net/wireless/ti/wl18xx/wl18xx.h53
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c11
-rw-r--r--drivers/net/wireless/ti/wlcore/hw_ops.h9
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c96
-rw-r--r--drivers/net/wireless/ti/wlcore/rx.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/rx.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h7
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h72
12 files changed, 277 insertions, 103 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index be7129ba16ad..3ad8767505c5 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1378,7 +1378,7 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
1378 1378
1379static int wl12xx_tx_delayed_compl(struct wl1271 *wl) 1379static int wl12xx_tx_delayed_compl(struct wl1271 *wl)
1380{ 1380{
1381 if (wl->fw_status_1->tx_results_counter == 1381 if (wl->fw_status->tx_results_counter ==
1382 (wl->tx_results_count & 0xff)) 1382 (wl->tx_results_count & 0xff))
1383 return 0; 1383 return 0;
1384 1384
@@ -1438,6 +1438,37 @@ out:
1438 return ret; 1438 return ret;
1439} 1439}
1440 1440
1441static void wl12xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
1442 struct wl_fw_status *fw_status)
1443{
1444 struct wl12xx_fw_status *int_fw_status = raw_fw_status;
1445
1446 fw_status->intr = le32_to_cpu(int_fw_status->intr);
1447 fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
1448 fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
1449 fw_status->tx_results_counter = int_fw_status->tx_results_counter;
1450 fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
1451
1452 fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
1453 fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
1454 fw_status->link_fast_bitmap =
1455 le32_to_cpu(int_fw_status->link_fast_bitmap);
1456 fw_status->total_released_blks =
1457 le32_to_cpu(int_fw_status->total_released_blks);
1458 fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
1459
1460 fw_status->counters.tx_released_pkts =
1461 int_fw_status->counters.tx_released_pkts;
1462 fw_status->counters.tx_lnk_free_pkts =
1463 int_fw_status->counters.tx_lnk_free_pkts;
1464 fw_status->counters.tx_voice_released_blks =
1465 int_fw_status->counters.tx_voice_released_blks;
1466 fw_status->counters.tx_last_rate =
1467 int_fw_status->counters.tx_last_rate;
1468
1469 fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
1470}
1471
1441static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl, 1472static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
1442 struct wl12xx_vif *wlvif) 1473 struct wl12xx_vif *wlvif)
1443{ 1474{
@@ -1677,6 +1708,7 @@ static struct wlcore_ops wl12xx_ops = {
1677 .tx_delayed_compl = wl12xx_tx_delayed_compl, 1708 .tx_delayed_compl = wl12xx_tx_delayed_compl,
1678 .hw_init = wl12xx_hw_init, 1709 .hw_init = wl12xx_hw_init,
1679 .init_vif = NULL, 1710 .init_vif = NULL,
1711 .convert_fw_status = wl12xx_convert_fw_status,
1680 .sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask, 1712 .sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask,
1681 .get_pg_ver = wl12xx_get_pg_ver, 1713 .get_pg_ver = wl12xx_get_pg_ver,
1682 .get_mac = wl12xx_get_mac, 1714 .get_mac = wl12xx_get_mac,
@@ -1725,6 +1757,7 @@ static int wl12xx_setup(struct wl1271 *wl)
1725 wl->band_rate_to_idx = wl12xx_band_rate_to_idx; 1757 wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
1726 wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; 1758 wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
1727 wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; 1759 wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
1760 wl->fw_status_len = sizeof(struct wl12xx_fw_status);
1728 wl->fw_status_priv_len = 0; 1761 wl->fw_status_priv_len = 0;
1729 wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); 1762 wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics);
1730 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap); 1763 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap);
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index 9e5484a73667..b9950f87f01f 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -79,4 +79,54 @@ struct wl12xx_priv {
79 struct wl127x_rx_mem_pool_addr *rx_mem_addr; 79 struct wl127x_rx_mem_pool_addr *rx_mem_addr;
80}; 80};
81 81
82struct wl12xx_fw_packet_counters {
83 /* Cumulative counter of released packets per AC */
84 u8 tx_released_pkts[NUM_TX_QUEUES];
85
86 /* Cumulative counter of freed packets per HLID */
87 u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
88
89 /* Cumulative counter of released Voice memory blocks */
90 u8 tx_voice_released_blks;
91
92 /* Tx rate of the last transmitted packet */
93 u8 tx_last_rate;
94
95 u8 padding[2];
96} __packed;
97
98/* FW status registers */
99struct wl12xx_fw_status {
100 __le32 intr;
101 u8 fw_rx_counter;
102 u8 drv_rx_counter;
103 u8 reserved;
104 u8 tx_results_counter;
105 __le32 rx_pkt_descs[WL12XX_NUM_RX_DESCRIPTORS];
106
107 __le32 fw_localtime;
108
109 /*
110 * A bitmap (where each bit represents a single HLID)
111 * to indicate if the station is in PS mode.
112 */
113 __le32 link_ps_bitmap;
114
115 /*
116 * A bitmap (where each bit represents a single HLID) to indicate
117 * if the station is in Fast mode
118 */
119 __le32 link_fast_bitmap;
120
121 /* Cumulative counter of total released mem blocks since FW-reset */
122 __le32 total_released_blks;
123
124 /* Size (in Memory Blocks) of TX pool */
125 __le32 tx_total;
126
127 struct wl12xx_fw_packet_counters counters;
128
129 __le32 log_start_addr;
130} __packed;
131
82#endif /* __WL12XX_PRIV_H__ */ 132#endif /* __WL12XX_PRIV_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index ec37b16585df..cbf9bf375c14 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1133,6 +1133,39 @@ static int wl18xx_hw_init(struct wl1271 *wl)
1133 return ret; 1133 return ret;
1134} 1134}
1135 1135
1136static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
1137 struct wl_fw_status *fw_status)
1138{
1139 struct wl18xx_fw_status *int_fw_status = raw_fw_status;
1140
1141 fw_status->intr = le32_to_cpu(int_fw_status->intr);
1142 fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
1143 fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
1144 fw_status->tx_results_counter = int_fw_status->tx_results_counter;
1145 fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
1146
1147 fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
1148 fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
1149 fw_status->link_fast_bitmap =
1150 le32_to_cpu(int_fw_status->link_fast_bitmap);
1151 fw_status->total_released_blks =
1152 le32_to_cpu(int_fw_status->total_released_blks);
1153 fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
1154
1155 fw_status->counters.tx_released_pkts =
1156 int_fw_status->counters.tx_released_pkts;
1157 fw_status->counters.tx_lnk_free_pkts =
1158 int_fw_status->counters.tx_lnk_free_pkts;
1159 fw_status->counters.tx_voice_released_blks =
1160 int_fw_status->counters.tx_voice_released_blks;
1161 fw_status->counters.tx_last_rate =
1162 int_fw_status->counters.tx_last_rate;
1163
1164 fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
1165
1166 fw_status->priv = &int_fw_status->priv;
1167}
1168
1136static void wl18xx_set_tx_desc_csum(struct wl1271 *wl, 1169static void wl18xx_set_tx_desc_csum(struct wl1271 *wl,
1137 struct wl1271_tx_hw_descr *desc, 1170 struct wl1271_tx_hw_descr *desc,
1138 struct sk_buff *skb) 1171 struct sk_buff *skb)
@@ -1572,7 +1605,7 @@ static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
1572{ 1605{
1573 u8 thold; 1606 u8 thold;
1574 struct wl18xx_fw_status_priv *status_priv = 1607 struct wl18xx_fw_status_priv *status_priv =
1575 (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; 1608 (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
1576 u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); 1609 u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1577 1610
1578 /* suspended links are never high priority */ 1611 /* suspended links are never high priority */
@@ -1594,7 +1627,7 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
1594{ 1627{
1595 u8 thold; 1628 u8 thold;
1596 struct wl18xx_fw_status_priv *status_priv = 1629 struct wl18xx_fw_status_priv *status_priv =
1597 (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; 1630 (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
1598 u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); 1631 u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1599 1632
1600 if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) 1633 if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
@@ -1632,6 +1665,7 @@ static struct wlcore_ops wl18xx_ops = {
1632 .tx_immediate_compl = wl18xx_tx_immediate_completion, 1665 .tx_immediate_compl = wl18xx_tx_immediate_completion,
1633 .tx_delayed_compl = NULL, 1666 .tx_delayed_compl = NULL,
1634 .hw_init = wl18xx_hw_init, 1667 .hw_init = wl18xx_hw_init,
1668 .convert_fw_status = wl18xx_convert_fw_status,
1635 .set_tx_desc_csum = wl18xx_set_tx_desc_csum, 1669 .set_tx_desc_csum = wl18xx_set_tx_desc_csum,
1636 .get_pg_ver = wl18xx_get_pg_ver, 1670 .get_pg_ver = wl18xx_get_pg_ver,
1637 .set_rx_csum = wl18xx_set_rx_csum, 1671 .set_rx_csum = wl18xx_set_rx_csum,
@@ -1726,6 +1760,7 @@ static int wl18xx_setup(struct wl1271 *wl)
1726 wl->band_rate_to_idx = wl18xx_band_rate_to_idx; 1760 wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
1727 wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; 1761 wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
1728 wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; 1762 wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
1763 wl->fw_status_len = sizeof(struct wl18xx_fw_status);
1729 wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv); 1764 wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv);
1730 wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics); 1765 wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics);
1731 wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv); 1766 wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv);
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c
index 57c694396647..be1ebd55ac88 100644
--- a/drivers/net/wireless/ti/wl18xx/tx.c
+++ b/drivers/net/wireless/ti/wl18xx/tx.c
@@ -32,7 +32,7 @@ static
32void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif, 32void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
33 struct ieee80211_tx_rate *rate) 33 struct ieee80211_tx_rate *rate)
34{ 34{
35 u8 fw_rate = wl->fw_status_2->counters.tx_last_rate; 35 u8 fw_rate = wl->fw_status->counters.tx_last_rate;
36 36
37 if (fw_rate > CONF_HW_RATE_INDEX_MAX) { 37 if (fw_rate > CONF_HW_RATE_INDEX_MAX) {
38 wl1271_error("last Tx rate invalid: %d", fw_rate); 38 wl1271_error("last Tx rate invalid: %d", fw_rate);
@@ -139,7 +139,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
139void wl18xx_tx_immediate_complete(struct wl1271 *wl) 139void wl18xx_tx_immediate_complete(struct wl1271 *wl)
140{ 140{
141 struct wl18xx_fw_status_priv *status_priv = 141 struct wl18xx_fw_status_priv *status_priv =
142 (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; 142 (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
143 struct wl18xx_priv *priv = wl->priv; 143 struct wl18xx_priv *priv = wl->priv;
144 u8 i; 144 u8 i;
145 145
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index 9204e07ee432..d32a6af2df68 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -109,6 +109,59 @@ struct wl18xx_fw_status_priv {
109 u8 padding[3]; 109 u8 padding[3];
110}; 110};
111 111
112struct wl18xx_fw_packet_counters {
113 /* Cumulative counter of released packets per AC */
114 u8 tx_released_pkts[NUM_TX_QUEUES];
115
116 /* Cumulative counter of freed packets per HLID */
117 u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
118
119 /* Cumulative counter of released Voice memory blocks */
120 u8 tx_voice_released_blks;
121
122 /* Tx rate of the last transmitted packet */
123 u8 tx_last_rate;
124
125 u8 padding[2];
126} __packed;
127
128/* FW status registers */
129struct wl18xx_fw_status {
130 __le32 intr;
131 u8 fw_rx_counter;
132 u8 drv_rx_counter;
133 u8 reserved;
134 u8 tx_results_counter;
135 __le32 rx_pkt_descs[WL18XX_NUM_RX_DESCRIPTORS];
136
137 __le32 fw_localtime;
138
139 /*
140 * A bitmap (where each bit represents a single HLID)
141 * to indicate if the station is in PS mode.
142 */
143 __le32 link_ps_bitmap;
144
145 /*
146 * A bitmap (where each bit represents a single HLID) to indicate
147 * if the station is in Fast mode
148 */
149 __le32 link_fast_bitmap;
150
151 /* Cumulative counter of total released mem blocks since FW-reset */
152 __le32 total_released_blks;
153
154 /* Size (in Memory Blocks) of TX pool */
155 __le32 tx_total;
156
157 struct wl18xx_fw_packet_counters counters;
158
159 __le32 log_start_addr;
160
161 /* Private status to be used by the lower drivers */
162 struct wl18xx_fw_status_priv priv;
163} __packed;
164
112#define WL18XX_PHY_VERSION_MAX_LEN 20 165#define WL18XX_PHY_VERSION_MAX_LEN 20
113 166
114struct wl18xx_static_data_priv { 167struct wl18xx_static_data_priv {
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 9b2ecf52449f..4d19fd22e23c 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -324,9 +324,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
324 __set_bit(link, wlvif->links_map); 324 __set_bit(link, wlvif->links_map);
325 spin_unlock_irqrestore(&wl->wl_lock, flags); 325 spin_unlock_irqrestore(&wl->wl_lock, flags);
326 326
327 /* take the last "freed packets" value from the current FW status */ 327 /*
328 wl->links[link].prev_freed_pkts = 328 * take the last "freed packets" value from the current FW status.
329 wl->fw_status_2->counters.tx_lnk_free_pkts[link]; 329 * on recovery, we might not have fw_status yet, and
330 * tx_lnk_free_pkts will be NULL. check for it.
331 */
332 if (wl->fw_status->counters.tx_lnk_free_pkts)
333 wl->links[link].prev_freed_pkts =
334 wl->fw_status->counters.tx_lnk_free_pkts[link];
330 wl->links[link].wlvif = wlvif; 335 wl->links[link].wlvif = wlvif;
331 336
332 /* 337 /*
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 51f8d634d32f..1555ff970050 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -106,6 +106,15 @@ wlcore_hw_init_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
106 return 0; 106 return 0;
107} 107}
108 108
109static inline void
110wlcore_hw_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
111 struct wl_fw_status *fw_status)
112{
113 BUG_ON(!wl->ops->convert_fw_status);
114
115 wl->ops->convert_fw_status(wl, raw_fw_status, fw_status);
116}
117
109static inline u32 118static inline u32
110wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif) 119wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif)
111{ 120{
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 1e191967aa26..70a3e573ca3d 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -357,12 +357,12 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
357 357
358static void wl12xx_irq_update_links_status(struct wl1271 *wl, 358static void wl12xx_irq_update_links_status(struct wl1271 *wl,
359 struct wl12xx_vif *wlvif, 359 struct wl12xx_vif *wlvif,
360 struct wl_fw_status_2 *status) 360 struct wl_fw_status *status)
361{ 361{
362 u32 cur_fw_ps_map; 362 u32 cur_fw_ps_map;
363 u8 hlid; 363 u8 hlid;
364 364
365 cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap); 365 cur_fw_ps_map = status->link_ps_bitmap;
366 if (wl->ap_fw_ps_map != cur_fw_ps_map) { 366 if (wl->ap_fw_ps_map != cur_fw_ps_map) {
367 wl1271_debug(DEBUG_PSM, 367 wl1271_debug(DEBUG_PSM,
368 "link ps prev 0x%x cur 0x%x changed 0x%x", 368 "link ps prev 0x%x cur 0x%x changed 0x%x",
@@ -377,41 +377,38 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
377 wl->links[hlid].allocated_pkts); 377 wl->links[hlid].allocated_pkts);
378} 378}
379 379
380static int wlcore_fw_status(struct wl1271 *wl, 380static int wlcore_fw_status(struct wl1271 *wl, struct wl_fw_status *status)
381 struct wl_fw_status_1 *status_1,
382 struct wl_fw_status_2 *status_2)
383{ 381{
384 struct wl12xx_vif *wlvif; 382 struct wl12xx_vif *wlvif;
385 struct timespec ts; 383 struct timespec ts;
386 u32 old_tx_blk_count = wl->tx_blocks_available; 384 u32 old_tx_blk_count = wl->tx_blocks_available;
387 int avail, freed_blocks; 385 int avail, freed_blocks;
388 int i; 386 int i;
389 size_t status_len;
390 int ret; 387 int ret;
391 struct wl1271_link *lnk; 388 struct wl1271_link *lnk;
392 389
393 status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + 390 ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR,
394 sizeof(*status_2) + wl->fw_status_priv_len; 391 wl->raw_fw_status,
395 392 wl->fw_status_len, false);
396 ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1,
397 status_len, false);
398 if (ret < 0) 393 if (ret < 0)
399 return ret; 394 return ret;
400 395
396 wlcore_hw_convert_fw_status(wl, wl->raw_fw_status, wl->fw_status);
397
401 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " 398 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
402 "drv_rx_counter = %d, tx_results_counter = %d)", 399 "drv_rx_counter = %d, tx_results_counter = %d)",
403 status_1->intr, 400 status->intr,
404 status_1->fw_rx_counter, 401 status->fw_rx_counter,
405 status_1->drv_rx_counter, 402 status->drv_rx_counter,
406 status_1->tx_results_counter); 403 status->tx_results_counter);
407 404
408 for (i = 0; i < NUM_TX_QUEUES; i++) { 405 for (i = 0; i < NUM_TX_QUEUES; i++) {
409 /* prevent wrap-around in freed-packets counter */ 406 /* prevent wrap-around in freed-packets counter */
410 wl->tx_allocated_pkts[i] -= 407 wl->tx_allocated_pkts[i] -=
411 (status_2->counters.tx_released_pkts[i] - 408 (status->counters.tx_released_pkts[i] -
412 wl->tx_pkts_freed[i]) & 0xff; 409 wl->tx_pkts_freed[i]) & 0xff;
413 410
414 wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i]; 411 wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i];
415 } 412 }
416 413
417 414
@@ -420,29 +417,28 @@ static int wlcore_fw_status(struct wl1271 *wl,
420 lnk = &wl->links[i]; 417 lnk = &wl->links[i];
421 418
422 /* prevent wrap-around in freed-packets counter */ 419 /* prevent wrap-around in freed-packets counter */
423 diff = (status_2->counters.tx_lnk_free_pkts[i] - 420 diff = (status->counters.tx_lnk_free_pkts[i] -
424 lnk->prev_freed_pkts) & 0xff; 421 lnk->prev_freed_pkts) & 0xff;
425 422
426 if (diff == 0) 423 if (diff == 0)
427 continue; 424 continue;
428 425
429 lnk->allocated_pkts -= diff; 426 lnk->allocated_pkts -= diff;
430 lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i]; 427 lnk->prev_freed_pkts = status->counters.tx_lnk_free_pkts[i];
431 428
432 /* accumulate the prev_freed_pkts counter */ 429 /* accumulate the prev_freed_pkts counter */
433 lnk->total_freed_pkts += diff; 430 lnk->total_freed_pkts += diff;
434 } 431 }
435 432
436 /* prevent wrap-around in total blocks counter */ 433 /* prevent wrap-around in total blocks counter */
437 if (likely(wl->tx_blocks_freed <= 434 if (likely(wl->tx_blocks_freed <= status->total_released_blks))
438 le32_to_cpu(status_2->total_released_blks))) 435 freed_blocks = status->total_released_blks -
439 freed_blocks = le32_to_cpu(status_2->total_released_blks) -
440 wl->tx_blocks_freed; 436 wl->tx_blocks_freed;
441 else 437 else
442 freed_blocks = 0x100000000LL - wl->tx_blocks_freed + 438 freed_blocks = 0x100000000LL - wl->tx_blocks_freed +
443 le32_to_cpu(status_2->total_released_blks); 439 status->total_released_blks;
444 440
445 wl->tx_blocks_freed = le32_to_cpu(status_2->total_released_blks); 441 wl->tx_blocks_freed = status->total_released_blks;
446 442
447 wl->tx_allocated_blocks -= freed_blocks; 443 wl->tx_allocated_blocks -= freed_blocks;
448 444
@@ -458,7 +454,7 @@ static int wlcore_fw_status(struct wl1271 *wl,
458 cancel_delayed_work(&wl->tx_watchdog_work); 454 cancel_delayed_work(&wl->tx_watchdog_work);
459 } 455 }
460 456
461 avail = le32_to_cpu(status_2->tx_total) - wl->tx_allocated_blocks; 457 avail = status->tx_total - wl->tx_allocated_blocks;
462 458
463 /* 459 /*
464 * The FW might change the total number of TX memblocks before 460 * The FW might change the total number of TX memblocks before
@@ -477,15 +473,15 @@ static int wlcore_fw_status(struct wl1271 *wl,
477 473
478 /* for AP update num of allocated TX blocks per link and ps status */ 474 /* for AP update num of allocated TX blocks per link and ps status */
479 wl12xx_for_each_wlvif_ap(wl, wlvif) { 475 wl12xx_for_each_wlvif_ap(wl, wlvif) {
480 wl12xx_irq_update_links_status(wl, wlvif, status_2); 476 wl12xx_irq_update_links_status(wl, wlvif, status);
481 } 477 }
482 478
483 /* update the host-chipset time offset */ 479 /* update the host-chipset time offset */
484 getnstimeofday(&ts); 480 getnstimeofday(&ts);
485 wl->time_offset = (timespec_to_ns(&ts) >> 10) - 481 wl->time_offset = (timespec_to_ns(&ts) >> 10) -
486 (s64)le32_to_cpu(status_2->fw_localtime); 482 (s64)(status->fw_localtime);
487 483
488 wl->fw_fast_lnk_map = le32_to_cpu(status_2->link_fast_bitmap); 484 wl->fw_fast_lnk_map = status->link_fast_bitmap;
489 485
490 return 0; 486 return 0;
491} 487}
@@ -549,13 +545,13 @@ static int wlcore_irq_locked(struct wl1271 *wl)
549 clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); 545 clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
550 smp_mb__after_clear_bit(); 546 smp_mb__after_clear_bit();
551 547
552 ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); 548 ret = wlcore_fw_status(wl, wl->fw_status);
553 if (ret < 0) 549 if (ret < 0)
554 goto out; 550 goto out;
555 551
556 wlcore_hw_tx_immediate_compl(wl); 552 wlcore_hw_tx_immediate_compl(wl);
557 553
558 intr = le32_to_cpu(wl->fw_status_1->intr); 554 intr = wl->fw_status->intr;
559 intr &= WLCORE_ALL_INTR_MASK; 555 intr &= WLCORE_ALL_INTR_MASK;
560 if (!intr) { 556 if (!intr) {
561 done = true; 557 done = true;
@@ -584,7 +580,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
584 if (likely(intr & WL1271_ACX_INTR_DATA)) { 580 if (likely(intr & WL1271_ACX_INTR_DATA)) {
585 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); 581 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
586 582
587 ret = wlcore_rx(wl, wl->fw_status_1); 583 ret = wlcore_rx(wl, wl->fw_status);
588 if (ret < 0) 584 if (ret < 0)
589 goto out; 585 goto out;
590 586
@@ -843,11 +839,11 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
843 wl12xx_cmd_stop_fwlog(wl); 839 wl12xx_cmd_stop_fwlog(wl);
844 840
845 /* Read the first memory block address */ 841 /* Read the first memory block address */
846 ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); 842 ret = wlcore_fw_status(wl, wl->fw_status);
847 if (ret < 0) 843 if (ret < 0)
848 goto out; 844 goto out;
849 845
850 addr = le32_to_cpu(wl->fw_status_2->log_start_addr); 846 addr = wl->fw_status->log_start_addr;
851 if (!addr) 847 if (!addr)
852 goto out; 848 goto out;
853 849
@@ -990,23 +986,23 @@ static int wlcore_fw_wakeup(struct wl1271 *wl)
990 986
991static int wl1271_setup(struct wl1271 *wl) 987static int wl1271_setup(struct wl1271 *wl)
992{ 988{
993 wl->fw_status_1 = kzalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + 989 wl->raw_fw_status = kzalloc(wl->fw_status_len, GFP_KERNEL);
994 sizeof(*wl->fw_status_2) + 990 if (!wl->raw_fw_status)
995 wl->fw_status_priv_len, GFP_KERNEL); 991 goto err;
996 if (!wl->fw_status_1)
997 return -ENOMEM;
998 992
999 wl->fw_status_2 = (struct wl_fw_status_2 *) 993 wl->fw_status = kzalloc(sizeof(*wl->fw_status), GFP_KERNEL);
1000 (((u8 *) wl->fw_status_1) + 994 if (!wl->fw_status)
1001 WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc)); 995 goto err;
1002 996
1003 wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL); 997 wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
1004 if (!wl->tx_res_if) { 998 if (!wl->tx_res_if)
1005 kfree(wl->fw_status_1); 999 goto err;
1006 return -ENOMEM;
1007 }
1008 1000
1009 return 0; 1001 return 0;
1002err:
1003 kfree(wl->fw_status);
1004 kfree(wl->raw_fw_status);
1005 return -ENOMEM;
1010} 1006}
1011 1007
1012static int wl12xx_set_power_on(struct wl1271 *wl) 1008static int wl12xx_set_power_on(struct wl1271 *wl)
@@ -1952,9 +1948,10 @@ static void wlcore_op_stop_locked(struct wl1271 *wl)
1952 1948
1953 wl1271_debugfs_reset(wl); 1949 wl1271_debugfs_reset(wl);
1954 1950
1955 kfree(wl->fw_status_1); 1951 kfree(wl->raw_fw_status);
1956 wl->fw_status_1 = NULL; 1952 wl->raw_fw_status = NULL;
1957 wl->fw_status_2 = NULL; 1953 kfree(wl->fw_status);
1954 wl->fw_status = NULL;
1958 kfree(wl->tx_res_if); 1955 kfree(wl->tx_res_if);
1959 wl->tx_res_if = NULL; 1956 wl->tx_res_if = NULL;
1960 kfree(wl->target_mem_map); 1957 kfree(wl->target_mem_map);
@@ -6025,7 +6022,8 @@ int wlcore_free_hw(struct wl1271 *wl)
6025 kfree(wl->nvs); 6022 kfree(wl->nvs);
6026 wl->nvs = NULL; 6023 wl->nvs = NULL;
6027 6024
6028 kfree(wl->fw_status_1); 6025 kfree(wl->raw_fw_status);
6026 kfree(wl->fw_status);
6029 kfree(wl->tx_res_if); 6027 kfree(wl->tx_res_if);
6030 destroy_workqueue(wl->freezable_wq); 6028 destroy_workqueue(wl->freezable_wq);
6031 6029
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c
index 94ab445fde77..a047e879d37b 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -203,7 +203,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
203 return is_data; 203 return is_data;
204} 204}
205 205
206int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) 206int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status)
207{ 207{
208 unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; 208 unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
209 u32 buf_size; 209 u32 buf_size;
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h
index 3363f60fb7da..a3b1618db27c 100644
--- a/drivers/net/wireless/ti/wlcore/rx.h
+++ b/drivers/net/wireless/ti/wlcore/rx.h
@@ -142,7 +142,7 @@ struct wl1271_rx_descriptor {
142 u8 reserved; 142 u8 reserved;
143} __packed; 143} __packed;
144 144
145int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); 145int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status);
146u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); 146u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
147int wl1271_rx_filter_enable(struct wl1271 *wl, 147int wl1271_rx_filter_enable(struct wl1271 *wl,
148 int index, bool enable, 148 int index, bool enable,
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index a3cc11740c88..cec526502054 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -73,6 +73,8 @@ struct wlcore_ops {
73 void (*tx_immediate_compl)(struct wl1271 *wl); 73 void (*tx_immediate_compl)(struct wl1271 *wl);
74 int (*hw_init)(struct wl1271 *wl); 74 int (*hw_init)(struct wl1271 *wl);
75 int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); 75 int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
76 void (*convert_fw_status)(struct wl1271 *wl, void *raw_fw_status,
77 struct wl_fw_status *fw_status);
76 u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, 78 u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl,
77 struct wl12xx_vif *wlvif); 79 struct wl12xx_vif *wlvif);
78 int (*get_pg_ver)(struct wl1271 *wl, s8 *ver); 80 int (*get_pg_ver)(struct wl1271 *wl, s8 *ver);
@@ -346,8 +348,8 @@ struct wl1271 {
346 u32 buffer_cmd; 348 u32 buffer_cmd;
347 u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; 349 u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
348 350
349 struct wl_fw_status_1 *fw_status_1; 351 void *raw_fw_status;
350 struct wl_fw_status_2 *fw_status_2; 352 struct wl_fw_status *fw_status;
351 struct wl1271_tx_hw_res_if *tx_res_if; 353 struct wl1271_tx_hw_res_if *tx_res_if;
352 354
353 /* Current chipset configuration */ 355 /* Current chipset configuration */
@@ -448,6 +450,7 @@ struct wl1271 {
448 struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS]; 450 struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS];
449 451
450 /* size of the private FW status data */ 452 /* size of the private FW status data */
453 size_t fw_status_len;
451 size_t fw_status_priv_len; 454 size_t fw_status_priv_len;
452 455
453 /* RX Data filter rule state - enabled/disabled */ 456 /* RX Data filter rule state - enabled/disabled */
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 38153323a36b..32e1e8b23a8b 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -120,70 +120,58 @@ struct wl1271_chip {
120 120
121#define AP_MAX_STATIONS 8 121#define AP_MAX_STATIONS 8
122 122
123struct wl_fw_packet_counters { 123struct wl_fw_status {
124 /* Cumulative counter of released packets per AC */ 124 u32 intr;
125 u8 tx_released_pkts[NUM_TX_QUEUES];
126
127 /* Cumulative counter of freed packets per HLID */
128 u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
129
130 /* Cumulative counter of released Voice memory blocks */
131 u8 tx_voice_released_blks;
132
133 /* Tx rate of the last transmitted packet */
134 u8 tx_last_rate;
135
136 u8 padding[2];
137} __packed;
138
139/* FW status registers */
140struct wl_fw_status_1 {
141 __le32 intr;
142 u8 fw_rx_counter; 125 u8 fw_rx_counter;
143 u8 drv_rx_counter; 126 u8 drv_rx_counter;
144 u8 reserved;
145 u8 tx_results_counter; 127 u8 tx_results_counter;
146 __le32 rx_pkt_descs[0]; 128 __le32 *rx_pkt_descs;
147} __packed;
148
149/*
150 * Each HW arch has a different number of Rx descriptors.
151 * The length of the status depends on it, since it holds an array
152 * of descriptors.
153 */
154#define WLCORE_FW_STATUS_1_LEN(num_rx_desc) \
155 (sizeof(struct wl_fw_status_1) + \
156 (sizeof(((struct wl_fw_status_1 *)0)->rx_pkt_descs[0])) * \
157 num_rx_desc)
158 129
159struct wl_fw_status_2 { 130 u32 fw_localtime;
160 __le32 fw_localtime;
161 131
162 /* 132 /*
163 * A bitmap (where each bit represents a single HLID) 133 * A bitmap (where each bit represents a single HLID)
164 * to indicate if the station is in PS mode. 134 * to indicate if the station is in PS mode.
165 */ 135 */
166 __le32 link_ps_bitmap; 136 u32 link_ps_bitmap;
167 137
168 /* 138 /*
169 * A bitmap (where each bit represents a single HLID) to indicate 139 * A bitmap (where each bit represents a single HLID) to indicate
170 * if the station is in Fast mode 140 * if the station is in Fast mode
171 */ 141 */
172 __le32 link_fast_bitmap; 142 u32 link_fast_bitmap;
173 143
174 /* Cumulative counter of total released mem blocks since FW-reset */ 144 /* Cumulative counter of total released mem blocks since FW-reset */
175 __le32 total_released_blks; 145 u32 total_released_blks;
176 146
177 /* Size (in Memory Blocks) of TX pool */ 147 /* Size (in Memory Blocks) of TX pool */
178 __le32 tx_total; 148 u32 tx_total;
179 149
180 struct wl_fw_packet_counters counters; 150 struct {
151 /*
152 * Cumulative counter of released packets per AC
153 * (length of the array is NUM_TX_QUEUES)
154 */
155 u8 *tx_released_pkts;
156
157 /*
158 * Cumulative counter of freed packets per HLID
159 * (length of the array is WL12XX_MAX_LINKS)
160 */
161 u8 *tx_lnk_free_pkts;
162
163 /* Cumulative counter of released Voice memory blocks */
164 u8 tx_voice_released_blks;
165
166 /* Tx rate of the last transmitted packet */
167 u8 tx_last_rate;
168 } counters;
181 169
182 __le32 log_start_addr; 170 u32 log_start_addr;
183 171
184 /* Private status to be used by the lower drivers */ 172 /* Private status to be used by the lower drivers */
185 u8 priv[0]; 173 void *priv;
186} __packed; 174};
187 175
188#define WL1271_MAX_CHANNELS 64 176#define WL1271_MAX_CHANNELS 64
189struct wl1271_scan { 177struct wl1271_scan {