[PATCH v2] mt76: mt7921: introduce mac tx done handling

Deren Wu deren.wu at mediatek.com
Fri May 28 07:50:53 PDT 2021


Hi all,

The patch was done with v1 already. Please ignore this version.

I will create another patch for coding issue.


Regards,
Deren


On Fri, 2021-05-28 at 22:13 +0800, Deren Wu wrote:
> From: Deren Wu <deren.wu at mediatek.com>
> 
> 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: Deren Wu <deren.wu at mediatek.com>
> ---
> change since v2: fix coding style
> ---
>  .../net/wireless/mediatek/mt76/mt7921/mac.c   | 67 +++++++++++----
> ----
>  .../net/wireless/mediatek/mt76/mt7921/mcu.c   | 47 +++++++++++++
>  .../net/wireless/mediatek/mt76/mt7921/mcu.h   | 28 ++++++++
>  .../wireless/mediatek/mt76/mt7921/mt7921.h    |  2 +
>  4 files changed, 115 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
> b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
> index 212832b34674..ec87097146ee 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
> @@ -13,6 +13,34 @@
>  #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;
> +}
> +
> +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;
> +}
> +
> +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 +754,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 +823,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
> @@ -1380,30 +1417,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;
> @@ -1421,10 +1434,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,
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> index 5a4c695f73c9..e8cd767ea475 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> @@ -531,6 +531,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)
>  {
> @@ -557,6 +600,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;
>  	}
> @@ -577,6 +623,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 ||
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
> b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
> index 49823d0a3d0a..22ebef4add00 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
> @@ -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
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> index 59862ea4951c..a1e4276273d8 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> @@ -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);


More information about the Linux-mediatek mailing list