From 3a3a799042165a09da73436aba8ab100b0b24d37 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 21 Jan 2018 10:34:42 +0100 Subject: [PATCH] mt76: get station pointer by wcid and pass it to mac80211 Avoids the rhashtable lookup based on the MAC address inside mac80211 Signed-off-by: Felix Fietkau --- dma.c | 4 ++++ mac80211.c | 9 ++++++--- mt76.h | 14 ++++++++++++++ mt7603_mac.c | 13 +++++++++++++ mt7603_main.c | 1 + mt76x2_mac.c | 13 +++++++++++++ mt76x2_main.c | 1 + 7 files changed, 52 insertions(+), 3 deletions(-) diff --git a/dma.c b/dma.c index e539b383..fd8bea14 100644 --- a/dma.c +++ b/dma.c @@ -392,12 +392,16 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget) dev = container_of(napi->dev, struct mt76_dev, napi_dev); qid = napi - dev->napi; + rcu_read_lock(); + do { cur = mt76_dma_rx_process(dev, &dev->q_rx[qid], budget - done); mt76_rx_complete(dev, qid); done += cur; } while (cur && done < budget); + rcu_read_unlock(); + if (done < budget) { napi_complete(napi); dev->drv->rx_poll_complete(dev, qid); diff --git a/mac80211.c b/mac80211.c index 9b512277..dc41aa94 100644 --- a/mac80211.c +++ b/mac80211.c @@ -384,7 +384,7 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, } EXPORT_SYMBOL_GPL(mt76_get_survey); -static void +static struct ieee80211_sta * mt76_rx_convert(struct sk_buff *skb) { struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); @@ -406,14 +406,17 @@ mt76_rx_convert(struct sk_buff *skb) BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb)); BUILD_BUG_ON(sizeof(status->chain_signal) != sizeof(mstat.chain_signal)); memcpy(status->chain_signal, mstat.chain_signal, sizeof(mstat.chain_signal)); + + return wcid_to_sta(mstat.wcid); } void mt76_rx_complete(struct mt76_dev *dev, enum mt76_rxq_id q) { + struct ieee80211_sta *sta; struct sk_buff *skb; while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) { - mt76_rx_convert(skb); - ieee80211_rx_napi(dev->hw, NULL, skb, &dev->napi[q]); + sta = mt76_rx_convert(skb); + ieee80211_rx_napi(dev->hw, sta, skb, &dev->napi[q]); } } diff --git a/mt76.h b/mt76.h index 5362aa90..9938dfce 100644 --- a/mt76.h +++ b/mt76.h @@ -125,6 +125,8 @@ struct mt76_wcid { u8 idx; u8 hw_key_idx; + u8 sta:1; + __le16 tx_rate; bool tx_rate_set; u8 tx_rate_nss; @@ -251,6 +253,7 @@ struct mt76_rate_power { }; struct mt76_rx_status { + struct mt76_wcid *wcid; u64 flag; u16 freq; u8 vht_flag; @@ -343,6 +346,17 @@ mtxq_to_txq(struct mt76_txq *mtxq) return container_of(ptr, struct ieee80211_txq, drv_priv); } +static inline struct ieee80211_sta * +wcid_to_sta(struct mt76_wcid *wcid) +{ + void *ptr = wcid; + + if (!wcid || !wcid->sta) + return NULL; + + return container_of(ptr, struct ieee80211_sta, drv_priv); +} + int mt76_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta); diff --git a/mt7603_mac.c b/mt7603_mac.c index 2f86639b..8311edf1 100644 --- a/mt7603_mac.c +++ b/mt7603_mac.c @@ -350,6 +350,15 @@ mt7603_get_rate(struct mt7603_dev *dev, struct ieee80211_supported_band *sband, return 0; } +static struct mt76_wcid * +mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx) +{ + if (idx >= ARRAY_SIZE(dev->wcid)) + return NULL; + + return rcu_dereference(dev->wcid[idx]); +} + int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) { @@ -360,6 +369,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); bool remove_pad; + int idx; int i; memset(status, 0, sizeof(*status)); @@ -368,6 +378,9 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) sband = (i & 1) ? &dev->mt76.sband_5g.sband : &dev->mt76.sband_2g.sband; i >>= 1; + idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); + status->wcid = mt7603_rx_get_wcid(dev, idx); + status->band = sband->band; if (i < sband->n_channels) status->freq = sband->channels[i].center_freq; diff --git a/mt7603_main.c b/mt7603_main.c index c83efd1b..21a25467 100644 --- a/mt7603_main.c +++ b/mt7603_main.c @@ -282,6 +282,7 @@ mt7603_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, for (i = 0; i < ARRAY_SIZE(sta->txq); i++) mt7603_txq_init(dev, sta->txq[i]); + msta->wcid.sta = 1; msta->wcid.idx = idx; mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr); mt7603_wtbl_update_cap(dev, sta); diff --git a/mt76x2_mac.c b/mt76x2_mac.c index be5ac8d6..cd660079 100644 --- a/mt76x2_mac.c +++ b/mt76x2_mac.c @@ -278,6 +278,15 @@ static void mt76x2_remove_hdr_pad(struct sk_buff *skb) skb_pull(skb, 2); } +static struct mt76_wcid * +mt76x2_rx_get_wcid(struct mt76x2_dev *dev, u8 idx) +{ + if (idx >= ARRAY_SIZE(dev->wcid)) + return NULL; + + return rcu_dereference(dev->wcid[idx]); +} + int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, void *rxi) { @@ -285,8 +294,12 @@ int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, struct mt76x2_rxwi *rxwi = rxi; u32 ctl = le32_to_cpu(rxwi->ctl); u16 rate = le16_to_cpu(rxwi->rate); + u8 wcid; int len; + wcid = FIELD_GET(MT_RXWI_CTL_WCID, ctl); + status->wcid = mt76x2_rx_get_wcid(dev, wcid); + if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) mt76x2_remove_hdr_pad(skb); diff --git a/mt76x2_main.c b/mt76x2_main.c index aa5fbb64..2a1cb65c 100644 --- a/mt76x2_main.c +++ b/mt76x2_main.c @@ -273,6 +273,7 @@ mt76x2_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, goto out; } + msta->wcid.sta = 1; msta->wcid.idx = idx; msta->wcid.hw_key_idx = -1; mt76x2_mac_wcid_setup(dev, idx, mvif->idx, sta->addr);