Commit 96c93589 authored by Gidon Studinski's avatar Gidon Studinski Committed by Kalle Valo
Browse files

wil6210: initialize TX and RX enhanced DMA rings



Enhanced DMA design includes the following rings:
- Single RX descriptor ring is used for all VIFs
- Multiple RX status rings are supported, to allow RSS
- TX descriptor ring is allocated per connection
- A single TX status ring is used for all TX descriptor rings

This patch initializes and frees the above descriptor and
status rings.

The RX SKBs are handled by a new entity of RX buffers manager,
which handles RX buffers, each one points to an allocated SKB.
During Rx completion processing, the driver extracts a buffer
ID which is used as an index to the buffers array.
After the SKB is freed the buffer is moved from the 'active'
list to the 'free' list, indicating it can be used for another
descriptor. During Rx refill, SKBs are allocated and attached
to 'free' buffers. Those buffers are attached to new descriptors
and moved to the 'active' list.

New debugfs entries were added to allow edma configuration:

Run the following command to configure the number of status rings:
echo NUM_OF_STATUS_RINGS > num_rx_status_rings

Run the following command to use extended RX status message for
additional debug fields from HW:
echo 0 > compressed_rx_status

Run the following command to control the size of the TX status ring:
echo TX_STATUS_RING_ORDER > tx_status_ring_order
The status ring size will be 1 << tx_status_ring_order

Run the following command to control the size of the RX status ring:
echo RX_STATUS_RING_ORDER > rx_status_ring_order
Due to HW constrains RX sring order should be bigger than RX ring order
The status ring size will be 1 << rx_status_ring_order

Run the following command to change the number of RX buffer IDs:
echo RX_BUFF_ID_COUNT > rx_buff_id_count

Signed-off-by: default avatarGidon Studinski <gidons@codeaurora.org>
Signed-off-by: default avatarMaya Erez <merez@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 10590c6a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ wil6210-$(CONFIG_WIL6210_DEBUGFS) += debugfs.o
wil6210-y += wmi.o
wil6210-y += interrupt.o
wil6210-y += txrx.o
wil6210-y += txrx_edma.o
wil6210-y += debug.o
wil6210-y += rx_reorder.o
wil6210-y += fw.o
+59 −0
Original line number Diff line number Diff line
@@ -1761,6 +1761,60 @@ static const struct file_operations fops_suspend_stats = {
	.open  = simple_open,
};

/*---------compressed_rx_status---------*/
static ssize_t wil_compressed_rx_status_write(struct file *file,
					      const char __user *buf,
					      size_t len, loff_t *ppos)
{
	struct seq_file *s = file->private_data;
	struct wil6210_priv *wil = s->private;
	int compressed_rx_status;
	int rc;

	rc = kstrtoint_from_user(buf, len, 0, &compressed_rx_status);
	if (rc) {
		wil_err(wil, "Invalid argument\n");
		return rc;
	}

	if (wil_has_active_ifaces(wil, true, false)) {
		wil_err(wil, "cannot change edma config after iface is up\n");
		return -EPERM;
	}

	wil_info(wil, "%sable compressed_rx_status\n",
		 compressed_rx_status ? "En" : "Dis");

	wil->use_compressed_rx_status = compressed_rx_status;

	return len;
}

static int
wil_compressed_rx_status_show(struct seq_file *s, void *data)
{
	struct wil6210_priv *wil = s->private;

	seq_printf(s, "%d\n", wil->use_compressed_rx_status);

	return 0;
}

static int
wil_compressed_rx_status_seq_open(struct inode *inode, struct file *file)
{
	return single_open(file, wil_compressed_rx_status_show,
			   inode->i_private);
}

static const struct file_operations fops_compressed_rx_status = {
	.open  = wil_compressed_rx_status_seq_open,
	.release = single_release,
	.read = seq_read,
	.write = wil_compressed_rx_status_write,
	.llseek	= seq_lseek,
};

/*----------------*/
static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
				       struct dentry *dbg)
@@ -1814,6 +1868,7 @@ static const struct {
	{"fw_capabilities",	0444,	&fops_fw_capabilities},
	{"fw_version",	0444,		&fops_fw_version},
	{"suspend_stats",	0644,	&fops_suspend_stats},
	{"compressed_rx_status", 0644,	&fops_compressed_rx_status},
};

static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
@@ -1860,6 +1915,10 @@ static const struct dbg_off dbg_wil_off[] = {
	WIL_FIELD(abft_len, 0644,		doff_u8),
	WIL_FIELD(wakeup_trigger, 0644,		doff_u8),
	WIL_FIELD(ring_idle_trsh, 0644,	doff_u32),
	WIL_FIELD(num_rx_status_rings, 0644,	doff_u8),
	WIL_FIELD(rx_status_ring_order, 0644,	doff_u32),
	WIL_FIELD(tx_status_ring_order, 0644,	doff_u32),
	WIL_FIELD(rx_buff_id_count, 0644,	doff_u32),
	{},
};

+1 −1
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev,
	if (ret < 0)
		return ret;

	wil_configure_interrupt_moderation(wil);
	wil->txrx_ops.configure_interrupt_moderation(wil);

	wil_pm_runtime_put(wil);

+21 −0
Original line number Diff line number Diff line
@@ -186,6 +186,27 @@ void wil_unmask_irq(struct wil6210_priv *wil)
	wil6210_unmask_irq_misc(wil, true);
}

void wil_configure_interrupt_moderation_edma(struct wil6210_priv *wil)
{
	u32 moderation;

	wil_s(wil, RGF_INT_GEN_IDLE_TIME_LIMIT, WIL_EDMA_IDLE_TIME_LIMIT_USEC);

	wil_s(wil, RGF_INT_GEN_TIME_UNIT_LIMIT, WIL_EDMA_TIME_UNIT_CLK_CYCLES);

	/* Update RX and TX moderation */
	moderation = wil->rx_max_burst_duration |
		(WIL_EDMA_AGG_WATERMARK << WIL_EDMA_AGG_WATERMARK_POS);
	wil_w(wil, RGF_INT_CTRL_INT_GEN_CFG_0, moderation);
	wil_w(wil, RGF_INT_CTRL_INT_GEN_CFG_1, moderation);

	/* Treat special events as regular
	 * (set bit 0 to 0x1 and clear bits 1-8)
	 */
	wil_c(wil, RGF_INT_COUNT_ON_SPECIAL_EVT, 0x1FE);
	wil_s(wil, RGF_INT_COUNT_ON_SPECIAL_EVT, 0x1);
}

void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
{
	struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
+73 −8
Original line number Diff line number Diff line
@@ -21,11 +21,13 @@

#include "wil6210.h"
#include "txrx.h"
#include "txrx_edma.h"
#include "wmi.h"
#include "boot_loader.h"

#define WAIT_FOR_HALP_VOTE_MS 100
#define WAIT_FOR_SCAN_ABORT_MS 1000
#define WIL_DEFAULT_NUM_RX_STATUS_RINGS 1

bool debug_fw; /* = false; */
module_param(debug_fw, bool, 0444);
@@ -160,6 +162,37 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
	}
}

static void wil_ring_fini_tx(struct wil6210_priv *wil, int id)
{
	struct wil_ring *ring = &wil->ring_tx[id];
	struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id];

	lockdep_assert_held(&wil->mutex);

	if (!ring->va)
		return;

	wil_dbg_misc(wil, "vring_fini_tx: id=%d\n", id);

	spin_lock_bh(&txdata->lock);
	txdata->dot1x_open = false;
	txdata->mid = U8_MAX;
	txdata->enabled = 0; /* no Tx can be in progress or start anew */
	spin_unlock_bh(&txdata->lock);
	/* napi_synchronize waits for completion of the current NAPI but will
	 * not prevent the next NAPI run.
	 * Add a memory barrier to guarantee that txdata->enabled is zeroed
	 * before napi_synchronize so that the next scheduled NAPI will not
	 * handle this vring
	 */
	wmb();
	/* make sure NAPI won't touch this vring */
	if (test_bit(wil_status_napi_en, wil->status))
		napi_synchronize(&wil->napi_tx);

	wil->txrx_ops.ring_fini_tx(wil, ring);
}

static void wil_disconnect_cid(struct wil6210_vif *vif, int cid,
			       u16 reason_code, bool from_event)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
@@ -456,15 +489,16 @@ static void wil_fw_error_worker(struct work_struct *work)
static int wil_find_free_ring(struct wil6210_priv *wil)
{
	int i;
	int min_ring_id = wil_get_min_tx_ring_id(wil);

	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
	for (i = min_ring_id; i < WIL6210_MAX_TX_RINGS; i++) {
		if (!wil->ring_tx[i].va)
			return i;
	}
	return -EINVAL;
}

int wil_tx_init(struct wil6210_vif *vif, int cid)
int wil_ring_init_tx(struct wil6210_vif *vif, int cid)
{
	struct wil6210_priv *wil = vif_to_wil(vif);
	int rc = -EINVAL, ringid;
@@ -482,7 +516,8 @@ int wil_tx_init(struct wil6210_vif *vif, int cid)
	wil_dbg_wmi(wil, "Configure for connection CID %d MID %d ring %d\n",
		    cid, vif->mid, ringid);

	rc = wil_vring_init_tx(vif, ringid, 1 << tx_ring_order, cid, 0);
	rc = wil->txrx_ops.ring_init_tx(vif, ringid, 1 << tx_ring_order,
					cid, 0);
	if (rc)
		wil_err(wil, "init TX for CID %d MID %d vring %d failed\n",
			cid, vif->mid, ringid);
@@ -504,7 +539,7 @@ int wil_bcast_init(struct wil6210_vif *vif)
		return ri;

	vif->bcast_ring = ri;
	rc = wil_vring_init_bcast(vif, ri, 1 << bcast_ring_order);
	rc = wil->txrx_ops.ring_init_bcast(vif, ri, 1 << bcast_ring_order);
	if (rc)
		vif->bcast_ring = -1;

@@ -594,6 +629,22 @@ int wil_priv_init(struct wil6210_priv *wil)
	wil->reply_mid = U8_MAX;
	wil->max_vifs = 1;

	/* edma configuration can be updated via debugfs before allocation */
	wil->num_rx_status_rings = WIL_DEFAULT_NUM_RX_STATUS_RINGS;
	wil->use_compressed_rx_status = true;
	wil->tx_status_ring_order = WIL_TX_SRING_SIZE_ORDER_DEFAULT;

	/* Rx status ring size should be bigger than the number of RX buffers
	 * in order to prevent backpressure on the status ring, which may
	 * cause HW freeze.
	 */
	wil->rx_status_ring_order = WIL_RX_SRING_SIZE_ORDER_DEFAULT;
	/* Number of RX buffer IDs should be bigger than the RX descriptor
	 * ring size as in HW reorder flow, the HW can consume additional
	 * buffers before releasing the previous ones.
	 */
	wil->rx_buff_id_count = WIL_RX_BUFF_ARR_SIZE_DEFAULT;

	return 0;

out_wmi_wq:
@@ -1312,7 +1363,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
	rc = wil_target_reset(wil, no_flash);
	wil6210_clear_irq(wil);
	wil_enable_irq(wil);
	wil_rx_fini(wil);
	wil->txrx_ops.rx_fini(wil);
	wil->txrx_ops.tx_fini(wil);
	if (rc) {
		if (!no_flash)
			wil_bl_crash_info(wil, true);
@@ -1365,7 +1417,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
	clear_bit(wil_status_resetting, wil->status);

	if (load_fw) {
		wil_configure_interrupt_moderation(wil);
		wil_unmask_irq(wil);

		/* we just started MAC, wait for FW ready */
@@ -1380,6 +1431,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
			return rc;
		}

		wil->txrx_ops.configure_interrupt_moderation(wil);

		rc = wil_restore_vifs(wil);
		if (rc) {
			wil_err(wil, "failed to restore vifs, rc %d\n", rc);
@@ -1434,8 +1487,12 @@ int __wil_up(struct wil6210_priv *wil)
	if (rc)
		return rc;

	/* Rx VRING. After MAC and beacon */
	rc = wil_rx_init(wil, 1 << rx_ring_order);
	/* Rx RING. After MAC and beacon */
	rc = wil->txrx_ops.rx_init(wil, 1 << rx_ring_order);
	if (rc)
		return rc;

	rc = wil->txrx_ops.tx_init(wil);
	if (rc)
		return rc;

@@ -1596,3 +1653,11 @@ void wil_halp_unvote(struct wil6210_priv *wil)

	mutex_unlock(&wil->halp.lock);
}

void wil_init_txrx_ops(struct wil6210_priv *wil)
{
	if (wil->use_enhanced_dma_hw)
		wil_init_txrx_ops_edma(wil);
	else
		wil_init_txrx_ops_legacy_dma(wil);
}
Loading