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

Commit ac109fd0 authored by Brian Cavagnolo's avatar Brian Cavagnolo Committed by John W. Linville
Browse files

mwl8k: add internal API for managing AMPDU streams



In particular, we can now add, start, lookup, and remove streams.

Based on work by Nishant Sarmukadam <nishants@marvell.com> and
Pradeep Nemavat <pnemavat@marvell.com>.

Signed-off-by: default avatarPradeep Nemavat <pnemavat@marvell.com>
Signed-off-by: default avatarNishant Sarmukadam <nishants@marvell.com>
Signed-off-by: default avatarBrian Cavagnolo <brian@cozybit.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e600707b
Loading
Loading
Loading
Loading
+81 −0
Original line number Diff line number Diff line
@@ -137,6 +137,13 @@ struct mwl8k_tx_queue {
	struct sk_buff **skb;
};

enum {
	AMPDU_NO_STREAM,
	AMPDU_STREAM_NEW,
	AMPDU_STREAM_IN_PROGRESS,
	AMPDU_STREAM_ACTIVE,
};

struct mwl8k_ampdu_stream {
	struct ieee80211_sta *sta;
	u8 tid;
@@ -172,6 +179,8 @@ struct mwl8k_priv {

	/* Ampdu stream information */
	u8 num_ampdu_queues;
	spinlock_t stream_lock;
	struct mwl8k_ampdu_stream ampdu[MWL8K_MAX_AMPDU_QUEUES];

	/* firmware access */
	struct mutex fw_mutex;
@@ -1594,6 +1603,74 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
	txq->txd = NULL;
}

/* caller must hold priv->stream_lock when calling the stream functions */
struct mwl8k_ampdu_stream *
mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid)
{
	struct mwl8k_ampdu_stream *stream;
	struct mwl8k_priv *priv = hw->priv;
	int i;

	for (i = 0; i < priv->num_ampdu_queues; i++) {
		stream = &priv->ampdu[i];
		if (stream->state == AMPDU_NO_STREAM) {
			stream->sta = sta;
			stream->state = AMPDU_STREAM_NEW;
			stream->tid = tid;
			stream->idx = i;
			stream->txq_idx = MWL8K_TX_WMM_QUEUES + i;
			wiphy_debug(hw->wiphy, "Added a new stream for %pM %d",
				    sta->addr, tid);
			return stream;
		}
	}
	return NULL;
}

static int
mwl8k_start_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
{
	int ret;

	/* if the stream has already been started, don't start it again */
	if (stream->state != AMPDU_STREAM_NEW)
		return 0;
	ret = ieee80211_start_tx_ba_session(stream->sta, stream->tid, 0);
	if (ret)
		wiphy_debug(hw->wiphy, "Failed to start stream for %pM %d: "
			    "%d\n", stream->sta->addr, stream->tid, ret);
	else
		wiphy_debug(hw->wiphy, "Started stream for %pM %d\n",
			    stream->sta->addr, stream->tid);
	return ret;
}

static void
mwl8k_remove_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
{
	wiphy_debug(hw->wiphy, "Remove stream for %pM %d\n", stream->sta->addr,
		    stream->tid);
	memset(stream, 0, sizeof(*stream));
}

static struct mwl8k_ampdu_stream *
mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid)
{
	struct mwl8k_priv *priv = hw->priv;
	int i;

	for (i = 0 ; i < priv->num_ampdu_queues; i++) {
		struct mwl8k_ampdu_stream *stream;
		stream = &priv->ampdu[i];
		if (stream->state == AMPDU_NO_STREAM)
			continue;
		if (!memcmp(stream->sta->addr, addr, ETH_ALEN) &&
		    stream->tid == tid)
			return stream;
	}
	return NULL;
}

static void
mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
{
@@ -4854,6 +4931,8 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw)
		goto err_free_queues;
	}

	memset(priv->ampdu, 0, sizeof(priv->ampdu));

	/*
	 * Temporarily enable interrupts.  Initial firmware host
	 * commands use interrupts and avoid polling.  Disable
@@ -5018,6 +5097,8 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)

	spin_lock_init(&priv->tx_lock);

	spin_lock_init(&priv->stream_lock);

	priv->tx_wait = NULL;

	rc = mwl8k_probe_hw(hw);