Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d56ad9c authored by Eliad Peller's avatar Eliad Peller Committed by Luciano Coelho
Browse files

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: default avatarEliad Peller <eliad@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 08c1d1c7
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -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);
+33 −49
Original line number Diff line number Diff line
@@ -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,25 +842,13 @@ 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
@@ -880,12 +860,18 @@ static void wl1271_fw_status(struct wl1271 *wl,
	 */
	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);

+9 −9
Original line number Diff line number Diff line
@@ -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,
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);

			/*
+1 −1
Original line number Diff line number Diff line
@@ -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
+24 −31
Original line number Diff line number Diff line
@@ -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;