Commit 7be13fc3 authored by Gidon Studinski's avatar Gidon Studinski Committed by Kalle Valo
Browse files

wil6210: add support for enhanced DMA RX data flows



Enhanced DMA RX data path is handled using a single
RX descriptor ring for all VIFs.
Multiple RX status rings are supported, to allow RSS
and multi MSI support.
The driver gets the RX completions via the RX status rings.
The RX status message includes the completed RX buffer ID,
which points to the allocated SKB.

The enhanced DMA RX data flow supports RX chaining, where
multiple SKBs are merged into a single packet.

Enhanced DMA HW supports RX HW reorder offload, enabled by
default for Talyn-MB.

amsdu_en debugfs entry was added to allow control MSDU aggregation.
Use the following command to disable AMSDU (enabled by default):
echo 0 > amsdu_en

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 9202d7b6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1919,6 +1919,7 @@ static const struct dbg_off dbg_wil_off[] = {
	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),
	WIL_FIELD(amsdu_en, 0644,	doff_u8),
	{},
};

+82 −4
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#define WIL6210_IMC_TX		(BIT_DMA_EP_TX_ICR_TX_DONE | \
				BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
#define WIL6210_IMC_TX_EDMA		BIT_TX_STATUS_IRQ
#define WIL6210_IMC_RX_EDMA		BIT_RX_STATUS_IRQ
#define WIL6210_IMC_MISC_NO_HALP	(ISR_MISC_FW_READY | \
					 ISR_MISC_MBOX_EVT | \
					 ISR_MISC_FW_ERROR)
@@ -100,6 +101,12 @@ static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
	      WIL6210_IRQ_DISABLE);
}

static void wil6210_mask_irq_rx_edma(struct wil6210_priv *wil)
{
	wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMS),
	      WIL6210_IRQ_DISABLE);
}

static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp)
{
	wil_dbg_irq(wil, "mask_irq_misc: mask_halp(%s)\n",
@@ -146,6 +153,12 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
	      unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH);
}

void wil6210_unmask_irq_rx_edma(struct wil6210_priv *wil)
{
	wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMC),
	      WIL6210_IMC_RX_EDMA);
}

static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp)
{
	wil_dbg_irq(wil, "unmask_irq_misc: unmask_halp(%s)\n",
@@ -179,6 +192,7 @@ void wil_mask_irq(struct wil6210_priv *wil)
	wil6210_mask_irq_tx(wil);
	wil6210_mask_irq_tx_edma(wil);
	wil6210_mask_irq_rx(wil);
	wil6210_mask_irq_rx_edma(wil);
	wil6210_mask_irq_misc(wil, true);
	wil6210_mask_irq_pseudo(wil);
}
@@ -195,10 +209,13 @@ void wil_unmask_irq(struct wil6210_priv *wil)
	      WIL_ICR_ICC_MISC_VALUE);
	wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC),
	      WIL_ICR_ICC_VALUE);
	wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, ICC),
	      WIL_ICR_ICC_VALUE);

	wil6210_unmask_irq_pseudo(wil);
	if (wil->use_enhanced_dma_hw) {
		wil6210_unmask_irq_tx_edma(wil);
		wil6210_unmask_irq_rx_edma(wil);
	} else {
		wil6210_unmask_irq_tx(wil);
		wil6210_unmask_irq_rx(wil);
@@ -335,6 +352,54 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
	return IRQ_HANDLED;
}

static irqreturn_t wil6210_irq_rx_edma(int irq, void *cookie)
{
	struct wil6210_priv *wil = cookie;
	u32 isr = wil_ioread32_and_clear(wil->csr +
					 HOSTADDR(RGF_INT_GEN_RX_ICR) +
					 offsetof(struct RGF_ICR, ICR));
	bool need_unmask = true;

	trace_wil6210_irq_rx(isr);
	wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);

	if (unlikely(!isr)) {
		wil_err(wil, "spurious IRQ: RX\n");
		return IRQ_NONE;
	}

	wil6210_mask_irq_rx_edma(wil);

	if (likely(isr & BIT_RX_STATUS_IRQ)) {
		wil_dbg_irq(wil, "RX status ring\n");
		isr &= ~BIT_RX_STATUS_IRQ;
		if (likely(test_bit(wil_status_fwready, wil->status))) {
			if (likely(test_bit(wil_status_napi_en, wil->status))) {
				wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
				need_unmask = false;
				napi_schedule(&wil->napi_rx);
			} else {
				wil_err(wil,
					"Got Rx interrupt while stopping interface\n");
			}
		} else {
			wil_err(wil, "Got Rx interrupt while in reset\n");
		}
	}

	if (unlikely(isr))
		wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr);

	/* Rx IRQ will be enabled when NAPI processing finished */

	atomic_inc(&wil->isr_count_rx);

	if (unlikely(need_unmask))
		wil6210_unmask_irq_rx_edma(wil);

	return IRQ_HANDLED;
}

static irqreturn_t wil6210_irq_tx_edma(int irq, void *cookie)
{
	struct wil6210_priv *wil = cookie;
@@ -594,12 +659,20 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
 */
static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
{
	u32 icm_rx = 0, icr_rx = 0, imv_rx = 0;
	u32 icm_rx, icr_rx, imv_rx;
	u32 icm_tx, icr_tx, imv_tx;
	u32 icm_misc, icr_misc, imv_misc;

	if (!test_bit(wil_status_irqen, wil->status)) {
		if (wil->use_enhanced_dma_hw) {
			icm_rx = wil_ioread32_and_clear(wil->csr +
					HOSTADDR(RGF_INT_GEN_RX_ICR) +
					offsetof(struct RGF_ICR, ICM));
			icr_rx = wil_ioread32_and_clear(wil->csr +
					HOSTADDR(RGF_INT_GEN_RX_ICR) +
					offsetof(struct RGF_ICR, ICR));
			imv_rx = wil_r(wil, RGF_INT_GEN_RX_ICR +
				   offsetof(struct RGF_ICR, IMV));
			icm_tx = wil_ioread32_and_clear(wil->csr +
					HOSTADDR(RGF_INT_GEN_TX_ICR) +
					offsetof(struct RGF_ICR, ICM));
@@ -691,7 +764,7 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
	 * voting for wake thread - need at least 1 vote
	 */
	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) &&
	    (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
	    (wil->txrx_ops.irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
		rc = IRQ_WAKE_THREAD;

	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) &&
@@ -723,6 +796,8 @@ void wil6210_clear_irq(struct wil6210_priv *wil)
		    offsetof(struct RGF_ICR, ICR));
	wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
		    offsetof(struct RGF_ICR, ICR));
	wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) +
		    offsetof(struct RGF_ICR, ICR));
	wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) +
		    offsetof(struct RGF_ICR, ICR));
	wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
@@ -753,10 +828,13 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi)

	wil_dbg_misc(wil, "init_irq: %s\n", use_msi ? "MSI" : "INTx");

	if (wil->use_enhanced_dma_hw)
	if (wil->use_enhanced_dma_hw) {
		wil->txrx_ops.irq_tx = wil6210_irq_tx_edma;
	else
		wil->txrx_ops.irq_rx = wil6210_irq_rx_edma;
	} else {
		wil->txrx_ops.irq_tx = wil6210_irq_tx;
		wil->txrx_ops.irq_rx = wil6210_irq_rx;
	}
	rc = request_threaded_irq(irq, wil6210_hardirq,
				  wil6210_thread_irq,
				  use_msi ? 0 : IRQF_SHARED,
+3 −0
Original line number Diff line number Diff line
@@ -632,6 +632,7 @@ int wil_priv_init(struct wil6210_priv *wil)
	/* 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->use_rx_hw_reordering = 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
@@ -645,6 +646,8 @@ int wil_priv_init(struct wil6210_priv *wil)
	 */
	wil->rx_buff_id_count = WIL_RX_BUFF_ARR_SIZE_DEFAULT;

	wil->amsdu_en = 1;

	return 0;

out_wmi_wq:
+30 −5
Original line number Diff line number Diff line
@@ -120,6 +120,27 @@ static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
	return done;
}

static int wil6210_netdev_poll_rx_edma(struct napi_struct *napi, int budget)
{
	struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
						napi_rx);
	int quota = budget;
	int done;

	wil_rx_handle_edma(wil, &quota);
	done = budget - quota;

	if (done < budget) {
		napi_complete_done(napi, done);
		wil6210_unmask_irq_rx_edma(wil);
		wil_dbg_txrx(wil, "NAPI RX complete\n");
	}

	wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done);

	return done;
}

static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
{
	struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
@@ -442,17 +463,21 @@ int wil_if_add(struct wil6210_priv *wil)
	}

	init_dummy_netdev(&wil->napi_ndev);
	netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx,
	if (wil->use_enhanced_dma_hw) {
		netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
			       wil6210_netdev_poll_rx_edma,
			       WIL6210_NAPI_BUDGET);
	if (wil->use_enhanced_dma_hw)
		netif_tx_napi_add(&wil->napi_ndev,
				  &wil->napi_tx, wil6210_netdev_poll_tx_edma,
				  WIL6210_NAPI_BUDGET);
	else
	} else {
		netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
			       wil6210_netdev_poll_rx,
			       WIL6210_NAPI_BUDGET);
		netif_tx_napi_add(&wil->napi_ndev,
				  &wil->napi_tx, wil6210_netdev_poll_tx,
				  WIL6210_NAPI_BUDGET);

	}

	wil_update_net_queues_bh(wil, vif, NULL, true);

+1 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ int wil_set_capabilities(struct wil6210_priv *wil)
		wil->rgf_ucode_assert_code_addr = TALYN_RGF_UCODE_ASSERT_CODE;
		set_bit(hw_capa_no_flash, wil->hw_capa);
		wil->use_enhanced_dma_hw = true;
		wil->use_rx_hw_reordering = true;
		break;
	default:
		wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n",
Loading