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

Commit 0afd04e5 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Luciano Coelho
Browse files

wlcore/wl12xx/18xx: split fw_status struct into two



The number of RX packet descriptors may vary from chip to chip and
in different firmware versions.  Unfortunately, the array that
contains the actual descriptors is in the middle of the fw_status
structure.  To manage this, we split the struct into two so we can
calculate the offset of what comes after the array and access the last
elements more easily.

[Changed the STATUS_LEN macro to be placement agnostic - Arik]

Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
parent 102165c6
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1156,7 +1156,8 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,

static void wl12xx_tx_delayed_compl(struct wl1271 *wl)
{
	if (wl->fw_status->tx_results_counter == (wl->tx_results_count & 0xff))
	if (wl->fw_status_1->tx_results_counter ==
	    (wl->tx_results_count & 0xff))
		return;

	wl1271_tx_complete(wl);
@@ -1414,6 +1415,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
	wl->ptable = wl12xx_ptable;
	wl->rtable = wl12xx_rtable;
	wl->num_tx_desc = 16;
	wl->num_rx_desc = 8;
	wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT;
	wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE;
	wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
+1 −0
Original line number Diff line number Diff line
@@ -1041,6 +1041,7 @@ int __devinit wl18xx_probe(struct platform_device *pdev)
	wl->ptable = wl18xx_ptable;
	wl->rtable = wl18xx_rtable;
	wl->num_tx_desc = 32;
	wl->num_rx_desc = 16;
	wl->normal_tx_spare = WL18XX_TX_HW_BLOCK_SPARE;
	wl->gem_tx_spare = WL18XX_TX_HW_GEM_BLOCK_SPARE;
	wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
void wl18xx_tx_immediate_complete(struct wl1271 *wl)
{
	struct wl18xx_fw_status_priv *status_priv =
		(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
		(struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
	struct wl18xx_priv *priv = wl->priv;
	u8 i;

+36 −28
Original line number Diff line number Diff line
@@ -347,7 +347,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,

static void wl12xx_irq_update_links_status(struct wl1271 *wl,
					   struct wl12xx_vif *wlvif,
					   struct wl_fw_status *status)
					   struct wl_fw_status_2 *status)
{
	struct wl1271_link *lnk;
	u32 cur_fw_ps_map;
@@ -379,7 +379,8 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
}

static void wl12xx_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 timespec ts;
@@ -388,37 +389,38 @@ static void wl12xx_fw_status(struct wl1271 *wl,
	int i;
	size_t status_len;

	status_len = sizeof(*status) + wl->fw_status_priv_len;
	status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
		sizeof(*status_2) + wl->fw_status_priv_len;

	wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status,
	wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1,
			     status_len, false);

	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
		     "drv_rx_counter = %d, tx_results_counter = %d)",
		     status->intr,
		     status->fw_rx_counter,
		     status->drv_rx_counter,
		     status->tx_results_counter);
		     status_1->intr,
		     status_1->fw_rx_counter,
		     status_1->drv_rx_counter,
		     status_1->tx_results_counter);

	for (i = 0; i < NUM_TX_QUEUES; i++) {
		/* prevent wrap-around in freed-packets counter */
		wl->tx_allocated_pkts[i] -=
				(status->counters.tx_released_pkts[i] -
				(status_2->counters.tx_released_pkts[i] -
				wl->tx_pkts_freed[i]) & 0xff;

		wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i];
		wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i];
	}

	/* prevent wrap-around in total blocks counter */
	if (likely(wl->tx_blocks_freed <=
		   le32_to_cpu(status->total_released_blks)))
		freed_blocks = le32_to_cpu(status->total_released_blks) -
		   le32_to_cpu(status_2->total_released_blks)))
		freed_blocks = le32_to_cpu(status_2->total_released_blks) -
			       wl->tx_blocks_freed;
	else
		freed_blocks = 0x100000000LL - wl->tx_blocks_freed +
			       le32_to_cpu(status->total_released_blks);
			       le32_to_cpu(status_2->total_released_blks);

	wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks);
	wl->tx_blocks_freed = le32_to_cpu(status_2->total_released_blks);

	wl->tx_allocated_blocks -= freed_blocks;

@@ -434,7 +436,7 @@ static void wl12xx_fw_status(struct wl1271 *wl,
			cancel_delayed_work(&wl->tx_watchdog_work);
	}

	avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks;
	avail = le32_to_cpu(status_2->tx_total) - wl->tx_allocated_blocks;

	/*
	 * The FW might change the total number of TX memblocks before
@@ -453,13 +455,13 @@ static void wl12xx_fw_status(struct wl1271 *wl,

	/* for AP update num of allocated TX blocks per link and ps status */
	wl12xx_for_each_wlvif_ap(wl, wlvif) {
		wl12xx_irq_update_links_status(wl, wlvif, status);
		wl12xx_irq_update_links_status(wl, wlvif, status_2);
	}

	/* update the host-chipset time offset */
	getnstimeofday(&ts);
	wl->time_offset = (timespec_to_ns(&ts) >> 10) -
		(s64)le32_to_cpu(status->fw_localtime);
		(s64)le32_to_cpu(status_2->fw_localtime);
}

static void wl1271_flush_deferred_work(struct wl1271 *wl)
@@ -528,11 +530,11 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
		clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
		smp_mb__after_clear_bit();

		wl12xx_fw_status(wl, wl->fw_status);
		wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2);

		wlcore_hw_tx_immediate_compl(wl);

		intr = le32_to_cpu(wl->fw_status->intr);
		intr = le32_to_cpu(wl->fw_status_1->intr);
		intr &= WL1271_INTR_MASK;
		if (!intr) {
			done = true;
@@ -551,7 +553,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
		if (likely(intr & WL1271_ACX_INTR_DATA)) {
			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");

			wl12xx_rx(wl, wl->fw_status);
			wl12xx_rx(wl, wl->fw_status_1);

			/* Check if any tx blocks were freed */
			spin_lock_irqsave(&wl->wl_lock, flags);
@@ -786,8 +788,8 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
		wl12xx_cmd_stop_fwlog(wl);

	/* Read the first memory block address */
	wl12xx_fw_status(wl, wl->fw_status);
	first_addr = le32_to_cpu(wl->fw_status->log_start_addr);
	wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2);
	first_addr = le32_to_cpu(wl->fw_status_2->log_start_addr);
	if (!first_addr)
		goto out;

@@ -901,13 +903,18 @@ static void wl1271_fw_wakeup(struct wl1271 *wl)

static int wl1271_setup(struct wl1271 *wl)
{
	wl->fw_status = kmalloc(sizeof(*wl->fw_status), GFP_KERNEL);
	if (!wl->fw_status)
	wl->fw_status_1 = kmalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) +
				  sizeof(*wl->fw_status_2), GFP_KERNEL);
	if (!wl->fw_status_1)
		return -ENOMEM;

	wl->fw_status_2 = (struct wl_fw_status_2 *)
				(((u8 *) wl->fw_status_1) +
				WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc));

	wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
	if (!wl->tx_res_if) {
		kfree(wl->fw_status);
		kfree(wl->fw_status_1);
		return -ENOMEM;
	}

@@ -1746,8 +1753,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)

	wl1271_debugfs_reset(wl);

	kfree(wl->fw_status);
	wl->fw_status = NULL;
	kfree(wl->fw_status_1);
	wl->fw_status_1 = NULL;
	wl->fw_status_2 = NULL;
	kfree(wl->tx_res_if);
	wl->tx_res_if = NULL;
	kfree(wl->target_mem_map);
@@ -5181,7 +5189,7 @@ int wlcore_free_hw(struct wl1271 *wl)
	kfree(wl->nvs);
	wl->nvs = NULL;

	kfree(wl->fw_status);
	kfree(wl->fw_status_1);
	kfree(wl->tx_res_if);
	destroy_workqueue(wl->freezable_wq);

+5 −5
Original line number Diff line number Diff line
@@ -200,12 +200,12 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
	return is_data;
}

void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status)
void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
{
	unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
	u32 buf_size;
	u32 fw_rx_counter  = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 fw_rx_counter = status->fw_rx_counter % wl->num_rx_desc;
	u32 drv_rx_counter = wl->rx_counter % wl->num_rx_desc;
	u32 rx_counter;
	u32 pkt_len, align_pkt_len;
	u32 pkt_offset, des;
@@ -224,7 +224,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status)
				break;
			buf_size += align_pkt_len;
			rx_counter++;
			rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
			rx_counter %= wl->num_rx_desc;
		}

		if (buf_size == 0) {
@@ -264,7 +264,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status)

			wl->rx_counter++;
			drv_rx_counter++;
			drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
			drv_rx_counter %= wl->num_rx_desc;
			pkt_offset += wlcore_rx_get_align_buf_size(wl, pkt_len);
		}
	}
Loading