aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorBrian Cavagnolo <brian@cozybit.com>2011-03-17 14:58:45 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-03-30 14:15:13 -0400
commitac109fd0427008e5b55e0e52e59c364de6d686fe (patch)
tree17a2013e1818da02b6cc15aec3b100f1f3fb23cb /drivers/net/wireless/mwl8k.c
parente600707b021efdc109e7becd467798da339ec26d (diff)
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: Pradeep Nemavat <pnemavat@marvell.com> Signed-off-by: Nishant Sarmukadam <nishants@marvell.com> Signed-off-by: Brian Cavagnolo <brian@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 53581ee8b79..dcd4508b1fd 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -137,6 +137,13 @@ struct mwl8k_tx_queue {
137 struct sk_buff **skb; 137 struct sk_buff **skb;
138}; 138};
139 139
140enum {
141 AMPDU_NO_STREAM,
142 AMPDU_STREAM_NEW,
143 AMPDU_STREAM_IN_PROGRESS,
144 AMPDU_STREAM_ACTIVE,
145};
146
140struct mwl8k_ampdu_stream { 147struct mwl8k_ampdu_stream {
141 struct ieee80211_sta *sta; 148 struct ieee80211_sta *sta;
142 u8 tid; 149 u8 tid;
@@ -172,6 +179,8 @@ struct mwl8k_priv {
172 179
173 /* Ampdu stream information */ 180 /* Ampdu stream information */
174 u8 num_ampdu_queues; 181 u8 num_ampdu_queues;
182 spinlock_t stream_lock;
183 struct mwl8k_ampdu_stream ampdu[MWL8K_MAX_AMPDU_QUEUES];
175 184
176 /* firmware access */ 185 /* firmware access */
177 struct mutex fw_mutex; 186 struct mutex fw_mutex;
@@ -1594,6 +1603,74 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
1594 txq->txd = NULL; 1603 txq->txd = NULL;
1595} 1604}
1596 1605
1606/* caller must hold priv->stream_lock when calling the stream functions */
1607struct mwl8k_ampdu_stream *
1608mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid)
1609{
1610 struct mwl8k_ampdu_stream *stream;
1611 struct mwl8k_priv *priv = hw->priv;
1612 int i;
1613
1614 for (i = 0; i < priv->num_ampdu_queues; i++) {
1615 stream = &priv->ampdu[i];
1616 if (stream->state == AMPDU_NO_STREAM) {
1617 stream->sta = sta;
1618 stream->state = AMPDU_STREAM_NEW;
1619 stream->tid = tid;
1620 stream->idx = i;
1621 stream->txq_idx = MWL8K_TX_WMM_QUEUES + i;
1622 wiphy_debug(hw->wiphy, "Added a new stream for %pM %d",
1623 sta->addr, tid);
1624 return stream;
1625 }
1626 }
1627 return NULL;
1628}
1629
1630static int
1631mwl8k_start_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
1632{
1633 int ret;
1634
1635 /* if the stream has already been started, don't start it again */
1636 if (stream->state != AMPDU_STREAM_NEW)
1637 return 0;
1638 ret = ieee80211_start_tx_ba_session(stream->sta, stream->tid, 0);
1639 if (ret)
1640 wiphy_debug(hw->wiphy, "Failed to start stream for %pM %d: "
1641 "%d\n", stream->sta->addr, stream->tid, ret);
1642 else
1643 wiphy_debug(hw->wiphy, "Started stream for %pM %d\n",
1644 stream->sta->addr, stream->tid);
1645 return ret;
1646}
1647
1648static void
1649mwl8k_remove_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
1650{
1651 wiphy_debug(hw->wiphy, "Remove stream for %pM %d\n", stream->sta->addr,
1652 stream->tid);
1653 memset(stream, 0, sizeof(*stream));
1654}
1655
1656static struct mwl8k_ampdu_stream *
1657mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid)
1658{
1659 struct mwl8k_priv *priv = hw->priv;
1660 int i;
1661
1662 for (i = 0 ; i < priv->num_ampdu_queues; i++) {
1663 struct mwl8k_ampdu_stream *stream;
1664 stream = &priv->ampdu[i];
1665 if (stream->state == AMPDU_NO_STREAM)
1666 continue;
1667 if (!memcmp(stream->sta->addr, addr, ETH_ALEN) &&
1668 stream->tid == tid)
1669 return stream;
1670 }
1671 return NULL;
1672}
1673
1597static void 1674static void
1598mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) 1675mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1599{ 1676{
@@ -4854,6 +4931,8 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw)
4854 goto err_free_queues; 4931 goto err_free_queues;
4855 } 4932 }
4856 4933
4934 memset(priv->ampdu, 0, sizeof(priv->ampdu));
4935
4857 /* 4936 /*
4858 * Temporarily enable interrupts. Initial firmware host 4937 * Temporarily enable interrupts. Initial firmware host
4859 * commands use interrupts and avoid polling. Disable 4938 * commands use interrupts and avoid polling. Disable
@@ -5018,6 +5097,8 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
5018 5097
5019 spin_lock_init(&priv->tx_lock); 5098 spin_lock_init(&priv->tx_lock);
5020 5099
5100 spin_lock_init(&priv->stream_lock);
5101
5021 priv->tx_wait = NULL; 5102 priv->tx_wait = NULL;
5022 5103
5023 rc = mwl8k_probe_hw(hw); 5104 rc = mwl8k_probe_hw(hw);