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

Commit ba429541 authored by Dedy Lansky's avatar Dedy Lansky Committed by Alexei Avshalom Lazar
Browse files

wil6210: support multiple desc and status rings handling



Support multiple status rings:
- Move Tx status ring initialization code to separate function
- Add status ring id argument to relevant functions instead of
  relaying on wil->tx_sring_idx
- Store allocated Rx status ring id in wil->rx_sring_idx and use it
  instead of hard coded WIL_DEFAULT_RX_STATUS_RING_ID
- Configure interrupt moderation for multiple rings
- Allow allocation of descriptor ring without ctx array
- Set irq_mode upon Tx ring allocation

Enhance wil_wmi_cfg_def_rx_offload to enable/disable checksum offload.

Change-Id: If7d346dec2c1ba35cf377235d4c520eca11be166
Signed-off-by: default avatarDedy Lansky <dlansky@codeaurora.org>
Signed-off-by: default avatarAlexei Avshalom Lazar <ailizaro@codeaurora.org>
parent b5e9995c
Loading
Loading
Loading
Loading
+5 −15
Original line number Diff line number Diff line
// SPDX-License-Identifier: ISC
/*
 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <linux/interrupt.h>
@@ -44,7 +33,7 @@
				    (~(BIT_DMA_EP_RX_ICR_RX_HTRSH)))
#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_TX_EDMA		(0xFFFFFFFFUL)
#define WIL6210_IMC_RX_EDMA		BIT_RX_STATUS_IRQ
#define WIL6210_IMC_MISC_NO_HALP	(ISR_MISC_FW_READY | \
					 ISR_MISC_MBOX_EVT | \
@@ -226,6 +215,7 @@ void wil_unmask_irq(struct wil6210_priv *wil)
void wil_configure_interrupt_moderation_edma(struct wil6210_priv *wil)
{
	u32 moderation;
	int i, num_int_lines = 2 /* Rx + Tx status */;

	wil_s(wil, RGF_INT_GEN_IDLE_TIME_LIMIT, WIL_EDMA_IDLE_TIME_LIMIT_USEC);

@@ -234,8 +224,8 @@ void wil_configure_interrupt_moderation_edma(struct wil6210_priv *wil)
	/* 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);
	for (i = 0; i < num_int_lines; i++)
		wil_w(wil, i * 4 + RGF_INT_CTRL_INT_GEN_CFG, moderation);

	/* Treat special events as regular
	 * (set bit 0 to 0x1 and clear bits 1-8)
+10 −2
Original line number Diff line number Diff line
@@ -178,10 +178,18 @@ static int wil6210_netdev_poll_tx_edma(struct napi_struct *napi, int budget)
						napi_tx);
	int tx_done;
	/* There is only one status TX ring */
	struct wil_status_ring *sring = &wil->srings[wil->tx_sring_idx];
	struct wil_status_ring *sring;

	if (!sring->va)
	if (wil->tx_sring_idx >= WIL6210_MAX_STATUS_RINGS) {
		napi_complete(napi);
		return 0;
	}

	sring = &wil->srings[wil->tx_sring_idx];
	if (!sring->va) {
		napi_complete(napi);
		return 0;
	}

	tx_done = wil_tx_sring_handler(wil, sring);

+0 −6
Original line number Diff line number Diff line
@@ -1636,12 +1636,6 @@ static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
	return v;
}

static inline
void wil_tx_desc_set_nr_frags(struct vring_tx_desc *d, int nr_frags)
{
	d->mac.d[2] |= (nr_frags << MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
}

/**
 * Sets the descriptor @d up for csum and/or TSO offloading. The corresponding
 * @skb is used to obtain the protocol and headers length.
+7 −12
Original line number Diff line number Diff line
/* SPDX-License-Identifier: ISC */
/*
 * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef WIL6210_TXRX_H
@@ -685,6 +674,12 @@ static inline void wil_skb_set_cid(struct sk_buff *skb, u8 cid)
	skb_rx_info->rx_info.cid = cid;
}

static inline
void wil_tx_desc_set_nr_frags(struct vring_tx_desc *d, int nr_frags)
{
	d->mac.d[2] |= (nr_frags << MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
}

void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev);
void wil_netif_rx(struct sk_buff *skb, struct net_device *ndev, int cid,
		  struct wil_net_stats *stats, bool gro);
+69 −40
Original line number Diff line number Diff line
@@ -103,50 +103,61 @@ static int wil_sring_alloc(struct wil6210_priv *wil,
	return 0;
}

static int wil_tx_init_edma(struct wil6210_priv *wil)
static int wil_init_tx_sring(struct wil6210_priv *wil, u16 status_ring_size,
			     size_t elem_size, u16 sring_id)
{
	int ring_id = wil_find_free_sring(wil);
	struct wil_status_ring *sring;
	struct wil_status_ring *sring = &wil->srings[sring_id];
	int rc;
	u16 status_ring_size;

	if (wil->tx_status_ring_order < WIL_SRING_SIZE_ORDER_MIN ||
	    wil->tx_status_ring_order > WIL_SRING_SIZE_ORDER_MAX)
		wil->tx_status_ring_order = WIL_TX_SRING_SIZE_ORDER_DEFAULT;
	u8 irq_mode = WMI_RING_ADD_IRQ_MODE_ENABLE;

	status_ring_size = 1 << wil->tx_status_ring_order;

	wil_dbg_misc(wil, "init TX sring: size=%u, ring_id=%u\n",
		     status_ring_size, ring_id);

	if (ring_id < 0)
		return ring_id;

	/* Allocate Tx status ring. Tx descriptor rings will be
	 * allocated on WMI connect event
	 */
	sring = &wil->srings[ring_id];
	wil_dbg_misc(wil, "init TX sring: size=%u, sring_id=%u\n",
		     status_ring_size, sring_id);

	sring->is_rx = false;
	sring->size = status_ring_size;
	sring->elem_size = sizeof(struct wil_ring_tx_status);
	sring->elem_size = elem_size;
	rc = wil_sring_alloc(wil, sring);
	if (rc)
		return rc;

	rc = wil_wmi_tx_sring_cfg(wil, ring_id);
	rc = wil_wmi_tx_sring_cfg(wil, sring_id, irq_mode);
	if (rc)
		goto out_free;

	sring->desc_rdy_pol = 1;
	wil->tx_sring_idx = ring_id;

	return 0;

out_free:
	wil_sring_free(wil, sring);
	return rc;
}

static int wil_tx_init_edma(struct wil6210_priv *wil)
{
	int sring_id = wil_find_free_sring(wil), rc;
	u16 sring_size;

	if (sring_id < 0)
		return sring_id;

	if (wil->tx_status_ring_order < WIL_SRING_SIZE_ORDER_MIN ||
	    wil->tx_status_ring_order > WIL_SRING_SIZE_ORDER_MAX)
		wil->tx_status_ring_order = WIL_TX_SRING_SIZE_ORDER_DEFAULT;

	sring_size = 1 << wil->tx_status_ring_order;

	/* Allocate Tx status ring. Tx descriptor rings will be
	 * allocated on WMI connect event
	 */
	rc = wil_init_tx_sring(wil, sring_size,
			       sizeof(struct wil_ring_tx_status), sring_id);
	if (!rc)
		wil->tx_sring_idx = sring_id;

	return rc;
}

/**
 * Allocate one skb for Rx descriptor RING
 */
@@ -374,7 +385,8 @@ static int wil_init_rx_sring(struct wil6210_priv *wil,
}

static int wil_ring_alloc_desc_ring(struct wil6210_priv *wil,
				    struct wil_ring *ring)
				    struct wil_ring *ring,
				    bool alloc_ctx)
{
	struct device *dev = wil_to_dev(wil);
	size_t sz = ring->size * sizeof(ring->va[0]);
@@ -385,9 +397,15 @@ static int wil_ring_alloc_desc_ring(struct wil6210_priv *wil,

	ring->swhead = 0;
	ring->swtail = 0;
	ring->ctx = kcalloc(ring->size, sizeof(ring->ctx[0]), GFP_KERNEL);

	if (alloc_ctx) {
		ring->ctx = kcalloc(ring->size, sizeof(ring->ctx[0]),
				    GFP_KERNEL);
		if (!ring->ctx)
			goto err;
	} else {
		ring->ctx = NULL;
	}

	ring->va = dma_alloc_coherent(dev, sz, &ring->pa, GFP_KERNEL);
	if (!ring->va)
@@ -490,7 +508,7 @@ static int wil_init_rx_desc_ring(struct wil6210_priv *wil, u16 desc_ring_size,

	ring->size = desc_ring_size;
	ring->is_rx = true;
	rc = wil_ring_alloc_desc_ring(wil, ring);
	rc = wil_ring_alloc_desc_ring(wil, ring, true);
	if (rc)
		return rc;

@@ -642,7 +660,7 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order)
	wil_dbg_misc(wil, "rx_init: allocate %d status rings\n",
		     wil->num_rx_status_rings);

	rc = wil_wmi_cfg_def_rx_offload(wil, wil->rx_buf_len);
	rc = wil_wmi_cfg_def_rx_offload(wil, wil->rx_buf_len, true);
	if (rc)
		return rc;

@@ -658,11 +676,13 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order)
				       sring_id);
		if (rc)
			goto err_free_status;

		if (i == 0)
			wil->rx_sring_idx = sring_id;
	}

	/* Allocate descriptor ring */
	rc = wil_init_rx_desc_ring(wil, desc_ring_size,
				   WIL_DEFAULT_RX_STATUS_RING_ID);
	rc = wil_init_rx_desc_ring(wil, desc_ring_size, wil->rx_sring_idx);
	if (rc)
		goto err_free_status;

@@ -703,6 +723,7 @@ static int wil_ring_init_tx_edma(struct wil6210_vif *vif, int ring_id,
	int rc;
	struct wil_ring *ring = &wil->ring_tx[ring_id];
	struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id];
	u8 irq_mode = WMI_RING_ADD_IRQ_MODE_DISABLE;

	lockdep_assert_held(&wil->mutex);

@@ -712,7 +733,7 @@ static int wil_ring_init_tx_edma(struct wil6210_vif *vif, int ring_id,

	wil_tx_data_init(txdata);
	ring->size = size;
	rc = wil_ring_alloc_desc_ring(wil, ring);
	rc = wil_ring_alloc_desc_ring(wil, ring, true);
	if (rc)
		goto out;

@@ -721,7 +742,8 @@ static int wil_ring_init_tx_edma(struct wil6210_vif *vif, int ring_id,
	if (!vif->privacy)
		txdata->dot1x_open = true;

	rc = wil_wmi_tx_desc_ring_add(vif, ring_id, cid, tid);
	rc = wil_wmi_tx_desc_ring_add(vif, ring_id, cid, tid, wil->tx_sring_idx,
				      irq_mode);
	if (rc) {
		wil_err(wil, "WMI_TX_DESC_RING_ADD_CMD failed\n");
		goto out_free;
@@ -1540,18 +1562,18 @@ static int wil_ring_init_bcast_edma(struct wil6210_vif *vif, int ring_id,
{
	struct wil6210_priv *wil = vif_to_wil(vif);
	struct wil_ring *ring = &wil->ring_tx[ring_id];
	int rc;
	int rc, sring_id = wil->tx_sring_idx;
	struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id];

	wil_dbg_misc(wil, "init bcast: ring_id=%d, sring_id=%d\n",
		     ring_id, wil->tx_sring_idx);
		     ring_id, sring_id);

	lockdep_assert_held(&wil->mutex);

	wil_tx_data_init(txdata);
	ring->size = size;
	ring->is_rx = false;
	rc = wil_ring_alloc_desc_ring(wil, ring);
	rc = wil_ring_alloc_desc_ring(wil, ring, true);
	if (rc)
		goto out;

@@ -1560,7 +1582,7 @@ static int wil_ring_init_bcast_edma(struct wil6210_vif *vif, int ring_id,
	if (!vif->privacy)
		txdata->dot1x_open = true;

	rc = wil_wmi_bcast_desc_ring_add(vif, ring_id);
	rc = wil_wmi_bcast_desc_ring_add(vif, ring_id, sring_id);
	if (rc)
		goto out_free;

@@ -1579,12 +1601,19 @@ static int wil_ring_init_bcast_edma(struct wil6210_vif *vif, int ring_id,

static void wil_tx_fini_edma(struct wil6210_priv *wil)
{
	struct wil_status_ring *sring = &wil->srings[wil->tx_sring_idx];
	int i;

	wil_dbg_misc(wil, "free TX sring\n");
	for (i = 0; i < WIL6210_MAX_STATUS_RINGS; i++) {
		struct wil_status_ring *sring = &wil->srings[i];

		if (!sring->va || sring->is_rx)
			continue;

		wil_dbg_misc(wil, "free TX sring %d\n", i);

		wil_sring_free(wil, sring);
	}
}

static void wil_rx_data_free(struct wil_status_ring *sring)
{
Loading