From 4d56ad9cae9e8553176427adc2335f8a7f4556b2 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 14 Aug 2011 13:17:05 +0300 Subject: [PATCH] wl12xx: update fw status struct Update the fw status struct according to the new fw api (fw >= 6/7.0.0.35). All the roles use the same struct now. The memory accounting was changed a bit according to the struct changes. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 5 +- drivers/net/wireless/wl12xx/main.c | 82 +++++++++++---------------- drivers/net/wireless/wl12xx/rx.c | 18 +++--- drivers/net/wireless/wl12xx/rx.h | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 55 ++++++++---------- 5 files changed, 68 insertions(+), 94 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index fd1c301be7c7..3102652c7625 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -349,10 +349,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(tx_packets_count); DRIVER_STATE_PRINT_INT(tx_results_count); DRIVER_STATE_PRINT_LHEX(flags); - DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]); - DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); - DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); - DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); + DRIVER_STATE_PRINT_INT(tx_blocks_freed); DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); DRIVER_STATE_PRINT_INT(rx_counter); DRIVER_STATE_PRINT_INT(session_counter); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 7fcdfa3ee1db..96f76b104e75 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -826,22 +826,14 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl, } #endif -static void wl1271_fw_status(struct wl1271 *wl, - struct wl1271_fw_full_status *full_status) +static void wl12xx_fw_status(struct wl1271 *wl, + struct wl12xx_fw_status *status) { - struct wl1271_fw_common_status *status = &full_status->common; struct timespec ts; u32 old_tx_blk_count = wl->tx_blocks_available; - u32 freed_blocks = 0; - int i; + int avail, freed_blocks; - if (wl->bss_type == BSS_TYPE_AP_BSS) { - wl1271_raw_read(wl, FW_STATUS_ADDR, status, - sizeof(struct wl1271_fw_ap_status), false); - } else { - wl1271_raw_read(wl, FW_STATUS_ADDR, status, - sizeof(struct wl1271_fw_sta_status), false); - } + wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " "drv_rx_counter = %d, tx_results_counter = %d)", @@ -850,42 +842,36 @@ static void wl1271_fw_status(struct wl1271 *wl, status->drv_rx_counter, status->tx_results_counter); - /* update number of available TX blocks */ - for (i = 0; i < NUM_TX_QUEUES; i++) { - freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - - wl->tx_blocks_freed[i]; - - wl->tx_blocks_freed[i] = - le32_to_cpu(status->tx_released_blks[i]); - } + freed_blocks = le32_to_cpu(status->total_released_blks) - + wl->tx_blocks_freed; + wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks); wl->tx_allocated_blocks -= freed_blocks; - if (wl->bss_type == BSS_TYPE_AP_BSS) { - /* Update num of allocated TX blocks per link and ps status */ -#if 0 - wl1271_irq_update_links_status(wl, &full_status->ap); -#endif - wl->tx_blocks_available += freed_blocks; - } else { - int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; + avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks; - /* - * The FW might change the total number of TX memblocks before - * we get a notification about blocks being released. Thus, the - * available blocks calculation might yield a temporary result - * which is lower than the actual available blocks. Keeping in - * mind that only blocks that were allocated can be moved from - * TX to RX, tx_blocks_available should never decrease here. - */ - wl->tx_blocks_available = max((int)wl->tx_blocks_available, - avail); - } + /* + * The FW might change the total number of TX memblocks before + * we get a notification about blocks being released. Thus, the + * available blocks calculation might yield a temporary result + * which is lower than the actual available blocks. Keeping in + * mind that only blocks that were allocated can be moved from + * TX to RX, tx_blocks_available should never decrease here. + */ + wl->tx_blocks_available = max((int)wl->tx_blocks_available, + avail); /* if more blocks are available now, tx work can be scheduled */ if (wl->tx_blocks_available > old_tx_blk_count) clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); + /* for AP update num of allocated TX blocks per link and ps status */ + if (wl->bss_type == BSS_TYPE_AP_BSS) { +#if 0 + wl1271_irq_update_links_status(wl, status); +#endif + } + /* update the host-chipset time offset */ getnstimeofday(&ts); wl->time_offset = (timespec_to_ns(&ts) >> 10) - @@ -958,8 +944,8 @@ irqreturn_t wl1271_irq(int irq, void *cookie) clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); smp_mb__after_clear_bit(); - wl1271_fw_status(wl, wl->fw_status); - intr = le32_to_cpu(wl->fw_status->common.intr); + wl12xx_fw_status(wl, wl->fw_status); + intr = le32_to_cpu(wl->fw_status->intr); intr &= WL1271_INTR_MASK; if (!intr) { done = true; @@ -978,7 +964,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) if (likely(intr & WL1271_ACX_INTR_DATA)) { wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); - wl1271_rx(wl, &wl->fw_status->common); + wl12xx_rx(wl, wl->fw_status); /* Check if any tx blocks were freed */ spin_lock_irqsave(&wl->wl_lock, flags); @@ -995,7 +981,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) } /* check for tx results */ - if (wl->fw_status->common.tx_results_counter != + if (wl->fw_status->tx_results_counter != (wl->tx_results_count & 0xff)) wl1271_tx_complete(wl); @@ -1169,8 +1155,8 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) wl12xx_cmd_stop_fwlog(wl); /* Read the first memory block address */ - wl1271_fw_status(wl, wl->fw_status); - first_addr = __le32_to_cpu(wl->fw_status->sta.log_start_addr); + wl12xx_fw_status(wl, wl->fw_status); + first_addr = le32_to_cpu(wl->fw_status->log_start_addr); if (!first_addr) goto out; @@ -1186,7 +1172,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) * of each memory block hold the hardware address of the next * one. The last memory block points to the first one. */ - addr = __le32_to_cpup((__le32 *)block); + addr = le32_to_cpup((__le32 *)block); if (!wl12xx_copy_fwlog(wl, block + sizeof(addr), WL12XX_HW_BLOCK_SIZE - sizeof(addr))) break; @@ -1923,7 +1909,6 @@ out: static void __wl1271_op_remove_interface(struct wl1271 *wl, bool reset_tx_queues) { - int i; wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); @@ -2004,8 +1989,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, */ wl->flags = 0; - for (i = 0; i < NUM_TX_QUEUES; i++) - wl->tx_blocks_freed[i] = 0; + wl->tx_blocks_freed = 0; wl1271_debugfs_reset(wl); diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 7a0c5fe294b2..78d8410da1f4 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -30,21 +30,21 @@ #include "rx.h" #include "io.h" -static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status, +static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, u32 drv_rx_counter) { return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & RX_MEM_BLOCK_MASK; } -static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status, - u32 drv_rx_counter) +static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status, + u32 drv_rx_counter) { return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; } -static bool wl1271_rx_get_unaligned(struct wl1271_fw_common_status *status, +static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status, u32 drv_rx_counter) { /* Convert the value to bool */ @@ -181,7 +181,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, return is_data; } -void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) +void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) { struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; u32 buf_size; @@ -199,7 +199,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) buf_size = 0; rx_counter = drv_rx_counter; while (rx_counter != fw_rx_counter) { - pkt_length = wl1271_rx_get_buf_size(status, rx_counter); + pkt_length = wl12xx_rx_get_buf_size(status, rx_counter); if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE) break; buf_size += pkt_length; @@ -218,7 +218,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) * For aggregated packets, only the first memory block * should be retrieved. The FW takes care of the rest. */ - mem_block = wl1271_rx_get_mem_block(status, + mem_block = wl12xx_rx_get_mem_block(status, drv_rx_counter); wl->rx_mem_pool_addr.addr = (mem_block << 8) + @@ -239,10 +239,10 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) /* Split data into separate packets */ pkt_offset = 0; while (pkt_offset < buf_size) { - pkt_length = wl1271_rx_get_buf_size(status, + pkt_length = wl12xx_rx_get_buf_size(status, drv_rx_counter); - unaligned = wl1271_rx_get_unaligned(status, + unaligned = wl12xx_rx_get_unaligned(status, drv_rx_counter); /* diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h index d3c0591665e8..00c1c1d27aaa 100644 --- a/drivers/net/wireless/wl12xx/rx.h +++ b/drivers/net/wireless/wl12xx/rx.h @@ -129,7 +129,7 @@ struct wl1271_rx_descriptor { u8 reserved; } __packed; -void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status); +void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); #endif diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 7707895120be..f708cd70185a 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -137,6 +137,7 @@ extern u32 wl12xx_debug_level; #define WL1271_DEFAULT_BEACON_INT 100 #define WL1271_DEFAULT_DTIM_PERIOD 1 +#define WL12XX_MAX_LINKS 8 #define WL1271_AP_GLOBAL_HLID 0 #define WL1271_AP_BROADCAST_HLID 1 #define WL1271_AP_STA_HLID_START 2 @@ -230,23 +231,15 @@ struct wl1271_stats { /* Broadcast and Global links + links to stations */ #define AP_MAX_LINKS (AP_MAX_STATIONS + 2) -/* FW status registers common for AP/STA */ -struct wl1271_fw_common_status { +/* 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[NUM_RX_PKT_DESC]; - __le32 tx_released_blks[NUM_TX_QUEUES]; __le32 fw_localtime; -} __packed; - -/* FW status registers for AP */ -struct wl1271_fw_ap_status { - struct wl1271_fw_common_status common; - - /* Next fields valid only in AP FW */ /* * A bitmap (where each bit represents a single HLID) @@ -254,29 +247,29 @@ struct wl1271_fw_ap_status { */ __le32 link_ps_bitmap; - /* Number of freed MBs per HLID */ - u8 tx_lnk_free_blks[AP_MAX_LINKS]; - u8 padding_1[1]; -} __packed; + /* + * A bitmap (where each bit represents a single HLID) to indicate + * if the station is in Fast mode + */ + __le32 link_fast_bitmap; -/* FW status registers for STA */ -struct wl1271_fw_sta_status { - struct wl1271_fw_common_status common; + /* Cumulative counter of total released mem blocks since FW-reset */ + __le32 total_released_blks; - u8 tx_total; - u8 reserved1; - __le16 reserved2; - __le32 log_start_addr; -} __packed; + /* Size (in Memory Blocks) of TX pool */ + __le32 tx_total; -struct wl1271_fw_full_status { - union { - struct wl1271_fw_common_status common; - struct wl1271_fw_sta_status sta; - struct wl1271_fw_ap_status ap; - }; -} __packed; + /* Cumulative counter of released mem-blocks per AC */ + u8 tx_released_blks[NUM_TX_QUEUES]; + /* Cumulative counter of freed MBs per HLID */ + u8 tx_lnk_free_blks[WL12XX_MAX_LINKS]; + + /* Cumulative counter of released Voice memory blocks */ + u8 tx_voice_released_blks; + u8 padding_1[7]; + __le32 log_start_addr; +} __packed; struct wl1271_rx_mem_pool_addr { u32 addr; @@ -401,7 +394,7 @@ struct wl1271 { struct wl1271_acx_mem_map *target_mem_map; /* Accounting for allocated / available TX blocks on HW */ - u32 tx_blocks_freed[NUM_TX_QUEUES]; + u32 tx_blocks_freed; u32 tx_blocks_available; u32 tx_allocated_blocks; u32 tx_results_count; @@ -537,7 +530,7 @@ struct wl1271 { u32 buffer_cmd; u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; - struct wl1271_fw_full_status *fw_status; + struct wl12xx_fw_status *fw_status; struct wl1271_tx_hw_res_if *tx_res_if; struct ieee80211_vif *vif; -- 2.30.2