Commit 75fb4df7 authored by Eliad Peller's avatar Eliad Peller Committed by John W. Linville

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: default avatarEliad Peller <eliad@wizery.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 7a536265
...@@ -1378,7 +1378,7 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, ...@@ -1378,7 +1378,7 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
static int wl12xx_tx_delayed_compl(struct wl1271 *wl) static int wl12xx_tx_delayed_compl(struct wl1271 *wl)
{ {
if (wl->fw_status_1->tx_results_counter == if (wl->fw_status->tx_results_counter ==
(wl->tx_results_count & 0xff)) (wl->tx_results_count & 0xff))
return 0; return 0;
...@@ -1438,6 +1438,37 @@ static int wl12xx_hw_init(struct wl1271 *wl) ...@@ -1438,6 +1438,37 @@ static int wl12xx_hw_init(struct wl1271 *wl)
return ret; return ret;
} }
static void wl12xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
struct wl_fw_status *fw_status)
{
struct wl12xx_fw_status *int_fw_status = raw_fw_status;
fw_status->intr = le32_to_cpu(int_fw_status->intr);
fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
fw_status->tx_results_counter = int_fw_status->tx_results_counter;
fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
fw_status->link_fast_bitmap =
le32_to_cpu(int_fw_status->link_fast_bitmap);
fw_status->total_released_blks =
le32_to_cpu(int_fw_status->total_released_blks);
fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
fw_status->counters.tx_released_pkts =
int_fw_status->counters.tx_released_pkts;
fw_status->counters.tx_lnk_free_pkts =
int_fw_status->counters.tx_lnk_free_pkts;
fw_status->counters.tx_voice_released_blks =
int_fw_status->counters.tx_voice_released_blks;
fw_status->counters.tx_last_rate =
int_fw_status->counters.tx_last_rate;
fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
}
static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl, static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
struct wl12xx_vif *wlvif) struct wl12xx_vif *wlvif)
{ {
...@@ -1677,6 +1708,7 @@ static struct wlcore_ops wl12xx_ops = { ...@@ -1677,6 +1708,7 @@ static struct wlcore_ops wl12xx_ops = {
.tx_delayed_compl = wl12xx_tx_delayed_compl, .tx_delayed_compl = wl12xx_tx_delayed_compl,
.hw_init = wl12xx_hw_init, .hw_init = wl12xx_hw_init,
.init_vif = NULL, .init_vif = NULL,
.convert_fw_status = wl12xx_convert_fw_status,
.sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask, .sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask,
.get_pg_ver = wl12xx_get_pg_ver, .get_pg_ver = wl12xx_get_pg_ver,
.get_mac = wl12xx_get_mac, .get_mac = wl12xx_get_mac,
...@@ -1725,6 +1757,7 @@ static int wl12xx_setup(struct wl1271 *wl) ...@@ -1725,6 +1757,7 @@ static int wl12xx_setup(struct wl1271 *wl)
wl->band_rate_to_idx = wl12xx_band_rate_to_idx; wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
wl->fw_status_len = sizeof(struct wl12xx_fw_status);
wl->fw_status_priv_len = 0; wl->fw_status_priv_len = 0;
wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics);
wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap); wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap);
......
...@@ -79,4 +79,54 @@ struct wl12xx_priv { ...@@ -79,4 +79,54 @@ struct wl12xx_priv {
struct wl127x_rx_mem_pool_addr *rx_mem_addr; struct wl127x_rx_mem_pool_addr *rx_mem_addr;
}; };
struct wl12xx_fw_packet_counters {
/* Cumulative counter of released packets per AC */
u8 tx_released_pkts[NUM_TX_QUEUES];
/* Cumulative counter of freed packets per HLID */
u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
/* Cumulative counter of released Voice memory blocks */
u8 tx_voice_released_blks;
/* Tx rate of the last transmitted packet */
u8 tx_last_rate;
u8 padding[2];
} __packed;
/* FW status registers */
struct wl12xx_fw_status {
__le32 intr;
u8 fw_rx_counter;
u8 drv_rx_counter;
u8 reserved;
u8 tx_results_counter;
__le32 rx_pkt_descs[WL12XX_NUM_RX_DESCRIPTORS];
__le32 fw_localtime;
/*
* A bitmap (where each bit represents a single HLID)
* to indicate if the station is in PS mode.
*/
__le32 link_ps_bitmap;
/*
* A bitmap (where each bit represents a single HLID) to indicate
* if the station is in Fast mode
*/
__le32 link_fast_bitmap;
/* Cumulative counter of total released mem blocks since FW-reset */
__le32 total_released_blks;
/* Size (in Memory Blocks) of TX pool */
__le32 tx_total;
struct wl12xx_fw_packet_counters counters;
__le32 log_start_addr;
} __packed;
#endif /* __WL12XX_PRIV_H__ */ #endif /* __WL12XX_PRIV_H__ */
...@@ -1133,6 +1133,39 @@ static int wl18xx_hw_init(struct wl1271 *wl) ...@@ -1133,6 +1133,39 @@ static int wl18xx_hw_init(struct wl1271 *wl)
return ret; return ret;
} }
static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
struct wl_fw_status *fw_status)
{
struct wl18xx_fw_status *int_fw_status = raw_fw_status;
fw_status->intr = le32_to_cpu(int_fw_status->intr);
fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
fw_status->tx_results_counter = int_fw_status->tx_results_counter;
fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
fw_status->link_fast_bitmap =
le32_to_cpu(int_fw_status->link_fast_bitmap);
fw_status->total_released_blks =
le32_to_cpu(int_fw_status->total_released_blks);
fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
fw_status->counters.tx_released_pkts =
int_fw_status->counters.tx_released_pkts;
fw_status->counters.tx_lnk_free_pkts =
int_fw_status->counters.tx_lnk_free_pkts;
fw_status->counters.tx_voice_released_blks =
int_fw_status->counters.tx_voice_released_blks;
fw_status->counters.tx_last_rate =
int_fw_status->counters.tx_last_rate;
fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
fw_status->priv = &int_fw_status->priv;
}
static void wl18xx_set_tx_desc_csum(struct wl1271 *wl, static void wl18xx_set_tx_desc_csum(struct wl1271 *wl,
struct wl1271_tx_hw_descr *desc, struct wl1271_tx_hw_descr *desc,
struct sk_buff *skb) struct sk_buff *skb)
...@@ -1572,7 +1605,7 @@ static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid, ...@@ -1572,7 +1605,7 @@ static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
{ {
u8 thold; u8 thold;
struct wl18xx_fw_status_priv *status_priv = struct wl18xx_fw_status_priv *status_priv =
(struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
/* suspended links are never high priority */ /* suspended links are never high priority */
...@@ -1594,7 +1627,7 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, ...@@ -1594,7 +1627,7 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
{ {
u8 thold; u8 thold;
struct wl18xx_fw_status_priv *status_priv = struct wl18xx_fw_status_priv *status_priv =
(struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
...@@ -1632,6 +1665,7 @@ static struct wlcore_ops wl18xx_ops = { ...@@ -1632,6 +1665,7 @@ static struct wlcore_ops wl18xx_ops = {
.tx_immediate_compl = wl18xx_tx_immediate_completion, .tx_immediate_compl = wl18xx_tx_immediate_completion,
.tx_delayed_compl = NULL, .tx_delayed_compl = NULL,
.hw_init = wl18xx_hw_init, .hw_init = wl18xx_hw_init,
.convert_fw_status = wl18xx_convert_fw_status,
.set_tx_desc_csum = wl18xx_set_tx_desc_csum, .set_tx_desc_csum = wl18xx_set_tx_desc_csum,
.get_pg_ver = wl18xx_get_pg_ver, .get_pg_ver = wl18xx_get_pg_ver,
.set_rx_csum = wl18xx_set_rx_csum, .set_rx_csum = wl18xx_set_rx_csum,
...@@ -1726,6 +1760,7 @@ static int wl18xx_setup(struct wl1271 *wl) ...@@ -1726,6 +1760,7 @@ static int wl18xx_setup(struct wl1271 *wl)
wl->band_rate_to_idx = wl18xx_band_rate_to_idx; wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0;
wl->fw_status_len = sizeof(struct wl18xx_fw_status);
wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv); wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv);
wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics); wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics);
wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv); wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv);
......
...@@ -32,7 +32,7 @@ static ...@@ -32,7 +32,7 @@ static
void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif, void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
struct ieee80211_tx_rate *rate) struct ieee80211_tx_rate *rate)
{ {
u8 fw_rate = wl->fw_status_2->counters.tx_last_rate; u8 fw_rate = wl->fw_status->counters.tx_last_rate;
if (fw_rate > CONF_HW_RATE_INDEX_MAX) { if (fw_rate > CONF_HW_RATE_INDEX_MAX) {
wl1271_error("last Tx rate invalid: %d", fw_rate); 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) ...@@ -139,7 +139,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
void wl18xx_tx_immediate_complete(struct wl1271 *wl) void wl18xx_tx_immediate_complete(struct wl1271 *wl)
{ {
struct wl18xx_fw_status_priv *status_priv = struct wl18xx_fw_status_priv *status_priv =
(struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; (struct wl18xx_fw_status_priv *)wl->fw_status->priv;
struct wl18xx_priv *priv = wl->priv; struct wl18xx_priv *priv = wl->priv;
u8 i; u8 i;
......
...@@ -109,6 +109,59 @@ struct wl18xx_fw_status_priv { ...@@ -109,6 +109,59 @@ struct wl18xx_fw_status_priv {
u8 padding[3]; u8 padding[3];
}; };
struct wl18xx_fw_packet_counters {
/* Cumulative counter of released packets per AC */
u8 tx_released_pkts[NUM_TX_QUEUES];
/* Cumulative counter of freed packets per HLID */
u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
/* Cumulative counter of released Voice memory blocks */
u8 tx_voice_released_blks;
/* Tx rate of the last transmitted packet */
u8 tx_last_rate;
u8 padding[2];
} __packed;
/* FW status registers */
struct wl18xx_fw_status {
__le32 intr;
u8 fw_rx_counter;
u8 drv_rx_counter;
u8 reserved;
u8 tx_results_counter;
__le32 rx_pkt_descs[WL18XX_NUM_RX_DESCRIPTORS];
__le32 fw_localtime;
/*
* A bitmap (where each bit represents a single HLID)
* to indicate if the station is in PS mode.
*/
__le32 link_ps_bitmap;
/*
* A bitmap (where each bit represents a single HLID) to indicate
* if the station is in Fast mode
*/
__le32 link_fast_bitmap;
/* Cumulative counter of total released mem blocks since FW-reset */
__le32 total_released_blks;
/* Size (in Memory Blocks) of TX pool */
__le32 tx_total;
struct wl18xx_fw_packet_counters counters;
__le32 log_start_addr;
/* Private status to be used by the lower drivers */
struct wl18xx_fw_status_priv priv;
} __packed;
#define WL18XX_PHY_VERSION_MAX_LEN 20 #define WL18XX_PHY_VERSION_MAX_LEN 20
struct wl18xx_static_data_priv { struct wl18xx_static_data_priv {
......
...@@ -324,9 +324,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) ...@@ -324,9 +324,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
__set_bit(link, wlvif->links_map); __set_bit(link, wlvif->links_map);
spin_unlock_irqrestore(&wl->wl_lock, flags); spin_unlock_irqrestore(&wl->wl_lock, flags);
/* take the last "freed packets" value from the current FW status */ /*
wl->links[link].prev_freed_pkts = * take the last "freed packets" value from the current FW status.
wl->fw_status_2->counters.tx_lnk_free_pkts[link]; * on recovery, we might not have fw_status yet, and
* tx_lnk_free_pkts will be NULL. check for it.
*/
if (wl->fw_status->counters.tx_lnk_free_pkts)
wl->links[link].prev_freed_pkts =
wl->fw_status->counters.tx_lnk_free_pkts[link];
wl->links[link].wlvif = wlvif; wl->links[link].wlvif = wlvif;
/* /*
......
...@@ -106,6 +106,15 @@ wlcore_hw_init_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif) ...@@ -106,6 +106,15 @@ wlcore_hw_init_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
return 0; return 0;
} }
static inline void
wlcore_hw_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
struct wl_fw_status *fw_status)
{
BUG_ON(!wl->ops->convert_fw_status);
wl->ops->convert_fw_status(wl, raw_fw_status, fw_status);
}
static inline u32 static inline u32
wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif) wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{ {
......
...@@ -357,12 +357,12 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, ...@@ -357,12 +357,12 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
static void wl12xx_irq_update_links_status(struct wl1271 *wl, static void wl12xx_irq_update_links_status(struct wl1271 *wl,
struct wl12xx_vif *wlvif, struct wl12xx_vif *wlvif,
struct wl_fw_status_2 *status) struct wl_fw_status *status)
{ {
u32 cur_fw_ps_map; u32 cur_fw_ps_map;
u8 hlid; u8 hlid;
cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap); cur_fw_ps_map = status->link_ps_bitmap;
if (wl->ap_fw_ps_map != cur_fw_ps_map) { if (wl->ap_fw_ps_map != cur_fw_ps_map) {
wl1271_debug(DEBUG_PSM, wl1271_debug(DEBUG_PSM,
"link ps prev 0x%x cur 0x%x changed 0x%x", "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,41 +377,38 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
wl->links[hlid].allocated_pkts); wl->links[hlid].allocated_pkts);
} }
static int wlcore_fw_status(struct wl1271 *wl, static int wlcore_fw_status(struct wl1271 *wl, struct wl_fw_status *status)
struct wl_fw_status_1 *status_1,
struct wl_fw_status_2 *status_2)
{ {
struct wl12xx_vif *wlvif; struct wl12xx_vif *wlvif;
struct timespec ts; struct timespec ts;
u32 old_tx_blk_count = wl->tx_blocks_available; u32 old_tx_blk_count = wl->tx_blocks_available;
int avail, freed_blocks; int avail, freed_blocks;
int i; int i;
size_t status_len;
int ret; int ret;
struct wl1271_link *lnk; struct wl1271_link *lnk;
status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR,
sizeof(*status_2) + wl->fw_status_priv_len; wl->raw_fw_status,
wl->fw_status_len, false);
ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1,
status_len, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
wlcore_hw_convert_fw_status(wl, wl->raw_fw_status, wl->fw_status);
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)", "drv_rx_counter = %d, tx_results_counter = %d)",
status_1->intr, status->intr,
status_1->fw_rx_counter, status->fw_rx_counter,
status_1->drv_rx_counter, status->drv_rx_counter,
status_1->tx_results_counter); status->tx_results_counter);
for (i = 0; i < NUM_TX_QUEUES; i++) { for (i = 0; i < NUM_TX_QUEUES; i++) {
/* prevent wrap-around in freed-packets counter */ /* prevent wrap-around in freed-packets counter */
wl->tx_allocated_pkts[i] -= wl->tx_allocated_pkts[i] -=
(status_2->counters.tx_released_pkts[i] - (status->counters.tx_released_pkts[i] -
wl->tx_pkts_freed[i]) & 0xff; wl->tx_pkts_freed[i]) & 0xff;
wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i]; wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i];
} }
...@@ -420,29 +417,28 @@ static int wlcore_fw_status(struct wl1271 *wl, ...@@ -420,29 +417,28 @@ static int wlcore_fw_status(struct wl1271 *wl,
lnk = &wl->links[i]; lnk = &wl->links[i];
/* prevent wrap-around in freed-packets counter */ /* prevent wrap-around in freed-packets counter */
diff = (status_2->counters.tx_lnk_free_pkts[i] - diff = (status->counters.tx_lnk_free_pkts[i] -
lnk->prev_freed_pkts) & 0xff; lnk->prev_freed_pkts) & 0xff;
if (diff == 0) if (diff == 0)
continue; continue;
lnk->allocated_pkts -= diff; lnk->allocated_pkts -= diff;
lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i]; lnk->prev_freed_pkts = status->counters.tx_lnk_free_pkts[i];
/* accumulate the prev_freed_pkts counter */ /* accumulate the prev_freed_pkts counter */
lnk->total_freed_pkts += diff; lnk->total_freed_pkts += diff;
} }
/* prevent wrap-around in total blocks counter */ /* prevent wrap-around in total blocks counter */
if (likely(wl->tx_blocks_freed <= if (likely(wl->tx_blocks_freed <= status->total_released_blks))
le32_to_cpu(status_2->total_released_blks))) freed_blocks = status->total_released_blks -
freed_blocks = le32_to_cpu(status_2->total_released_blks) -
wl->tx_blocks_freed; wl->tx_blocks_freed;
else else
freed_blocks = 0x100000000LL - wl->tx_blocks_freed + freed_blocks = 0x100000000LL - wl->tx_blocks_freed +
le32_to_cpu(status_2->total_released_blks); status->total_released_blks;
wl->tx_blocks_freed = le32_to_cpu(status_2->total_released_blks); wl->tx_blocks_freed = status->total_released_blks;
wl->tx_allocated_blocks -= freed_blocks; wl->tx_allocated_blocks -= freed_blocks;
...@@ -458,7 +454,7 @@ static int wlcore_fw_status(struct wl1271 *wl, ...@@ -458,7 +454,7 @@ static int wlcore_fw_status(struct wl1271 *wl,
cancel_delayed_work(&wl->tx_watchdog_work); cancel_delayed_work(&wl->tx_watchdog_work);
} }
avail = le32_to_cpu(status_2->tx_total) - wl->tx_allocated_blocks; avail = status->tx_total - wl->tx_allocated_blocks;
/* /*
* The FW might change the total number of TX memblocks before * The FW might change the total number of TX memblocks before
...@@ -477,15 +473,15 @@ static int wlcore_fw_status(struct wl1271 *wl, ...@@ -477,15 +473,15 @@ static int wlcore_fw_status(struct wl1271 *wl,
/* for AP update num of allocated TX blocks per link and ps status */ /* for AP update num of allocated TX blocks per link and ps status */
wl12xx_for_each_wlvif_ap(wl, wlvif) { wl12xx_for_each_wlvif_ap(wl, wlvif) {
wl12xx_irq_update_links_status(wl, wlvif, status_2); wl12xx_irq_update_links_status(wl, wlvif, status);
} }
/* update the host-chipset time offset */ /* update the host-chipset time offset */
getnstimeofday(&ts); getnstimeofday(&ts);
wl->time_offset = (timespec_to_ns(&ts) >> 10) - wl->time_offset = (timespec_to_ns(&ts) >> 10) -
(s64)le32_to_cpu(status_2->fw_localtime); (s64)(status->fw_localtime);
wl->fw_fast_lnk_map = le32_to_cpu(status_2->link_fast_bitmap); wl->fw_fast_lnk_map = status->link_fast_bitmap;
return 0; return 0;
} }
...@@ -549,13 +545,13 @@ static int wlcore_irq_locked(struct wl1271 *wl) ...@@ -549,13 +545,13 @@ static int wlcore_irq_locked(struct wl1271 *wl)
clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
smp_mb__after_clear_bit(); smp_mb__after_clear_bit();
ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); ret = wlcore_fw_status(wl, wl->fw_status);
if (ret < 0) if (ret < 0)
goto out; goto out;
wlcore_hw_tx_immediate_compl(wl); wlcore_hw_tx_immediate_compl(wl);
intr = le32_to_cpu(wl->fw_status_1->intr); intr = wl->fw_status->intr;
intr &= WLCORE_ALL_INTR_MASK; intr &= WLCORE_ALL_INTR_MASK;
if (!intr) { if (!intr) {
done = true; done = true;
...@@ -584,7 +580,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) ...@@ -584,7 +580,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
if (likely(intr & WL1271_ACX_INTR_DATA)) { if (likely(intr & WL1271_ACX_INTR_DATA)) {
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
ret = wlcore_rx(wl, wl->fw_status_1); ret = wlcore_rx(wl, wl->fw_status);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -843,11 +839,11 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) ...@@ -843,11 +839,11 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
wl12xx_cmd_stop_fwlog(wl); wl12xx_cmd_stop_fwlog(wl);
/* Read the first memory block address */ /* Read the first memory block address */
ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); ret = wlcore_fw_status(wl, wl->fw_status);
if (ret < 0) if (ret < 0)
goto out; goto out;
addr = le32_to_cpu(wl->fw_status_2->log_start_addr); addr = wl->fw_status->log_start_addr;
if (!addr) if (!addr)
goto out; goto out;
...@@ -990,23 +986,23 @@ static int wlcore_fw_wakeup(struct wl1271 *wl) ...@@ -990,23 +986,23 @@ static int wlcore_fw_wakeup(struct wl1271 *wl)
static int wl1271_setup(struct wl1271 *wl) static int wl1271_setup(struct wl1271 *wl)
{ {
wl->fw_status_1 = kzalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + wl->raw_fw_status = kzalloc(wl->fw_status_len, GFP_KERNEL);
sizeof(*wl->fw_status_2) + if (!wl->raw_fw_status)
wl->fw_status_priv_len, GFP_KERNEL); goto err;
if (!wl->fw_status_1)
return -ENOMEM;
wl->fw_status_2 = (struct wl_fw_status_2 *) wl->fw_status = kzalloc(sizeof(*wl->fw_status), GFP_KERNEL);
(((u8 *) wl->fw_status_1) + if (!wl->fw_status)
WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc)); goto err;
wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL); wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
if (!wl->tx_res_if) { if (!wl->tx_res_if)
kfree(wl->fw_status_1); goto err;
return -ENOMEM;
}
return 0; return 0;
err:
kfree(wl->fw_status);
kfree(wl->raw_fw_status);
return -ENOMEM;
} }
static int wl12xx_set_power_on(struct wl1271 *wl) static int wl12xx_set_power_on(struct wl1271 *wl)
...@@ -1952,9 +1948,10 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) ...@@ -1952,9 +1948,10 @@ static void wlcore_op_stop_locked(struct wl1271 *wl)
wl1271_debugfs_reset(wl); wl1271_debugfs_reset(wl);
kfree(wl->fw_status_1); kfree(wl->raw_fw_status);
wl->fw_status_1 = NULL; wl->raw_fw_status = NULL;
wl->fw_status_2 = NULL; kfree(wl->fw_status);
wl->fw_status = NULL;
kfree(wl->tx_res_if); kfree(wl->tx_res_if);
wl->tx_res_if = NULL; wl->tx_res_if = NULL;
kfree(wl->target_mem_map); kfree(wl->target_mem_map);
...@@ -6025,7 +6022,8 @@ int wlcore_free_hw(struct wl1271 *wl) ...@@ -6025,7 +6022,8 @@ int wlcore_free_hw(struct wl1271 *wl)
kfree(wl->nvs); kfree(wl->nvs);
wl->nvs = NULL; wl->nvs = NULL;
kfree(wl->fw_status_1); kfree(wl->raw_fw_status);
kfree(wl->fw_status);
kfree(wl->tx_res_if); kfree(wl->tx_res_if);
destroy_workqueue(wl->freezable_wq); destroy_workqueue(wl->freezable_wq);
......
...@@ -203,7 +203,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, ...@@ -203,7 +203,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
return is_data; return is_data;
} }
int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status)
{ {
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
u32 buf_size; u32 buf_size;
......
...@@ -142,7 +142,7 @@ struct wl1271_rx_descriptor { ...@@ -142,7 +142,7 @@ struct wl1271_rx_descriptor {
u8 reserved; u8 reserved;
} __packed; } __packed;
int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
int wl1271_rx_filter_enable(struct wl1271 *wl, int wl1271_rx_filter_enable(struct wl1271 *wl,
int index, bool enable, int index, bool enable,
......
...@@ -73,6 +73,8 @@ struct wlcore_ops { ...@@ -73,6 +73,8 @@ struct wlcore_ops {
void (*tx_immediate_compl)(struct wl1271 *wl); void (*tx_immediate_compl)(struct wl1271 *wl);
int (*hw_init)(struct wl1271 *wl); int (*hw_init)(struct wl1271 *wl);
int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void (*convert_fw_status)(struct wl1271 *wl, void *raw_fw_status,
struct wl_fw_status *fw_status);
u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl,
struct wl12xx_vif *wlvif); struct wl12xx_vif *wlvif);
int (*get_pg_ver)(struct wl1271 *wl, s8 *ver); int (*get_pg_ver)(struct wl1271 *wl, s8 *ver);
...@@ -346,8 +348,8 @@ struct wl1271 { ...@@ -346,8 +348,8 @@ struct wl1271 {
u32 buffer_cmd; u32 buffer_cmd;
u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
struct wl_fw_status_1 *fw_status_1; void *raw_fw_status;
struct wl_fw_status_2 *fw_status_2; struct wl_fw_status *fw_status;
struct wl1271_tx_hw_res_if *tx_res_if; struct wl1271_tx_hw_res_if *tx_res_if;
/* Current chipset configuration */ /* Current chipset configuration */
...@@ -448,6 +450,7 @@ struct wl1271 { ...@@ -448,6 +450,7 @@ struct wl1271 {
struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS]; struct ieee80211_sta_ht_cap ht_cap[WLCORE_NUM_BANDS];
/* size of the private FW status data */ /* size of the private FW status data */
size_t fw_status_len;
size_t fw_status_priv_len; size_t fw_status_priv_len;
/* RX Data filter rule state - enabled/disabled */ /* RX Data filter rule state - enabled/disabled */
......
...@@ -120,70 +120,58 @@ struct wl1271_chip { ...@@ -120,70 +120,58 @@ struct wl1271_chip {
#define AP_MAX_STATIONS 8 #define AP_MAX_STATIONS 8
struct wl_fw_packet_counters { struct wl_fw_status {
/* Cumulative counter of released packets per AC */ u32 intr;
u8 tx_released_pkts[NUM_TX_QUEUES];
/* Cumulative counter of freed packets per HLID */
u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
/* Cumulative counter of released Voice memory blocks */
u8 tx_voice_released_blks;
/* Tx rate of the last transmitted packet */
u8 tx_last_rate;
u8 padding[2];
} __packed;
/* FW status registers */
struct wl_fw_status_1 {
__le32 intr;
u8 fw_rx_counter; u8 fw_rx_counter;
u8 drv_rx_counter; u8 drv_rx_counter;
u8 reserved;
u8 tx_results_counter; u8 tx_results_counter;
__le32 rx_pkt_descs[0]; __le32 *rx_pkt_descs;
} __packed;
/*
* Each HW arch has a different number of Rx descriptors.
* The length of the status depends on it, since it holds an array
* of descriptors.
*/
#define WLCORE_FW_STATUS_1_LEN(num_rx_desc) \
(sizeof(struct wl_fw_status_1) + \
(sizeof(((struct wl_fw_status_1 *)0)->rx_pkt_descs[0])) * \
num_rx_desc)
struct wl_fw_status_2 { u32 fw_localtime;
__le32 fw_localtime;
/* /*
* A bitmap (where each bit represents a single HLID) * A bitmap (where each bit represents a single HLID)
* to indicate if the station is in PS mode. * to indicate if the station is in PS mode.
*/ */
__le32 link_ps_bitmap; u32 link_ps_bitmap;
/* /*
* A bitmap (where each bit represents a single HLID) to indicate * A bitmap (where each bit represents a single HLID) to indicate
* if the station is in Fast mode * if the station is in Fast mode
*/ */
__le32 link_fast_bitmap; u32 link_fast_bitmap;
/* Cumulative counter of total released mem blocks since FW-reset */ /* Cumulative counter of total released mem blocks since FW-reset */
__le32 total_released_blks; u32 total_released_blks;
/* Size (in Memory Blocks) of TX pool */ /* Size (in Memory Blocks) of TX pool */
__le32 tx_total; u32 tx_total;
struct wl_fw_packet_counters counters; struct {
/*
* Cumulative counter of released packets per AC
* (length of the array is NUM_TX_QUEUES)
*/
u8 *tx_released_pkts;
/*
* Cumulative counter of freed packets per HLID
* (length of the array is WL12XX_MAX_LINKS)
*/
u8 *tx_lnk_free_pkts;
/* Cumulative counter of released Voice memory blocks */
u8 tx_voice_released_blks;
/* Tx rate of the last transmitted packet */
u8 tx_last_rate;
} counters;
__le32 log_start_addr; u32 log_start_addr;
/* Private status to be used by the lower drivers */ /* Private status to be used by the lower drivers */
u8 priv[0]; void *priv;
} __packed; };
#define WL1271_MAX_CHANNELS 64 #define WL1271_MAX_CHANNELS 64
struct wl1271_scan { struct wl1271_scan {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment