mt76: introduce packet_id idr
Introduce per-wcid idr to manage packet id for txs. This allow fast idr lookup and skb queueing at the same time. Tested-by: mrkiko.rs@gmail.com Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
50ac15a511
commit
bd1e3e7b69
@ -566,6 +566,8 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
|
|||||||
spin_lock_init(&dev->token_lock);
|
spin_lock_init(&dev->token_lock);
|
||||||
idr_init(&dev->token);
|
idr_init(&dev->token);
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&dev->wcid_list);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&dev->txwi_cache);
|
INIT_LIST_HEAD(&dev->txwi_cache);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
|
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
|
||||||
@ -1237,6 +1239,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
|||||||
wcid->ext_phy = ext_phy;
|
wcid->ext_phy = ext_phy;
|
||||||
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
|
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
|
||||||
|
|
||||||
|
mt76_packet_id_init(wcid);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dev->mutex);
|
mutex_unlock(&dev->mutex);
|
||||||
|
|
||||||
@ -1255,7 +1258,8 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
|||||||
if (dev->drv->sta_remove)
|
if (dev->drv->sta_remove)
|
||||||
dev->drv->sta_remove(dev, vif, sta);
|
dev->drv->sta_remove(dev, vif, sta);
|
||||||
|
|
||||||
mt76_tx_status_check(dev, wcid, true);
|
mt76_packet_id_flush(dev, wcid);
|
||||||
|
|
||||||
mt76_wcid_mask_clear(dev->wcid_mask, idx);
|
mt76_wcid_mask_clear(dev->wcid_mask, idx);
|
||||||
mt76_wcid_mask_clear(dev->wcid_phy_mask, idx);
|
mt76_wcid_mask_clear(dev->wcid_phy_mask, idx);
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,8 @@ struct mt76_wcid {
|
|||||||
u32 tx_info;
|
u32 tx_info;
|
||||||
bool sw_iv;
|
bool sw_iv;
|
||||||
|
|
||||||
u8 packet_id;
|
struct list_head list;
|
||||||
|
struct idr pktid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt76_txq {
|
struct mt76_txq {
|
||||||
@ -701,6 +702,7 @@ struct mt76_dev {
|
|||||||
|
|
||||||
struct mt76_wcid global_wcid;
|
struct mt76_wcid global_wcid;
|
||||||
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
|
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
|
||||||
|
struct list_head wcid_list;
|
||||||
|
|
||||||
u32 rev;
|
u32 rev;
|
||||||
|
|
||||||
@ -1311,14 +1313,22 @@ mt76_token_put(struct mt76_dev *dev, int token)
|
|||||||
return txwi;
|
return txwi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline void mt76_packet_id_init(struct mt76_wcid *wcid)
|
||||||
mt76_get_next_pkt_id(struct mt76_wcid *wcid)
|
|
||||||
{
|
{
|
||||||
wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
|
INIT_LIST_HEAD(&wcid->list);
|
||||||
if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
|
idr_init(&wcid->pktid);
|
||||||
wcid->packet_id == MT_PACKET_ID_NO_SKB)
|
|
||||||
wcid->packet_id = MT_PACKET_ID_FIRST;
|
|
||||||
|
|
||||||
return wcid->packet_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
mt76_packet_id_flush(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||||
|
{
|
||||||
|
struct sk_buff_head list;
|
||||||
|
|
||||||
|
mt76_tx_status_lock(dev, &list);
|
||||||
|
mt76_tx_status_skb_get(dev, wcid, -1, &list);
|
||||||
|
mt76_tx_status_unlock(dev, &list);
|
||||||
|
|
||||||
|
idr_destroy(&wcid->pktid);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,6 +69,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||||||
INIT_LIST_HEAD(&mvif->sta.poll_list);
|
INIT_LIST_HEAD(&mvif->sta.poll_list);
|
||||||
mvif->sta.wcid.idx = idx;
|
mvif->sta.wcid.idx = idx;
|
||||||
mvif->sta.wcid.hw_key_idx = -1;
|
mvif->sta.wcid.hw_key_idx = -1;
|
||||||
|
mt76_packet_id_init(&mvif->sta.wcid);
|
||||||
|
|
||||||
eth_broadcast_addr(bc_addr);
|
eth_broadcast_addr(bc_addr);
|
||||||
mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
|
mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
|
||||||
@ -107,6 +108,8 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||||||
mutex_lock(&dev->mt76.mutex);
|
mutex_lock(&dev->mt76.mutex);
|
||||||
dev->mt76.vif_mask &= ~BIT(mvif->idx);
|
dev->mt76.vif_mask &= ~BIT(mvif->idx);
|
||||||
mutex_unlock(&dev->mt76.mutex);
|
mutex_unlock(&dev->mt76.mutex);
|
||||||
|
|
||||||
|
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mt7603_init_edcca(struct mt7603_dev *dev)
|
void mt7603_init_edcca(struct mt7603_dev *dev)
|
||||||
|
@ -231,6 +231,8 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
|
|||||||
mvif->sta.wcid.idx = idx;
|
mvif->sta.wcid.idx = idx;
|
||||||
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
|
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
|
||||||
mvif->sta.wcid.hw_key_idx = -1;
|
mvif->sta.wcid.hw_key_idx = -1;
|
||||||
|
mt76_packet_id_init(&mvif->sta.wcid);
|
||||||
|
|
||||||
mt7615_mac_wtbl_update(dev, idx,
|
mt7615_mac_wtbl_update(dev, idx,
|
||||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||||
|
|
||||||
@ -281,6 +283,8 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
|
|||||||
if (!list_empty(&msta->poll_list))
|
if (!list_empty(&msta->poll_list))
|
||||||
list_del_init(&msta->poll_list);
|
list_del_init(&msta->poll_list);
|
||||||
spin_unlock_bh(&dev->sta_poll_lock);
|
spin_unlock_bh(&dev->sta_poll_lock);
|
||||||
|
|
||||||
|
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mt7615_init_dfs_state(struct mt7615_phy *phy)
|
static void mt7615_init_dfs_state(struct mt7615_phy *phy)
|
||||||
|
@ -287,6 +287,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
|
|||||||
mvif->idx = idx;
|
mvif->idx = idx;
|
||||||
mvif->group_wcid.idx = MT_VIF_WCID(idx);
|
mvif->group_wcid.idx = MT_VIF_WCID(idx);
|
||||||
mvif->group_wcid.hw_key_idx = -1;
|
mvif->group_wcid.hw_key_idx = -1;
|
||||||
|
mt76_packet_id_init(&mvif->group_wcid);
|
||||||
|
|
||||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||||
mtxq->wcid = &mvif->group_wcid;
|
mtxq->wcid = &mvif->group_wcid;
|
||||||
}
|
}
|
||||||
@ -341,6 +343,7 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
|
|||||||
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
|
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
|
||||||
|
|
||||||
dev->mt76.vif_mask &= ~BIT(mvif->idx);
|
dev->mt76.vif_mask &= ~BIT(mvif->idx);
|
||||||
|
mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
|
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
|
||||||
|
|
||||||
|
@ -236,6 +236,8 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
|||||||
mvif->sta.wcid.ext_phy = mvif->band_idx;
|
mvif->sta.wcid.ext_phy = mvif->band_idx;
|
||||||
mvif->sta.wcid.hw_key_idx = -1;
|
mvif->sta.wcid.hw_key_idx = -1;
|
||||||
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||||
|
mt76_packet_id_init(&mvif->sta.wcid);
|
||||||
|
|
||||||
mt7915_mac_wtbl_update(dev, idx,
|
mt7915_mac_wtbl_update(dev, idx,
|
||||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||||
|
|
||||||
@ -290,6 +292,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
|
|||||||
if (!list_empty(&msta->poll_list))
|
if (!list_empty(&msta->poll_list))
|
||||||
list_del_init(&msta->poll_list);
|
list_del_init(&msta->poll_list);
|
||||||
spin_unlock_bh(&dev->sta_poll_lock);
|
spin_unlock_bh(&dev->sta_poll_lock);
|
||||||
|
|
||||||
|
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mt7915_init_dfs_state(struct mt7915_phy *phy)
|
static void mt7915_init_dfs_state(struct mt7915_phy *phy)
|
||||||
|
@ -304,6 +304,8 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
|
|||||||
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
|
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
|
||||||
mvif->sta.wcid.hw_key_idx = -1;
|
mvif->sta.wcid.hw_key_idx = -1;
|
||||||
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||||
|
mt76_packet_id_init(&mvif->sta.wcid);
|
||||||
|
|
||||||
mt7921_mac_wtbl_update(dev, idx,
|
mt7921_mac_wtbl_update(dev, idx,
|
||||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||||
|
|
||||||
@ -350,6 +352,8 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
|
|||||||
if (!list_empty(&msta->poll_list))
|
if (!list_empty(&msta->poll_list))
|
||||||
list_del_init(&msta->poll_list);
|
list_del_init(&msta->poll_list);
|
||||||
spin_unlock_bh(&dev->sta_poll_lock);
|
spin_unlock_bh(&dev->sta_poll_lock);
|
||||||
|
|
||||||
|
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt7921_set_channel(struct mt7921_phy *phy)
|
static int mt7921_set_channel(struct mt7921_phy *phy)
|
||||||
|
@ -92,8 +92,6 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags,
|
|||||||
if ((flags & done) != done)
|
if ((flags & done) != done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
__skb_unlink(skb, &dev->status_list);
|
|
||||||
|
|
||||||
/* Tx status can be unreliable. if it fails, mark the frame as ACKed */
|
/* Tx status can be unreliable. if it fails, mark the frame as ACKed */
|
||||||
if (flags & MT_TX_CB_TXS_FAILED) {
|
if (flags & MT_TX_CB_TXS_FAILED) {
|
||||||
info->status.rates[0].count = 0;
|
info->status.rates[0].count = 0;
|
||||||
@ -120,6 +118,8 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
|||||||
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
|
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
|
memset(cb, 0, sizeof(*cb));
|
||||||
|
|
||||||
if (!wcid)
|
if (!wcid)
|
||||||
return MT_PACKET_ID_NO_ACK;
|
return MT_PACKET_ID_NO_ACK;
|
||||||
|
|
||||||
@ -132,13 +132,21 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
|||||||
|
|
||||||
spin_lock_bh(&dev->status_list.lock);
|
spin_lock_bh(&dev->status_list.lock);
|
||||||
|
|
||||||
memset(cb, 0, sizeof(*cb));
|
pid = idr_alloc(&wcid->pktid, skb, MT_PACKET_ID_FIRST,
|
||||||
pid = mt76_get_next_pkt_id(wcid);
|
MT_PACKET_ID_MASK, GFP_ATOMIC);
|
||||||
|
if (pid < 0) {
|
||||||
|
pid = MT_PACKET_ID_NO_SKB;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
cb->wcid = wcid->idx;
|
cb->wcid = wcid->idx;
|
||||||
cb->pktid = pid;
|
cb->pktid = pid;
|
||||||
cb->jiffies = jiffies;
|
cb->jiffies = jiffies;
|
||||||
|
|
||||||
__skb_queue_tail(&dev->status_list, skb);
|
if (list_empty(&wcid->list))
|
||||||
|
list_add_tail(&wcid->list, &dev->wcid_list);
|
||||||
|
|
||||||
|
out:
|
||||||
spin_unlock_bh(&dev->status_list.lock);
|
spin_unlock_bh(&dev->status_list.lock);
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
@ -149,26 +157,38 @@ struct sk_buff *
|
|||||||
mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid,
|
mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid,
|
||||||
struct sk_buff_head *list)
|
struct sk_buff_head *list)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb, *tmp;
|
struct sk_buff *skb;
|
||||||
|
int id;
|
||||||
|
|
||||||
skb_queue_walk_safe(&dev->status_list, skb, tmp) {
|
lockdep_assert_held(&dev->status_list.lock);
|
||||||
|
|
||||||
|
skb = idr_remove(&wcid->pktid, pktid);
|
||||||
|
if (skb)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* look for stale entries in the wcid idr queue */
|
||||||
|
idr_for_each_entry(&wcid->pktid, skb, id) {
|
||||||
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
|
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
|
||||||
|
|
||||||
if (wcid && cb->wcid != wcid->idx)
|
if (pktid >= 0) {
|
||||||
continue;
|
if (!(cb->flags & MT_TX_CB_DMA_DONE))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (cb->pktid == pktid)
|
if (!time_is_after_jiffies(cb->jiffies +
|
||||||
return skb;
|
MT_TX_STATUS_SKB_TIMEOUT))
|
||||||
|
continue;
|
||||||
if (pktid >= 0 && !time_after(jiffies, cb->jiffies +
|
}
|
||||||
MT_TX_STATUS_SKB_TIMEOUT))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
idr_remove(&wcid->pktid, cb->pktid);
|
||||||
__mt76_tx_status_skb_done(dev, skb, MT_TX_CB_TXS_FAILED |
|
__mt76_tx_status_skb_done(dev, skb, MT_TX_CB_TXS_FAILED |
|
||||||
MT_TX_CB_TXS_DONE, list);
|
MT_TX_CB_TXS_DONE, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
out:
|
||||||
|
if (idr_is_empty(&wcid->pktid))
|
||||||
|
list_del_init(&wcid->list);
|
||||||
|
|
||||||
|
return skb;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mt76_tx_status_skb_get);
|
EXPORT_SYMBOL_GPL(mt76_tx_status_skb_get);
|
||||||
|
|
||||||
@ -176,9 +196,11 @@ void
|
|||||||
mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid, bool flush)
|
mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid, bool flush)
|
||||||
{
|
{
|
||||||
struct sk_buff_head list;
|
struct sk_buff_head list;
|
||||||
|
struct mt76_wcid *tmp;
|
||||||
|
|
||||||
mt76_tx_status_lock(dev, &list);
|
mt76_tx_status_lock(dev, &list);
|
||||||
mt76_tx_status_skb_get(dev, wcid, flush ? -1 : 0, &list);
|
list_for_each_entry_safe(wcid, tmp, &dev->wcid_list, list)
|
||||||
|
mt76_tx_status_skb_get(dev, wcid, flush ? -1 : 0, &list);
|
||||||
mt76_tx_status_unlock(dev, &list);
|
mt76_tx_status_unlock(dev, &list);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mt76_tx_status_check);
|
EXPORT_SYMBOL_GPL(mt76_tx_status_check);
|
||||||
@ -201,6 +223,7 @@ mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
|||||||
void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb,
|
void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb,
|
||||||
struct list_head *free_list)
|
struct list_head *free_list)
|
||||||
{
|
{
|
||||||
|
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
|
||||||
struct ieee80211_tx_status status = {
|
struct ieee80211_tx_status status = {
|
||||||
.skb = skb,
|
.skb = skb,
|
||||||
.free_list = free_list,
|
.free_list = free_list,
|
||||||
@ -230,7 +253,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!skb->prev) {
|
if (cb->pktid < MT_PACKET_ID_FIRST) {
|
||||||
hw = mt76_tx_status_get_hw(dev, skb);
|
hw = mt76_tx_status_get_hw(dev, skb);
|
||||||
status.sta = wcid_to_sta(wcid);
|
status.sta = wcid_to_sta(wcid);
|
||||||
ieee80211_tx_status_ext(hw, &status);
|
ieee80211_tx_status_ext(hw, &status);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user