Commit 3cce2b98 authored by Deren Wu's avatar Deren Wu Committed by Felix Fietkau

mt76: mt7921: introduce mac tx done handling

Instead of read tx status from mac table, add new mechanisam to hanele
tx done event for data frame, every 250ms

This event indicate the real tx status of this pkt in mac layer and
would help mac80211 correct status more frequently
Signed-off-by: default avatarDeren Wu <deren.wu@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 3253f8fd
......@@ -13,6 +13,36 @@
#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
IEEE80211_RADIOTAP_HE_##f)
static u8
mt7921_next_pid(struct mt7921_dev *dev, struct mt76_wcid *wcid)
{
wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
wcid->packet_id == MT_PACKET_ID_NO_SKB)
wcid->packet_id = MT_PACKET_ID_FIRST;
return wcid->packet_id;
}
static unsigned long
mt7921_next_txs_set(struct mt7921_dev *dev, struct mt76_wcid *wcid,
u32 timeout)
{
struct mt7921_sta *msta;
msta = container_of(wcid, struct mt7921_sta, wcid);
msta->next_txs_ts = jiffies + msecs_to_jiffies(timeout);
return msta->next_txs_ts;
}
static bool
mt7921_next_txs_timeout(struct mt7921_dev *dev, struct mt76_wcid *wcid)
{
struct mt7921_sta *msta;
msta = container_of(wcid, struct mt7921_sta, wcid);
return time_is_before_jiffies(msta->next_txs_ts);
}
static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev,
u16 idx, bool unicast)
{
......@@ -726,7 +756,7 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
struct mt76_phy *mphy = &dev->mphy;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
u8 pid, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
u16 tx_count = 15;
u32 val;
......@@ -795,6 +825,15 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
txwi[6] |= cpu_to_le32(val);
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
}
if ((FIELD_GET(MT_TXD2_FRAME_TYPE, txwi[2]) &
(IEEE80211_FTYPE_DATA >> 2)) &&
mt7921_next_txs_timeout(dev, wcid)) {
mt7921_next_txs_set(dev, wcid, 250);
pid = mt7921_next_pid(dev, wcid);
val = MT_TXD5_TX_STATUS_MCU | FIELD_PREP(MT_TXD5_PID, pid);
txwi[5] |= cpu_to_le32(val);
}
}
static void
......@@ -1392,30 +1431,6 @@ mt7921_mac_update_mib_stats(struct mt7921_phy *phy)
}
}
static void
mt7921_mac_sta_stats_work(struct mt7921_phy *phy)
{
struct mt7921_dev *dev = phy->dev;
struct mt7921_sta *msta;
LIST_HEAD(list);
spin_lock_bh(&dev->sta_poll_lock);
list_splice_init(&phy->stats_list, &list);
while (!list_empty(&list)) {
msta = list_first_entry(&list, struct mt7921_sta, stats_list);
list_del_init(&msta->stats_list);
spin_unlock_bh(&dev->sta_poll_lock);
/* query wtbl info to report tx rate for further devices */
mt7921_get_wtbl_info(dev, msta->wcid.idx);
spin_lock_bh(&dev->sta_poll_lock);
}
spin_unlock_bh(&dev->sta_poll_lock);
}
void mt7921_mac_work(struct work_struct *work)
{
struct mt7921_phy *phy;
......@@ -1433,10 +1448,6 @@ void mt7921_mac_work(struct work_struct *work)
mt7921_mac_update_mib_stats(phy);
}
if (++phy->sta_work_count == 4) {
phy->sta_work_count = 0;
mt7921_mac_sta_stats_work(phy);
}
mt7921_mutex_release(phy->dev);
ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work,
......
......@@ -534,6 +534,49 @@ mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb)
trace_lp_event(dev, event->state);
}
static void
mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb)
{
struct mt7921_mcu_tx_done_event *event;
struct mt7921_sta *msta;
struct mt7921_phy *mphy = &dev->phy;
struct mt7921_mcu_peer_cap peer;
struct ieee80211_sta *sta;
LIST_HEAD(list);
skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
event = (struct mt7921_mcu_tx_done_event *)skb->data;
spin_lock_bh(&dev->sta_poll_lock);
list_splice_init(&mphy->stats_list, &list);
while (!list_empty(&list)) {
msta = list_first_entry(&list, struct mt7921_sta, stats_list);
list_del_init(&msta->stats_list);
if (msta->wcid.idx != event->wlan_idx)
continue;
spin_unlock_bh(&dev->sta_poll_lock);
sta = wcid_to_sta(&msta->wcid);
/* peer config based on IEEE SPEC */
memset(&peer, 0x0, sizeof(peer));
peer.bw = event->bw;
peer.g2 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
peer.g4 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
peer.g8 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
peer.g16 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160);
mt7921_mcu_tx_rate_parse(mphy->mt76, &peer,
&msta->stats.tx_rate, event->tx_rate);
spin_lock_bh(&dev->sta_poll_lock);
break;
}
spin_unlock_bh(&dev->sta_poll_lock);
}
static void
mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
{
......@@ -560,6 +603,9 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
case MCU_EVENT_LP_INFO:
mt7921_mcu_low_power_event(dev, skb);
break;
case MCU_EVENT_TX_DONE:
mt7921_mcu_tx_done_event(dev, skb);
break;
default:
break;
}
......@@ -580,6 +626,7 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||
rxd->eid == MCU_EVENT_BSS_ABSENCE ||
rxd->eid == MCU_EVENT_SCAN_DONE ||
rxd->eid == MCU_EVENT_TX_DONE ||
rxd->eid == MCU_EVENT_DBG_MSG ||
rxd->eid == MCU_EVENT_COREDUMP ||
rxd->eid == MCU_EVENT_LP_INFO ||
......
......@@ -81,6 +81,7 @@ enum {
MCU_EVENT_REG_ACCESS = 0x05,
MCU_EVENT_LP_INFO = 0x07,
MCU_EVENT_SCAN_DONE = 0x0d,
MCU_EVENT_TX_DONE = 0x0f,
MCU_EVENT_BSS_ABSENCE = 0x11,
MCU_EVENT_BSS_BEACON_LOSS = 0x13,
MCU_EVENT_CH_PRIVILEGE = 0x18,
......@@ -407,4 +408,31 @@ struct mt7921_txpwr_event {
struct mt7921_txpwr txpwr;
} __packed;
struct mt7921_mcu_tx_done_event {
u8 pid;
u8 status;
u16 seq;
u8 wlan_idx;
u8 tx_cnt;
u16 tx_rate;
u8 flag;
u8 tid;
u8 rsp_rate;
u8 mcs;
u8 bw;
u8 tx_pwr;
u8 reason;
u8 rsv0[1];
u32 delay;
u32 timestamp;
u32 applied_flag;
u8 txs[28];
u8 rsv1[32];
} __packed;
#endif
......@@ -92,6 +92,8 @@ struct mt7921_sta {
unsigned long ampdu_state;
struct mt7921_sta_key_conf bip;
unsigned long next_txs_ts;
};
DECLARE_EWMA(rssi, 10, 8);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment