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

Commit 23379477 authored by Dedy Lansky's avatar Dedy Lansky Committed by Gerrit - the friendly Code Review server
Browse files

wil6210: ipa stop/wake queue based on outstanding packets



wil6210 doesn't use stop/wake net queue in IPA mode. This leads into
situations of IPA Tx queue getting full and eventually draining out
all memory.

To fix this, add outstanding Tx packets counter in wil6210 and invoke
stop/wake net queue when this counter reaches high/low watermarks.
IPA_WRITE_DONE is sent from IPA to notify wil6210 when a Tx is
complete, at which point wil6210 decrements outstanding_pkts counter.

Change-Id: Iaef7efeecb8d7a13a453297c08bc43e894bed174
Signed-off-by: default avatarDedy Lansky <dlansky@codeaurora.org>
parent 879f7556
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@
#define WIL_IPA_RX_BUFF_SIZE (8 * 1024)
#define WIL_IPA_TX_BUFF_SIZE (2 * 1024)

#define WIL_IPA_DEFAULT_OUTSTANDING_HIGH 128
#define WIL_IPA_DEFAULT_OUTSTANDING_LOW 64

u8 ipa_offload;
module_param(ipa_offload, byte, 0444);
MODULE_PARM_DESC(ipa_offload, " Enable IPA offload, default - disabled");
@@ -138,13 +141,30 @@ static void wil_ipa_notify_cb(void *priv, enum ipa_dp_evt_type evt,
			      unsigned long data)
{
	struct wil_ipa *ipa = (struct wil_ipa *)priv;
	struct wil6210_priv *wil = ipa->wil;
	struct net_device *ndev = wil->main_ndev;
	struct sk_buff *skb;
	int outs;

	switch (evt) {
	case IPA_RECEIVE:
		skb = (struct sk_buff *)data;
		wil_ipa_rx(ipa, skb);
		break;
	case IPA_WRITE_DONE:
		skb = (struct sk_buff *)data;
		outs = atomic_dec_return(&ipa->outstanding_pkts);
		wil_dbg_txrx(wil, "ipa tx complete len %d, outstanding %d",
			     skb->len, outs);
		if (netif_queue_stopped(ndev) &&
		    outs <= WIL_IPA_DEFAULT_OUTSTANDING_LOW) {
			wil_dbg_txrx(wil, "outstanding low reached (%d)\n",
				     WIL_IPA_DEFAULT_OUTSTANDING_LOW);
			netif_wake_queue(ndev);
		}

		dev_kfree_skb_any(skb);
		break;
	default:
		wil_dbg_misc(ipa->wil, "unhandled ipa evt %d\n", evt);
		break;
@@ -728,6 +748,7 @@ int wil_ipa_tx(void *ipa_handle, struct wil_ring *ring, struct sk_buff *skb)
	int cid, rc;
	const u8 *da;
	unsigned int len = skb->len;
	int outs;

	wil_hex_dump_txrx("Tx ", DUMP_PREFIX_OFFSET, 16, 1,
			  skb->data, skb_headlen(skb), false);
@@ -752,6 +773,14 @@ int wil_ipa_tx(void *ipa_handle, struct wil_ring *ring, struct sk_buff *skb)
		return rc;
	/* skb could be freed after this point */

	outs = atomic_inc_return(&ipa->outstanding_pkts);
	wil_dbg_txrx(wil, "ipa tx outstanding %d", outs);
	if (outs >= WIL_IPA_DEFAULT_OUTSTANDING_HIGH) {
		wil_dbg_txrx(wil, "outstanding high reached (%d)\n",
			     WIL_IPA_DEFAULT_OUTSTANDING_HIGH);
		netif_stop_queue(ndev);
	}

	stats = &wil->sta[cid].stats;
	stats->tx_packets++;
	stats->tx_bytes += len;
@@ -927,6 +956,8 @@ void *wil_ipa_init(struct wil6210_priv *wil)
	if (rc)
		goto err;

	atomic_set(&ipa->outstanding_pkts, 0);

	return ipa;

err:
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ struct wil_ipa {
	struct wil_ipa_conn conn[WIL6210_MAX_CID];
	struct wil_ipa_rx_buf rx_buf; /* contiguous memory split into rx bufs */
	struct msi_msg orig_msi_msg;
	atomic_t outstanding_pkts;
};

static inline bool wil_ipa_offload(void) {return ipa_offload; }