diff options
76 files changed, 3449 insertions, 2156 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index 52f583cb1418..d4a6b8108971 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -30,8 +30,8 @@ int mt76_queues_read(struct seq_file *s, void *data)  	struct mt76_dev *dev = dev_get_drvdata(s->private);  	int i; -	for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) { -		struct mt76_queue *q = dev->q_tx[i]; +	for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) { +		struct mt76_queue *q = dev->phy.q_tx[i];  		if (!q)  			continue; diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 214fc95b8a33..73eeb00d5aa6 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -72,9 +72,11 @@ mt76_free_pending_txwi(struct mt76_dev *dev)  {  	struct mt76_txwi_cache *t; +	local_bh_disable();  	while ((t = __mt76_get_txwi(dev)) != NULL)  		dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size,  				 DMA_TO_DEVICE); +	local_bh_enable();  }  static int @@ -86,6 +88,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,  	int i;  	spin_lock_init(&q->lock); +	spin_lock_init(&q->cleanup_lock);  	q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE;  	q->ndesc = n_desc; @@ -215,16 +218,15 @@ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)  }  static void -mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) +mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)  { -	struct mt76_queue *q = dev->q_tx[qid];  	struct mt76_queue_entry entry; -	bool wake = false;  	int last;  	if (!q)  		return; +	spin_lock_bh(&q->cleanup_lock);  	if (flush)  		last = -1;  	else @@ -237,13 +239,13 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)  		if (entry.txwi) {  			if (!(dev->drv->drv_flags & MT_DRV_TXWI_NO_FREE))  				mt76_put_txwi(dev, entry.txwi); -			wake = !flush;  		}  		if (!flush && q->tail == last)  			last = readl(&q->regs->dma_idx);  	} +	spin_unlock_bh(&q->cleanup_lock);  	if (flush) {  		spin_lock_bh(&q->lock); @@ -252,16 +254,8 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush)  		spin_unlock_bh(&q->lock);  	} -	wake = wake && q->stopped && -	       qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; -	if (wake) -		q->stopped = false; -  	if (!q->queued)  		wake_up(&dev->tx_wait); - -	if (wake) -		ieee80211_wake_queue(dev->hw, qid);  }  static void * @@ -312,10 +306,9 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,  }  static int -mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,  			  struct sk_buff *skb, u32 tx_info)  { -	struct mt76_queue *q = dev->q_tx[qid];  	struct mt76_queue_buf buf;  	dma_addr_t addr; @@ -343,11 +336,10 @@ error:  }  static int -mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,  		      struct sk_buff *skb, struct mt76_wcid *wcid,  		      struct ieee80211_sta *sta)  { -	struct mt76_queue *q = dev->q_tx[qid];  	struct mt76_tx_info tx_info = {  		.skb = skb,  	}; @@ -397,7 +389,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,  	dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size,  				DMA_TO_DEVICE); -	ret = dev->drv->tx_prepare_skb(dev, txwi, qid, wcid, sta, &tx_info); +	ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info);  	dma_sync_single_for_device(dev->dev, t->dma_addr, dev->drv->txwi_size,  				   DMA_TO_DEVICE);  	if (ret < 0) @@ -661,8 +653,15 @@ void mt76_dma_cleanup(struct mt76_dev *dev)  	mt76_worker_disable(&dev->tx_worker);  	netif_napi_del(&dev->tx_napi); -	for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) -		mt76_dma_tx_cleanup(dev, i, true); + +	for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) { +		mt76_dma_tx_cleanup(dev, dev->phy.q_tx[i], true); +		if (dev->phy2) +			mt76_dma_tx_cleanup(dev, dev->phy2->q_tx[i], true); +	} + +	for (i = 0; i < ARRAY_SIZE(dev->q_mcu); i++) +		mt76_dma_tx_cleanup(dev, dev->q_mcu[i], true);  	mt76_for_each_q_rx(dev, i) {  		netif_napi_del(&dev->napi[i]); diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 3044e0069991..90278aeb6721 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -88,8 +88,10 @@ out_put_node:  }  void -mt76_eeprom_override(struct mt76_dev *dev) +mt76_eeprom_override(struct mt76_phy *phy)  { +	struct mt76_dev *dev = phy->dev; +  #ifdef CONFIG_OF  	struct device_node *np = dev->dev->of_node;  	const u8 *mac = NULL; @@ -97,14 +99,14 @@ mt76_eeprom_override(struct mt76_dev *dev)  	if (np)  		mac = of_get_mac_address(np);  	if (!IS_ERR_OR_NULL(mac)) -		ether_addr_copy(dev->macaddr, mac); +		ether_addr_copy(phy->macaddr, mac);  #endif -	if (!is_valid_ether_addr(dev->macaddr)) { -		eth_random_addr(dev->macaddr); +	if (!is_valid_ether_addr(phy->macaddr)) { +		eth_random_addr(phy->macaddr);  		dev_info(dev->dev,  			 "Invalid MAC address, using random address %pM\n", -			 dev->macaddr); +			 phy->macaddr);  	}  }  EXPORT_SYMBOL_GPL(mt76_eeprom_override); diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 4befe7f937a9..a840396f2c74 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -159,21 +159,22 @@ static void mt76_init_stream_cap(struct mt76_phy *phy,  void mt76_set_stream_caps(struct mt76_phy *phy, bool vht)  { -	if (phy->dev->cap.has_2ghz) +	if (phy->cap.has_2ghz)  		mt76_init_stream_cap(phy, &phy->sband_2g.sband, false); -	if (phy->dev->cap.has_5ghz) +	if (phy->cap.has_5ghz)  		mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht);  }  EXPORT_SYMBOL_GPL(mt76_set_stream_caps);  static int -mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, +mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband,  		const struct ieee80211_channel *chan, int n_chan,  		struct ieee80211_rate *rates, int n_rates, bool vht)  {  	struct ieee80211_supported_band *sband = &msband->sband; -	struct ieee80211_sta_ht_cap *ht_cap;  	struct ieee80211_sta_vht_cap *vht_cap; +	struct ieee80211_sta_ht_cap *ht_cap; +	struct mt76_dev *dev = phy->dev;  	void *chanlist;  	int size; @@ -203,7 +204,7 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband,  	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;  	ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; -	mt76_init_stream_cap(&dev->phy, sband, vht); +	mt76_init_stream_cap(phy, sband, vht);  	if (!vht)  		return 0; @@ -221,27 +222,25 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband,  }  static int -mt76_init_sband_2g(struct mt76_dev *dev, struct ieee80211_rate *rates, +mt76_init_sband_2g(struct mt76_phy *phy, struct ieee80211_rate *rates,  		   int n_rates)  { -	dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->phy.sband_2g.sband; +	phy->hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; -	return mt76_init_sband(dev, &dev->phy.sband_2g, -			       mt76_channels_2ghz, -			       ARRAY_SIZE(mt76_channels_2ghz), -			       rates, n_rates, false); +	return mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz, +			       ARRAY_SIZE(mt76_channels_2ghz), rates, +			       n_rates, false);  }  static int -mt76_init_sband_5g(struct mt76_dev *dev, struct ieee80211_rate *rates, +mt76_init_sband_5g(struct mt76_phy *phy, struct ieee80211_rate *rates,  		   int n_rates, bool vht)  { -	dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->phy.sband_5g.sband; +	phy->hw->wiphy->bands[NL80211_BAND_5GHZ] = &phy->sband_5g.sband; -	return mt76_init_sband(dev, &dev->phy.sband_5g, -			       mt76_channels_5ghz, -			       ARRAY_SIZE(mt76_channels_5ghz), -			       rates, n_rates, vht); +	return mt76_init_sband(phy, &phy->sband_5g, mt76_channels_5ghz, +			       ARRAY_SIZE(mt76_channels_5ghz), rates, +			       n_rates, vht);  }  static void @@ -274,12 +273,13 @@ mt76_check_sband(struct mt76_phy *phy, struct mt76_sband *msband,  }  static void -mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) +mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)  { +	struct mt76_dev *dev = phy->dev;  	struct wiphy *wiphy = hw->wiphy;  	SET_IEEE80211_DEV(hw, dev->dev); -	SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); +	SET_IEEE80211_PERM_ADDR(hw, phy->macaddr);  	wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;  	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH | @@ -305,6 +305,7 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw)  	ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);  	ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);  	ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); +	ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);  	if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) {  		ieee80211_hw_set(hw, TX_AMSDU); @@ -314,7 +315,6 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw)  	ieee80211_hw_set(hw, MFP_CAPABLE);  	ieee80211_hw_set(hw, AP_LINK_PS);  	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); -	ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);  	wiphy->flags |= WIPHY_FLAG_IBSS_RSN;  	wiphy->interface_modes = @@ -333,65 +333,57 @@ mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,  	       const struct ieee80211_ops *ops)  {  	struct ieee80211_hw *hw; +	unsigned int phy_size;  	struct mt76_phy *phy; -	unsigned int phy_size, chan_size; -	unsigned int size_2g, size_5g; -	void *priv;  	phy_size = ALIGN(sizeof(*phy), 8); -	chan_size = sizeof(dev->phy.sband_2g.chan[0]); -	size_2g = ALIGN(ARRAY_SIZE(mt76_channels_2ghz) * chan_size, 8); -	size_5g = ALIGN(ARRAY_SIZE(mt76_channels_5ghz) * chan_size, 8); - -	size += phy_size + size_2g + size_5g; -	hw = ieee80211_alloc_hw(size, ops); +	hw = ieee80211_alloc_hw(size + phy_size, ops);  	if (!hw)  		return NULL;  	phy = hw->priv;  	phy->dev = dev;  	phy->hw = hw; +	phy->priv = hw->priv + phy_size; -	mt76_phy_init(dev, hw); - -	priv = hw->priv + phy_size; +	return phy; +} +EXPORT_SYMBOL_GPL(mt76_alloc_phy); -	phy->sband_2g = dev->phy.sband_2g; -	phy->sband_2g.chan = priv; -	priv += size_2g; +int mt76_register_phy(struct mt76_phy *phy, bool vht, +		      struct ieee80211_rate *rates, int n_rates) +{ +	int ret; -	phy->sband_5g = dev->phy.sband_5g; -	phy->sband_5g.chan = priv; -	priv += size_5g; +	mt76_phy_init(phy, phy->hw); -	phy->priv = priv; +	if (phy->cap.has_2ghz) { +		ret = mt76_init_sband_2g(phy, rates, n_rates); +		if (ret) +			return ret; +	} -	hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; -	hw->wiphy->bands[NL80211_BAND_5GHZ] = &phy->sband_5g.sband; +	if (phy->cap.has_5ghz) { +		ret = mt76_init_sband_5g(phy, rates + 4, n_rates - 4, vht); +		if (ret) +			return ret; +	} +	wiphy_read_of_freq_limits(phy->hw->wiphy);  	mt76_check_sband(phy, &phy->sband_2g, NL80211_BAND_2GHZ);  	mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ); -	return phy; -} -EXPORT_SYMBOL_GPL(mt76_alloc_phy); - -int -mt76_register_phy(struct mt76_phy *phy) -{ -	int ret; -  	ret = ieee80211_register_hw(phy->hw);  	if (ret)  		return ret;  	phy->dev->phy2 = phy; +  	return 0;  }  EXPORT_SYMBOL_GPL(mt76_register_phy); -void -mt76_unregister_phy(struct mt76_phy *phy) +void mt76_unregister_phy(struct mt76_phy *phy)  {  	struct mt76_dev *dev = phy->dev; @@ -459,16 +451,16 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,  	int ret;  	dev_set_drvdata(dev->dev, dev); -	mt76_phy_init(dev, hw); +	mt76_phy_init(phy, hw); -	if (dev->cap.has_2ghz) { -		ret = mt76_init_sband_2g(dev, rates, n_rates); +	if (phy->cap.has_2ghz) { +		ret = mt76_init_sband_2g(phy, rates, n_rates);  		if (ret)  			return ret;  	} -	if (dev->cap.has_5ghz) { -		ret = mt76_init_sband_5g(dev, rates + 4, n_rates - 4, vht); +	if (phy->cap.has_5ghz) { +		ret = mt76_init_sband_5g(phy, rates + 4, n_rates - 4, vht);  		if (ret)  			return ret;  	} @@ -539,14 +531,11 @@ EXPORT_SYMBOL_GPL(mt76_rx);  bool mt76_has_tx_pending(struct mt76_phy *phy)  { -	struct mt76_dev *dev = phy->dev;  	struct mt76_queue *q; -	int i, offset; - -	offset = __MT_TXQ_MAX * (phy != &dev->phy); +	int i;  	for (i = 0; i < __MT_TXQ_MAX; i++) { -		q = dev->q_tx[offset + i]; +		q = phy->q_tx[i];  		if (q && q->queued)  			return true;  	} @@ -842,7 +831,7 @@ mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb)  		return;  	if (!wcid || !wcid->sta) { -		if (!ether_addr_equal(hdr->addr1, dev->macaddr)) +		if (!ether_addr_equal(hdr->addr1, dev->phy.macaddr))  			return;  		wcid = NULL; @@ -932,7 +921,8 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,  {  	struct ieee80211_sta *sta;  	struct ieee80211_hw *hw; -	struct sk_buff *skb; +	struct sk_buff *skb, *tmp; +	LIST_HEAD(list);  	spin_lock(&dev->rx_lock);  	while ((skb = __skb_dequeue(frames)) != NULL) { @@ -942,9 +932,19 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,  		}  		mt76_rx_convert(dev, skb, &hw, &sta); -		ieee80211_rx_napi(hw, sta, skb, napi); +		ieee80211_rx_list(hw, sta, skb, &list);  	}  	spin_unlock(&dev->rx_lock); + +	if (!napi) { +		netif_receive_skb_list(&list); +		return; +	} + +	list_for_each_entry_safe(skb, tmp, &list, list) { +		skb_list_del_init(skb); +		napi_gro_receive(napi, skb); +	}  }  void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q, @@ -1202,3 +1202,22 @@ int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)  	return 0;  }  EXPORT_SYMBOL_GPL(mt76_get_antenna); + +struct mt76_queue * +mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, +		int ring_base) +{ +	struct mt76_queue *hwq; +	int err; + +	hwq = devm_kzalloc(dev->dev, sizeof(*hwq), GFP_KERNEL); +	if (!hwq) +		return ERR_PTR(-ENOMEM); + +	err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base); +	if (err < 0) +		return ERR_PTR(err); + +	return hwq; +} +EXPORT_SYMBOL_GPL(mt76_init_queue); diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index ade61a5334c6..d3a5e2c4f12a 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -50,3 +50,83 @@ void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb)  	wake_up(&dev->mcu.wait);  }  EXPORT_SYMBOL_GPL(mt76_mcu_rx_event); + +int mt76_mcu_send_and_get_msg(struct mt76_dev *dev, int cmd, const void *data, +			      int len, bool wait_resp, struct sk_buff **ret_skb) +{ +	struct sk_buff *skb; + +	if (dev->mcu_ops->mcu_send_msg) +		return dev->mcu_ops->mcu_send_msg(dev, cmd, data, len, wait_resp); + +	skb = mt76_mcu_msg_alloc(dev, data, len); +	if (!skb) +		return -ENOMEM; + +	return mt76_mcu_skb_send_and_get_msg(dev, skb, cmd, wait_resp, ret_skb); +} +EXPORT_SYMBOL_GPL(mt76_mcu_send_and_get_msg); + +int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, +				  int cmd, bool wait_resp, +				  struct sk_buff **ret_skb) +{ +	unsigned long expires; +	int ret, seq; + +	if (ret_skb) +		*ret_skb = NULL; + +	mutex_lock(&dev->mcu.mutex); + +	ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq); +	if (ret < 0) +		goto out; + +	if (!wait_resp) { +		ret = 0; +		goto out; +	} + +	expires = jiffies + dev->mcu.timeout; + +	do { +		skb = mt76_mcu_get_response(dev, expires); +		ret = dev->mcu_ops->mcu_parse_response(dev, cmd, skb, seq); +		if (!ret && ret_skb) +			*ret_skb = skb; +		else +			dev_kfree_skb(skb); +	} while (ret == -EAGAIN); + +out: +	mutex_unlock(&dev->mcu.mutex); + +	return ret; +} +EXPORT_SYMBOL_GPL(mt76_mcu_skb_send_and_get_msg); + +int mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data, +			   int len) +{ +	int err, cur_len; + +	while (len > 0) { +		cur_len = min_t(int, 4096 - dev->mcu_ops->headroom, len); + +		err = mt76_mcu_send_msg(dev, cmd, data, cur_len, false); +		if (err) +			return err; + +		data += cur_len; +		len -= cur_len; + +		if (dev->queue_ops->tx_cleanup) +			dev->queue_ops->tx_cleanup(dev, +						   dev->q_mcu[MT_MCUQ_FWDL], +						   false); +	} + +	return 0; +} +EXPORT_SYMBOL_GPL(mt76_mcu_send_firmware); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index a5be66de1cff..3e496a188bf0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -64,18 +64,23 @@ enum mt76_txq_id {  	MT_TXQ_BE = IEEE80211_AC_BE,  	MT_TXQ_BK = IEEE80211_AC_BK,  	MT_TXQ_PSD, -	MT_TXQ_MCU, -	MT_TXQ_MCU_WA,  	MT_TXQ_BEACON,  	MT_TXQ_CAB, -	MT_TXQ_FWDL,  	__MT_TXQ_MAX  }; +enum mt76_mcuq_id { +	MT_MCUQ_WM, +	MT_MCUQ_WA, +	MT_MCUQ_FWDL, +	__MT_MCUQ_MAX +}; +  enum mt76_rxq_id {  	MT_RXQ_MAIN,  	MT_RXQ_MCU,  	MT_RXQ_MCU_WA, +	MT_RXQ_EXT,  	__MT_RXQ_MAX  }; @@ -121,6 +126,7 @@ struct mt76_queue {  	struct mt76_queue_regs __iomem *regs;  	spinlock_t lock; +	spinlock_t cleanup_lock;  	struct mt76_queue_entry *entry;  	struct mt76_desc *desc; @@ -131,9 +137,11 @@ struct mt76_queue {  	int queued;  	int buf_size;  	bool stopped; +	bool blocked;  	u8 buf_offset;  	u8 hw_idx; +	u8 qid;  	dma_addr_t desc_dma;  	struct sk_buff *rx_head; @@ -147,7 +155,9 @@ struct mt76_mcu_ops {  	int (*mcu_send_msg)(struct mt76_dev *dev, int cmd, const void *data,  			    int len, bool wait_resp);  	int (*mcu_skb_send_msg)(struct mt76_dev *dev, struct sk_buff *skb, -				int cmd, bool wait_resp); +				int cmd, int *seq); +	int (*mcu_parse_response)(struct mt76_dev *dev, int cmd, +				  struct sk_buff *skb, int seq);  	u32 (*mcu_rr)(struct mt76_dev *dev, u32 offset);  	void (*mcu_wr)(struct mt76_dev *dev, u32 offset, u32 val);  	int (*mcu_wr_rp)(struct mt76_dev *dev, u32 base, @@ -164,11 +174,11 @@ struct mt76_queue_ops {  		     int idx, int n_desc, int bufsize,  		     u32 ring_base); -	int (*tx_queue_skb)(struct mt76_dev *dev, enum mt76_txq_id qid, +	int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q,  			    struct sk_buff *skb, struct mt76_wcid *wcid,  			    struct ieee80211_sta *sta); -	int (*tx_queue_skb_raw)(struct mt76_dev *dev, enum mt76_txq_id qid, +	int (*tx_queue_skb_raw)(struct mt76_dev *dev, struct mt76_queue *q,  				struct sk_buff *skb, u32 tx_info);  	void *(*dequeue)(struct mt76_dev *dev, struct mt76_queue *q, bool flush, @@ -176,7 +186,7 @@ struct mt76_queue_ops {  	void (*rx_reset)(struct mt76_dev *dev, enum mt76_rxq_id qid); -	void (*tx_cleanup)(struct mt76_dev *dev, enum mt76_txq_id qid, +	void (*tx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q,  			   bool flush);  	void (*kick)(struct mt76_dev *dev, struct mt76_queue *q); @@ -185,6 +195,7 @@ struct mt76_queue_ops {  enum mt76_wcid_flags {  	MT_WCID_FLAG_CHECK_PS,  	MT_WCID_FLAG_PS, +	MT_WCID_FLAG_4ADDR,  };  #define MT76_N_WCIDS 288 @@ -411,6 +422,7 @@ enum mt76u_out_ep {  struct mt76_mcu {  	struct mutex mutex;  	u32 msg_seq; +	int timeout;  	struct sk_buff_head res_q;  	wait_queue_head_t wait; @@ -426,7 +438,9 @@ struct mt76_usb {  	u8 *data;  	u16 data_len; -	struct tasklet_struct rx_tasklet; +	struct mt76_worker status_worker; +	struct mt76_worker rx_worker; +  	struct work_struct stat_work;  	u8 out_ep[__MT_EP_OUT_MAX]; @@ -445,25 +459,18 @@ struct mt76_usb {  #define MT76S_XMIT_BUF_SZ	(16 * PAGE_SIZE)  struct mt76_sdio { -	struct workqueue_struct *txrx_wq; -	struct { -		struct work_struct xmit_work; -		struct work_struct status_work; -	} tx; -	struct { -		struct work_struct recv_work; -		struct work_struct net_work; -	} rx; +	struct mt76_worker txrx_worker; +	struct mt76_worker status_worker; +	struct mt76_worker net_worker;  	struct work_struct stat_work; -	u8 *xmit_buf[MT_TXQ_MCU_WA]; +	u8 *xmit_buf[IEEE80211_NUM_ACS + 2];  	struct sdio_func *func;  	void *intr_data;  	struct { -		struct mutex lock;  		int pse_data_quota;  		int ple_data_quota;  		int pse_mcu_quota; @@ -528,6 +535,8 @@ struct mt76_testmode_data {  	u8 tx_rate_nss;  	u8 tx_rate_sgi;  	u8 tx_rate_ldpc; +	u8 tx_rate_stbc; +	u8 tx_ltf;  	u8 tx_antenna_mask; @@ -555,15 +564,20 @@ struct mt76_phy {  	unsigned long state; +	struct mt76_queue *q_tx[__MT_TXQ_MAX]; +  	struct cfg80211_chan_def chandef;  	struct ieee80211_channel *main_chan;  	struct mt76_channel_state *chan_state;  	ktime_t survey_time; +	struct mt76_hw_cap cap;  	struct mt76_sband sband_2g;  	struct mt76_sband sband_5g; +	u8 macaddr[ETH_ALEN]; +  	u32 vif_mask;  	int txpower_cur; @@ -601,7 +615,7 @@ struct mt76_dev {  	struct sk_buff_head rx_skb[__MT_RXQ_MAX];  	struct list_head txwi_cache; -	struct mt76_queue *q_tx[2 * __MT_TXQ_MAX]; +	struct mt76_queue *q_mcu[__MT_MCUQ_MAX];  	struct mt76_queue q_rx[__MT_RXQ_MAX];  	const struct mt76_queue_ops *queue_ops;  	int tx_dma_idx[4]; @@ -619,7 +633,6 @@ struct mt76_dev {  	struct mt76_wcid global_wcid;  	struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; -	u8 macaddr[ETH_ALEN];  	u32 rev;  	u32 aggr_stats[32]; @@ -630,7 +643,6 @@ struct mt76_dev {  	struct debugfs_blob_wrapper eeprom;  	struct debugfs_blob_wrapper otp; -	struct mt76_hw_cap cap;  	struct mt76_rate_power rate_power; @@ -690,10 +702,7 @@ enum mt76_phy_type {  #define mt76_wr_rp(dev, ...)	(dev)->mt76.bus->wr_rp(&((dev)->mt76), __VA_ARGS__)  #define mt76_rd_rp(dev, ...)	(dev)->mt76.bus->rd_rp(&((dev)->mt76), __VA_ARGS__) -#define mt76_mcu_send_msg(dev, ...)	(dev)->mt76.mcu_ops->mcu_send_msg(&((dev)->mt76), __VA_ARGS__) -#define __mt76_mcu_send_msg(dev, ...)	(dev)->mcu_ops->mcu_send_msg((dev), __VA_ARGS__) -#define __mt76_mcu_skb_send_msg(dev, ...)	(dev)->mcu_ops->mcu_skb_send_msg((dev), __VA_ARGS__)  #define mt76_mcu_restart(dev, ...)	(dev)->mt76.mcu_ops->mcu_restart(&((dev)->mt76))  #define __mt76_mcu_restart(dev, ...)	(dev)->mcu_ops->mcu_restart((dev)) @@ -752,7 +761,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev)  #define mt76_tx_queue_skb_raw(dev, ...)	(dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__)  #define mt76_tx_queue_skb(dev, ...)	(dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__)  #define mt76_queue_rx_reset(dev, ...)	(dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) -#define mt76_queue_tx_cleanup(dev, ...)	(dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) +#define mt76_queue_tx_cleanup(dev, ...)        (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)  #define mt76_queue_kick(dev, ...)	(dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)  #define mt76_for_each_q_rx(dev, i)	\ @@ -770,7 +779,8 @@ void mt76_unregister_phy(struct mt76_phy *phy);  struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,  				const struct ieee80211_ops *ops); -int mt76_register_phy(struct mt76_phy *phy); +int mt76_register_phy(struct mt76_phy *phy, bool vht, +		      struct ieee80211_rate *rates, int n_rates);  struct dentry *mt76_register_debugfs(struct mt76_dev *dev);  int mt76_queues_read(struct seq_file *s, void *data); @@ -778,7 +788,40 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,  			 s8 *val, int len);  int mt76_eeprom_init(struct mt76_dev *dev, int len); -void mt76_eeprom_override(struct mt76_dev *dev); +void mt76_eeprom_override(struct mt76_phy *phy); + +struct mt76_queue * +mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, +		int ring_base); +static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx, +				     int n_desc, int ring_base) +{ +	struct mt76_queue *q; + +	q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base); +	if (IS_ERR(q)) +		return PTR_ERR(q); + +	q->qid = qid; +	phy->q_tx[qid] = q; + +	return 0; +} + +static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx, +				      int n_desc, int ring_base) +{ +	struct mt76_queue *q; + +	q = mt76_init_queue(dev, qid, idx, n_desc, ring_base); +	if (IS_ERR(q)) +		return PTR_ERR(q); + +	q->qid = __MT_TXQ_MAX + qid; +	dev->q_mcu[qid] = q; + +	return 0; +}  static inline struct mt76_phy *  mt76_dev_phy(struct mt76_dev *dev, bool phy_ext) @@ -901,7 +944,7 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb);  void mt76_tx(struct mt76_phy *dev, struct ieee80211_sta *sta,  	     struct mt76_wcid *wcid, struct sk_buff *skb);  void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq); -void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, +void mt76_stop_tx_queues(struct mt76_phy *phy, struct ieee80211_sta *sta,  			 bool send_bar);  void mt76_tx_check_agg_ssn(struct ieee80211_sta *sta, struct sk_buff *skb);  void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid); @@ -1064,7 +1107,6 @@ void mt76u_queues_deinit(struct mt76_dev *dev);  int mt76s_init(struct mt76_dev *dev, struct sdio_func *func,  	       const struct mt76_bus_ops *bus_ops);  int mt76s_alloc_queues(struct mt76_dev *dev); -void mt76s_stop_txrx(struct mt76_dev *dev);  void mt76s_deinit(struct mt76_dev *dev);  struct sk_buff * @@ -1073,6 +1115,25 @@ mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,  void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb);  struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,  				      unsigned long expires); +int mt76_mcu_send_and_get_msg(struct mt76_dev *dev, int cmd, const void *data, +			      int len, bool wait_resp, struct sk_buff **ret); +int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb, +				  int cmd, bool wait_resp, struct sk_buff **ret); +int mt76_mcu_send_firmware(struct mt76_dev *dev, int cmd, const void *data, +			   int len); +static inline int +mt76_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, int len, +		  bool wait_resp) +{ +	return mt76_mcu_send_and_get_msg(dev, cmd, data, len, wait_resp, NULL); +} + +static inline int +mt76_mcu_skb_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd, +		      bool wait_resp) +{ +	return mt76_mcu_skb_send_and_get_msg(dev, skb, cmd, wait_resp, NULL); +}  void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index d728c5e43783..5d4522f440b7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -13,23 +13,25 @@ static void  mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)  {  	struct mt7603_dev *dev = (struct mt7603_dev *)priv; +	struct mt76_dev *mdev = &dev->mt76;  	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;  	struct sk_buff *skb = NULL; -	if (!(dev->mt76.beacon_mask & BIT(mvif->idx))) +	if (!(mdev->beacon_mask & BIT(mvif->idx)))  		return;  	skb = ieee80211_beacon_get(mt76_hw(dev), vif);  	if (!skb)  		return; -	mt76_tx_queue_skb(dev, MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL); +	mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON], skb, +			  &mvif->sta.wcid, NULL);  	spin_lock_bh(&dev->ps_lock);  	mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |  		FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) |  		FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, -			   dev->mt76.q_tx[MT_TXQ_CAB]->hw_idx) | +			   dev->mphy.q_tx[MT_TXQ_CAB]->hw_idx) |  		FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |  		FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8)); @@ -64,9 +66,10 @@ mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)  	data->count[mvif->idx]++;  } -void mt7603_pre_tbtt_tasklet(unsigned long arg) +void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)  { -	struct mt7603_dev *dev = (struct mt7603_dev *)arg; +	struct mt7603_dev *dev = from_tasklet(dev, t, mt76.pre_tbtt_tasklet); +	struct mt76_dev *mdev = &dev->mt76;  	struct mt76_queue *q;  	struct beacon_bc_data data = {};  	struct sk_buff *skb; @@ -78,7 +81,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)  	data.dev = dev;  	__skb_queue_head_init(&data.q); -	q = dev->mt76.q_tx[MT_TXQ_BEACON]; +	q = dev->mphy.q_tx[MT_TXQ_BEACON];  	spin_lock_bh(&q->lock);  	ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),  		IEEE80211_IFACE_ITER_RESUME_ALL, @@ -89,13 +92,13 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)  	/* Flush all previous CAB queue packets */  	mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0)); -	mt76_queue_tx_cleanup(dev, MT_TXQ_CAB, false); +	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false); -	mt76_csa_check(&dev->mt76); -	if (dev->mt76.csa_complete) +	mt76_csa_check(mdev); +	if (mdev->csa_complete)  		goto out; -	q = dev->mt76.q_tx[MT_TXQ_CAB]; +	q = dev->mphy.q_tx[MT_TXQ_CAB];  	do {  		nframes = skb_queue_len(&data.q);  		ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), @@ -120,7 +123,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)  		struct ieee80211_vif *vif = info->control.vif;  		struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; -		mt76_tx_queue_skb(dev, MT_TXQ_CAB, skb, &mvif->sta.wcid, NULL); +		mt76_tx_queue_skb(dev, q, skb, &mvif->sta.wcid, NULL);  	}  	mt76_queue_kick(dev, q);  	spin_unlock_bh(&q->lock); @@ -135,9 +138,8 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)  		 ((1 << (MT7603_MAX_INTERFACES - 1)) - 1)));  out: -	mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false); -	if (dev->mt76.q_tx[MT_TXQ_BEACON]->queued > -	    hweight8(dev->mt76.beacon_mask)) +	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false); +	if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > hweight8(mdev->beacon_mask))  		dev->beacon_check++;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index d60d00f6f6a0..0086f18cb79a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -4,27 +4,6 @@  #include "mac.h"  #include "../dma.h" -static int -mt7603_init_tx_queue(struct mt7603_dev *dev, int qid, int idx, int n_desc) -{ -	struct mt76_queue *hwq; -	int err; - -	hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); -	if (!hwq) -		return -ENOMEM; - -	err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); -	if (err < 0) -		return err; - -	dev->mt76.q_tx[qid] = hwq; - -	mt7603_irq_enable(dev, MT_INT_TX_DONE(idx)); - -	return 0; -} -  static void  mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)  { @@ -152,14 +131,16 @@ static int mt7603_poll_tx(struct napi_struct *napi, int budget)  	dev = container_of(napi, struct mt7603_dev, mt76.tx_napi);  	dev->tx_dma_check = 0; -	for (i = MT_TXQ_MCU; i >= 0; i--) -		mt76_queue_tx_cleanup(dev, i, false); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); +	for (i = MT_TXQ_PSD; i >= 0; i--) +		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);  	if (napi_complete_done(napi, 0))  		mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); -	for (i = MT_TXQ_MCU; i >= 0; i--) -		mt76_queue_tx_cleanup(dev, i, false); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); +	for (i = MT_TXQ_PSD; i >= 0; i--) +		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);  	mt7603_mac_sta_poll(dev); @@ -191,32 +172,42 @@ int mt7603_dma_init(struct mt7603_dev *dev)  	mt7603_pse_client_reset(dev);  	for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { -		ret = mt7603_init_tx_queue(dev, i, wmm_queue_map[i], -					   MT7603_TX_RING_SIZE); +		ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], +					 MT7603_TX_RING_SIZE, MT_TX_RING_BASE);  		if (ret)  			return ret;  	} -	ret = mt7603_init_tx_queue(dev, MT_TXQ_PSD, -				   MT_TX_HW_QUEUE_MGMT, MT7603_PSD_RING_SIZE); +	ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, +				 MT7603_PSD_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret; -	ret = mt7603_init_tx_queue(dev, MT_TXQ_MCU, -				   MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE); +	ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT_TX_HW_QUEUE_MCU, +				  MT_MCU_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret; -	ret = mt7603_init_tx_queue(dev, MT_TXQ_BEACON, -				   MT_TX_HW_QUEUE_BCN, MT_MCU_RING_SIZE); +	ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN, +				 MT_MCU_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret; -	ret = mt7603_init_tx_queue(dev, MT_TXQ_CAB, -				   MT_TX_HW_QUEUE_BMC, MT_MCU_RING_SIZE); +	ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC, +				 MT_MCU_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret; +	mt7603_irq_enable(dev, +			  MT_INT_TX_DONE(IEEE80211_AC_VO) | +			  MT_INT_TX_DONE(IEEE80211_AC_VI) | +			  MT_INT_TX_DONE(IEEE80211_AC_BE) | +			  MT_INT_TX_DONE(IEEE80211_AC_BK) | +			  MT_INT_TX_DONE(MT_TX_HW_QUEUE_MGMT) | +			  MT_INT_TX_DONE(MT_TX_HW_QUEUE_MCU) | +			  MT_INT_TX_DONE(MT_TX_HW_QUEUE_BCN) | +			  MT_INT_TX_DONE(MT_TX_HW_QUEUE_BMC)); +  	ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,  				   MT7603_MCU_RX_RING_SIZE, MT_RX_BUF_SIZE);  	if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c index 01f1e0da5ee1..d951cb81df83 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c @@ -141,6 +141,7 @@ static int mt7603_check_eeprom(struct mt76_dev *dev)  	switch (val) {  	case 0x7628:  	case 0x7603: +	case 0x7600:  		return 0;  	default:  		return -EINVAL; @@ -170,8 +171,8 @@ int mt7603_eeprom_init(struct mt7603_dev *dev)  	}  	eeprom = (u8 *)dev->mt76.eeprom.data; -	dev->mt76.cap.has_2ghz = true; -	memcpy(dev->mt76.macaddr, eeprom + MT_EE_MAC_ADDR, ETH_ALEN); +	dev->mphy.cap.has_2ghz = true; +	memcpy(dev->mphy.macaddr, eeprom + MT_EE_MAC_ADDR, ETH_ALEN);  	/* Check for 1SS devices */  	dev->mphy.antenna_mask = 3; @@ -180,7 +181,7 @@ int mt7603_eeprom_init(struct mt7603_dev *dev)  	    is_mt7688(dev))  		dev->mphy.antenna_mask = 1; -	mt76_eeprom_override(&dev->mt76); +	mt76_eeprom_override(&dev->mphy);  	return 0;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index c4848fafd270..b14e08046e20 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -533,8 +533,7 @@ int mt7603_register_device(struct mt7603_dev *dev)  	spin_lock_init(&dev->ps_lock);  	INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7603_mac_work); -	tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet, -		     (unsigned long)dev); +	tasklet_setup(&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet);  	dev->slottime = 9;  	dev->sensitivity_limit = 28; @@ -557,6 +556,7 @@ int mt7603_register_device(struct mt7603_dev *dev)  	ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);  	ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); +	ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);  	/* init led callbacks */  	if (IS_ENABLED(CONFIG_MT76_LEDS)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index f665a1c95eed..55095e66f2ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -445,7 +445,7 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev)  		sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);  		for (i = 0; i < 4; i++) { -			struct mt76_queue *q = dev->mt76.q_tx[i]; +			struct mt76_queue *q = dev->mphy.q_tx[i];  			u8 qidx = q->hw_idx;  			u8 tid = ac_to_tid[i];  			u32 txtime = airtime[qidx]; @@ -896,7 +896,7 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;  	struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data;  	struct ieee80211_vif *vif = info->control.vif; -	struct mt76_queue *q = dev->mt76.q_tx[qid]; +	struct mt76_queue *q = dev->mphy.q_tx[qid];  	struct mt7603_vif *mvif;  	int wlan_idx;  	int hdr_len = ieee80211_get_hdrlen_from_skb(skb); @@ -1434,8 +1434,9 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)  	mt7603_pse_client_reset(dev); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true);  	for (i = 0; i < __MT_TXQ_MAX; i++) -		mt76_queue_tx_cleanup(dev, i, true); +		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);  	mt76_for_each_q_rx(&dev->mt76, i) {  		mt76_queue_rx_reset(dev, i); @@ -1514,7 +1515,7 @@ static bool mt7603_tx_hang(struct mt7603_dev *dev)  	int i;  	for (i = 0; i < 4; i++) { -		q = dev->mt76.q_tx[i]; +		q = dev->mphy.q_tx[i];  		if (!q->queued)  			continue; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index c9226dceb510..6d47b57cbc39 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -380,9 +380,11 @@ mt7603_ps_tx_list(struct mt7603_dev *dev, struct sk_buff_head *list)  {  	struct sk_buff *skb; -	while ((skb = __skb_dequeue(list)) != NULL) -		mt76_tx_queue_skb_raw(dev, skb_get_queue_mapping(skb), -				      skb, 0); +	while ((skb = __skb_dequeue(list)) != NULL) { +		int qid = skb_get_queue_mapping(skb); + +		mt76_tx_queue_skb_raw(dev, dev->mphy.q_tx[qid], skb, 0); +	}  }  void @@ -392,7 +394,7 @@ mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)  	struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;  	struct sk_buff_head list; -	mt76_stop_tx_queues(&dev->mt76, sta, true); +	mt76_stop_tx_queues(&dev->mphy, sta, true);  	mt7603_wtbl_set_ps(dev, msta, ps);  	if (ps)  		return; @@ -512,7 +514,7 @@ mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,  	u16 cw_max = (1 << 10) - 1;  	u32 val; -	queue = dev->mt76.q_tx[queue]->hw_idx; +	queue = dev->mphy.q_tx[queue]->hw_idx;  	if (params->cw_min)  		cw_min = params->cw_min; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index a47a3a644ecc..96b6c8916730 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -14,14 +14,38 @@ struct mt7603_fw_trailer {  } __packed;  static int -__mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, -		      int cmd, int *wait_seq) +mt7603_mcu_parse_response(struct mt76_dev *mdev, int cmd, +			  struct sk_buff *skb, int seq)  { +	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); +	struct mt7603_mcu_rxd *rxd; + +	if (!skb) { +		dev_err(mdev->dev, +			"MCU message %d (seq %d) timed out\n", +			cmd, seq); +		dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT; +		return -ETIMEDOUT; +	} + +	rxd = (struct mt7603_mcu_rxd *)skb->data; +	if (seq != rxd->seq) +		return -EAGAIN; + +	return 0; +} + +static int +mt7603_mcu_skb_send_msg(struct mt76_dev *mdev, struct sk_buff *skb, +			int cmd, int *wait_seq) +{ +	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);  	int hdrlen = dev->mcu_running ? sizeof(struct mt7603_mcu_txd) : 12; -	struct mt76_dev *mdev = &dev->mt76;  	struct mt7603_mcu_txd *txd;  	u8 seq; +	mdev->mcu.timeout = 3 * HZ; +  	seq = ++mdev->mcu.msg_seq & 0xf;  	if (!seq)  		seq = ++mdev->mcu.msg_seq & 0xf; @@ -49,56 +73,7 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb,  	if (wait_seq)  		*wait_seq = seq; -	return mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0); -} - -static int -mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, -		    int len, bool wait_resp) -{ -	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); -	unsigned long expires = jiffies + 3 * HZ; -	struct mt7603_mcu_rxd *rxd; -	struct sk_buff *skb; -	int ret, seq; - -	skb = mt76_mcu_msg_alloc(mdev, data, len); -	if (!skb) -		return -ENOMEM; - -	mutex_lock(&mdev->mcu.mutex); - -	ret = __mt7603_mcu_msg_send(dev, skb, cmd, &seq); -	if (ret) -		goto out; - -	while (wait_resp) { -		bool check_seq = false; - -		skb = mt76_mcu_get_response(&dev->mt76, expires); -		if (!skb) { -			dev_err(mdev->dev, -				"MCU message %d (seq %d) timed out\n", -				cmd, seq); -			dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT; -			ret = -ETIMEDOUT; -			break; -		} - -		rxd = (struct mt7603_mcu_rxd *)skb->data; -		if (seq == rxd->seq) -			check_seq = true; - -		dev_kfree_skb(skb); - -		if (check_seq) -			break; -	} - -out: -	mutex_unlock(&mdev->mcu.mutex); - -	return ret; +	return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[MT_MCUQ_WM], skb, 0);  }  static int @@ -114,29 +89,8 @@ mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len)  		.mode = cpu_to_le32(BIT(31)),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, -				   &req, sizeof(req), true); -} - -static int -mt7603_mcu_send_firmware(struct mt7603_dev *dev, const void *data, int len) -{ -	int cur_len, ret = 0; - -	while (len > 0) { -		cur_len = min_t(int, 4096 - sizeof(struct mt7603_mcu_txd), -				len); - -		ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, -					  data, cur_len, false); -		if (ret) -			break; - -		data += cur_len; -		len -= cur_len; -	} - -	return ret; +	return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, +				 &req, sizeof(req), true);  }  static int @@ -150,15 +104,14 @@ mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr)  		.addr = cpu_to_le32(addr),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, &req, +				 sizeof(req), true);  }  static int  mt7603_mcu_restart(struct mt76_dev *dev)  { -	return __mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, -				   NULL, 0, true); +	return mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, NULL, 0, true);  }  static int mt7603_load_firmware(struct mt7603_dev *dev) @@ -226,7 +179,8 @@ static int mt7603_load_firmware(struct mt7603_dev *dev)  		goto out;  	} -	ret = mt7603_mcu_send_firmware(dev, fw->data, dl_len); +	ret = mt76_mcu_send_firmware(&dev->mt76, -MCU_CMD_FW_SCATTER, +				     fw->data, dl_len);  	if (ret) {  		dev_err(dev->mt76.dev, "Failed to send firmware to device\n");  		goto out; @@ -266,7 +220,8 @@ int mt7603_mcu_init(struct mt7603_dev *dev)  {  	static const struct mt76_mcu_ops mt7603_mcu_ops = {  		.headroom = sizeof(struct mt7603_mcu_txd), -		.mcu_send_msg = mt7603_mcu_msg_send, +		.mcu_skb_send_msg = mt7603_mcu_skb_send_msg, +		.mcu_parse_response = mt7603_mcu_parse_response,  		.mcu_restart = mt7603_mcu_restart,  	}; @@ -377,8 +332,8 @@ int mt7603_mcu_set_eeprom(struct mt7603_dev *dev)  		data[i].val = eep[req_fields[i]];  	} -	ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, -				  req, len, true); +	ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, +				req, len, true);  	kfree(req);  	return ret; @@ -424,8 +379,8 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)  	memcpy(req.temp_comp_power, eep + MT_EE_STEP_NUM_NEG_6_7,  	       sizeof(req.temp_comp_power)); -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, +				 &req, sizeof(req), true);  }  int mt7603_mcu_set_channel(struct mt7603_dev *dev) @@ -470,8 +425,8 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev)  	for (i = 0; i < ARRAY_SIZE(req.txpower); i++)  		req.txpower[i] = tx_power; -	ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, -				  &req, sizeof(req), true); +	ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, &req, +				sizeof(req), true);  	if (ret)  		return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 2a6e4332ad06..6e0a92a28b1c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -256,7 +256,7 @@ void mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,  void mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,  		       struct ieee80211_sta *sta); -void mt7603_pre_tbtt_tasklet(unsigned long arg); +void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t);  void mt7603_update_channel(struct mt76_dev *mdev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/pci.c b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c index a5845da3547a..06fa28f645f2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c @@ -57,7 +57,8 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	return 0;  error: -	ieee80211_free_hw(mt76_hw(dev)); +	mt76_free_device(&dev->mt76); +  	return ret;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index 00ba550fc48f..4d5e3f8b2a62 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -55,11 +55,26 @@ static int  mt7615_pm_set(void *data, u64 val)  {  	struct mt7615_dev *dev = data; +	int ret = 0;  	if (!mt7615_wait_for_mcu_init(dev))  		return 0; -	return mt7615_pm_set_enable(dev, val); +	if (!mt7615_firmware_offload(dev) || !mt76_is_mmio(&dev->mt76)) +		return -EOPNOTSUPP; + +	mt7615_mutex_acquire(dev); + +	if (dev->phy.n_beacon_vif) { +		ret = -EBUSY; +		goto out; +	} + +	dev->pm.enable = val; +out: +	mt7615_mutex_release(dev); + +	return ret;  }  static int @@ -172,7 +187,7 @@ mt7615_reset_test_set(void *data, u64 val)  	skb_put(skb, 1);  	mt7615_mutex_acquire(dev); -	mt76_tx_queue_skb_raw(dev, 0, skb, 0); +	mt76_tx_queue_skb_raw(dev, dev->mphy.q_tx[0], skb, 0);  	mt7615_mutex_release(dev);  	return 0; @@ -317,21 +332,18 @@ static int  mt7615_queues_read(struct seq_file *s, void *data)  {  	struct mt7615_dev *dev = dev_get_drvdata(s->private); -	static const struct { +	struct { +		struct mt76_queue *q;  		char *queue; -		int id;  	} queue_map[] = { -		{ "PDMA0", MT_TXQ_BE }, -		{ "MCUQ", MT_TXQ_MCU }, -		{ "MCUFWQ", MT_TXQ_FWDL }, +		{ dev->mphy.q_tx[MT_TXQ_BE], "PDMA0" }, +		{ dev->mt76.q_mcu[MT_MCUQ_WM], "MCUQ" }, +		{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },  	};  	int i;  	for (i = 0; i < ARRAY_SIZE(queue_map); i++) { -		struct mt76_queue *q = dev->mt76.q_tx[queue_map[i].id]; - -		if (!q) -			continue; +		struct mt76_queue *q = queue_map[i].q;  		seq_printf(s,  			   "%s:	queued=%d head=%d tail=%d\n", @@ -365,6 +377,107 @@ mt7615_rf_reg_get(void *data, u64 *val)  DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_reg, mt7615_rf_reg_get, mt7615_rf_reg_set,  			 "0x%08llx\n"); +static ssize_t +mt7615_ext_mac_addr_read(struct file *file, char __user *userbuf, +			 size_t count, loff_t *ppos) +{ +	struct mt7615_dev *dev = file->private_data; +	char buf[32 * ((ETH_ALEN * 3) + 4) + 1]; +	u8 addr[ETH_ALEN]; +	int ofs = 0; +	int i; + +	for (i = 0; i < 32; i++) { +		if (!(dev->muar_mask & BIT(i))) +			continue; + +		mt76_wr(dev, MT_WF_RMAC_MAR1, +			FIELD_PREP(MT_WF_RMAC_MAR1_IDX, i * 2) | +			MT_WF_RMAC_MAR1_START); +		put_unaligned_le32(mt76_rr(dev, MT_WF_RMAC_MAR0), addr); +		put_unaligned_le16((mt76_rr(dev, MT_WF_RMAC_MAR1) & +				    MT_WF_RMAC_MAR1_ADDR), addr + 4); +		ofs += snprintf(buf + ofs, sizeof(buf) - ofs, "%d=%pM\n", i, addr); +	} + +	return simple_read_from_buffer(userbuf, count, ppos, buf, ofs); +} + +static ssize_t +mt7615_ext_mac_addr_write(struct file *file, const char __user *userbuf, +			  size_t count, loff_t *ppos) +{ +	struct mt7615_dev *dev = file->private_data; +	unsigned long idx = 0; +	u8 addr[ETH_ALEN]; +	char buf[32]; +	char *p; + +	if (count > sizeof(buf)) +		return -EINVAL; + +	if (copy_from_user(buf, userbuf, count)) +		return -EFAULT; + +	buf[sizeof(buf) - 1] = '\0'; + +	p = strchr(buf, '='); +	if (p) { +		*p = 0; +		p++; + +		if (kstrtoul(buf, 0, &idx) || idx > 31) +			return -EINVAL; +	} else { +		idx = 0; +		p = buf; +	} + +	if (!mac_pton(p, addr)) +		return -EINVAL; + +	if (is_valid_ether_addr(addr)) { +		dev->muar_mask |= BIT(idx); +	} else { +		memset(addr, 0, sizeof(addr)); +		dev->muar_mask &= ~BIT(idx); +	} + +	mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, 1); +	mt76_wr(dev, MT_WF_RMAC_MAR0, get_unaligned_le32(addr)); +	mt76_wr(dev, MT_WF_RMAC_MAR1, +		get_unaligned_le16(addr + 4) | +		FIELD_PREP(MT_WF_RMAC_MAR1_IDX, idx * 2) | +		MT_WF_RMAC_MAR1_START | +		MT_WF_RMAC_MAR1_WRITE); + +	mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, !!dev->muar_mask); + +	return count; +} + +static const struct file_operations fops_ext_mac_addr = { +	.open = simple_open, +	.llseek = generic_file_llseek, +	.read = mt7615_ext_mac_addr_read, +	.write = mt7615_ext_mac_addr_write, +	.owner = THIS_MODULE, +}; + +static int +mt7663s_sched_quota_read(struct seq_file *s, void *data) +{ +	struct mt7615_dev *dev = dev_get_drvdata(s->private); +	struct mt76_sdio *sdio = &dev->mt76.sdio; + +	seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota); +	seq_printf(s, "ple_data_quota\t%d\n", sdio->sched.ple_data_quota); +	seq_printf(s, "pse_mcu_quota\t%d\n", sdio->sched.pse_mcu_quota); +	seq_printf(s, "sched_deficit\t%d\n", sdio->sched.deficit); + +	return 0; +} +  int mt7615_init_debugfs(struct mt7615_dev *dev)  {  	struct dentry *dir; @@ -406,11 +519,15 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)  			    &fops_reset_test);  	debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir,  				    mt7615_read_temperature); +	debugfs_create_file("ext_mac_addr", 0600, dir, dev, &fops_ext_mac_addr);  	debugfs_create_u32("rf_wfidx", 0600, dir, &dev->debugfs_rf_wf);  	debugfs_create_u32("rf_regidx", 0600, dir, &dev->debugfs_rf_reg);  	debugfs_create_file_unsafe("rf_regval", 0600, dir, dev,  				   &fops_rf_reg); +	if (mt76_is_sdio(&dev->mt76)) +		debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir, +					    mt7663s_sched_quota_read);  	return 0;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index bf8ae14121db..25e3069cf2b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -12,25 +12,6 @@  #include "mac.h"  static int -mt7615_init_tx_queue(struct mt7615_dev *dev, int qid, int idx, int n_desc) -{ -	struct mt76_queue *hwq; -	int err; - -	hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); -	if (!hwq) -		return -ENOMEM; - -	err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); -	if (err < 0) -		return err; - -	dev->mt76.q_tx[qid] = hwq; - -	return 0; -} - -static int  mt7622_init_tx_queues_multi(struct mt7615_dev *dev)  {  	static const u8 wmm_queue_map[] = { @@ -43,20 +24,21 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev)  	int i;  	for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { -		ret = mt7615_init_tx_queue(dev, i, wmm_queue_map[i], -					   MT7615_TX_RING_SIZE / 2); +		ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], +					 MT7615_TX_RING_SIZE / 2, +					 MT_TX_RING_BASE);  		if (ret)  			return ret;  	} -	ret = mt7615_init_tx_queue(dev, MT_TXQ_PSD, -				   MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE); +	ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT7622_TXQ_MGMT, +				 MT7615_TX_MGMT_RING_SIZE, +				 MT_TX_RING_BASE);  	if (ret)  		return ret; -	ret = mt7615_init_tx_queue(dev, MT_TXQ_MCU, -				   MT7622_TXQ_MCU, MT7615_TX_MCU_RING_SIZE); -	return ret; +	return mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7622_TXQ_MCU, +				   MT7615_TX_MCU_RING_SIZE, MT_TX_RING_BASE);  }  static int @@ -64,25 +46,24 @@ mt7615_init_tx_queues(struct mt7615_dev *dev)  {  	int ret, i; -	ret = mt7615_init_tx_queue(dev, MT_TXQ_FWDL, -				   MT7615_TXQ_FWDL, -				   MT7615_TX_FWDL_RING_SIZE); +	ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7615_TXQ_FWDL, +				  MT7615_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret;  	if (!is_mt7615(&dev->mt76))  		return mt7622_init_tx_queues_multi(dev); -	ret = mt7615_init_tx_queue(dev, 0, 0, MT7615_TX_RING_SIZE); +	ret = mt76_init_tx_queue(&dev->mphy, 0, 0, MT7615_TX_RING_SIZE, +				 MT_TX_RING_BASE);  	if (ret)  		return ret; -	for (i = 1; i < MT_TXQ_MCU; i++) -		dev->mt76.q_tx[i] = dev->mt76.q_tx[0]; +	for (i = 1; i <= MT_TXQ_PSD ; i++) +		dev->mphy.q_tx[i] = dev->mphy.q_tx[0]; -	ret = mt7615_init_tx_queue(dev, MT_TXQ_MCU, MT7615_TXQ_MCU, -				   MT7615_TX_MCU_RING_SIZE); -	return 0; +	return mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7615_TXQ_MCU, +				   MT7615_TX_MCU_RING_SIZE, MT_TX_RING_BASE);  }  static int mt7615_poll_tx(struct napi_struct *napi, int budget) @@ -91,7 +72,7 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget)  	dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); -	mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);  	if (napi_complete_done(napi, 0))  		mt7615_irq_enable(dev, mt7615_tx_mcu_int_mask(dev)); @@ -202,7 +183,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)  	int ret;  	/* Increase buffer size to receive large VHT MPDUs */ -	if (dev->mt76.cap.has_5ghz) +	if (dev->mphy.cap.has_5ghz)  		rx_buf_size *= 2;  	mt76_dma_attach(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index f4756bb946c3..3232ebd5eda6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -99,20 +99,20 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)  	if (is_mt7663(&dev->mt76)) {  		/* dual band */ -		dev->mt76.cap.has_2ghz = true; -		dev->mt76.cap.has_5ghz = true; +		dev->mphy.cap.has_2ghz = true; +		dev->mphy.cap.has_5ghz = true;  		return;  	}  	if (is_mt7622(&dev->mt76)) {  		/* 2GHz only */ -		dev->mt76.cap.has_2ghz = true; +		dev->mphy.cap.has_2ghz = true;  		return;  	}  	if (is_mt7611(&dev->mt76)) {  		/* 5GHz only */ -		dev->mt76.cap.has_5ghz = true; +		dev->mphy.cap.has_5ghz = true;  		return;  	} @@ -120,17 +120,17 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)  			eeprom[MT_EE_WIFI_CONF]);  	switch (val) {  	case MT_EE_5GHZ: -		dev->mt76.cap.has_5ghz = true; +		dev->mphy.cap.has_5ghz = true;  		break;  	case MT_EE_2GHZ: -		dev->mt76.cap.has_2ghz = true; +		dev->mphy.cap.has_2ghz = true;  		break;  	case MT_EE_DBDC:  		dev->dbdc_support = true; -		/* fall through */ +		fallthrough;  	default: -		dev->mt76.cap.has_2ghz = true; -		dev->mt76.cap.has_5ghz = true; +		dev->mphy.cap.has_2ghz = true; +		dev->mphy.cap.has_5ghz = true;  		break;  	}  } @@ -342,10 +342,10 @@ int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr)  	}  	mt7615_eeprom_parse_hw_cap(dev); -	memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, +	memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,  	       ETH_ALEN); -	mt76_eeprom_override(&dev->mt76); +	mt76_eeprom_override(&dev->mphy);  	return 0;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index e194259c84e9..a73b76e57c7f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -221,7 +221,7 @@ static const struct ieee80211_iface_combination if_comb_radar[] = {  	{  		.limits = if_limits,  		.n_limits = ARRAY_SIZE(if_limits), -		.max_interfaces = 4, +		.max_interfaces = MT7615_MAX_INTERFACES,  		.num_different_channels = 1,  		.beacon_int_infra_match = true,  		.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | @@ -237,7 +237,7 @@ static const struct ieee80211_iface_combination if_comb[] = {  	{  		.limits = if_limits,  		.n_limits = ARRAY_SIZE(if_limits), -		.max_interfaces = 4, +		.max_interfaces = MT7615_MAX_INTERFACES,  		.num_different_channels = 1,  		.beacon_int_infra_match = true,  	} @@ -385,7 +385,7 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)  {  	struct mt7615_phy *phy = mt7615_ext_phy(dev);  	struct mt76_phy *mphy; -	int ret; +	int i, ret;  	if (!is_mt7615(&dev->mt76))  		return -EOPNOTSUPP; @@ -422,14 +422,21 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)  	 * Make the secondary PHY MAC address local without overlapping with  	 * the usual MAC address allocation scheme on multiple virtual interfaces  	 */ -	mphy->hw->wiphy->perm_addr[0] |= 2; -	mphy->hw->wiphy->perm_addr[0] ^= BIT(7); +	memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, +	       ETH_ALEN); +	mphy->macaddr[0] |= 2; +	mphy->macaddr[0] ^= BIT(7); +	mt76_eeprom_override(mphy);  	/* second phy can only handle 5 GHz */ -	mphy->sband_2g.sband.n_channels = 0; -	mphy->hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; +	mphy->cap.has_5ghz = true; -	ret = mt76_register_phy(mphy); +	/* mt7615 second phy shares the same hw queues with the primary one */ +	for (i = 0; i <= MT_TXQ_PSD ; i++) +		mphy->q_tx[i] = dev->mphy.q_tx[i]; + +	ret = mt76_register_phy(mphy, true, mt7615_rates, +				ARRAY_SIZE(mt7615_rates));  	if (ret)  		ieee80211_free_hw(mphy->hw); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 8dc645e398fd..0f360be0b885 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -215,8 +215,8 @@ static void mt7615_mac_fill_tm_rx(struct mt7615_dev *dev, __le32 *rxv)  	dev->test.last_rcpi[1] = FIELD_GET(MT_RXV4_RCPI1, rxv4);  	dev->test.last_rcpi[2] = FIELD_GET(MT_RXV4_RCPI2, rxv4);  	dev->test.last_rcpi[3] = FIELD_GET(MT_RXV4_RCPI3, rxv4); -	dev->test.last_ib_rssi = FIELD_GET(MT_RXV3_IB_RSSI, rxv3); -	dev->test.last_wb_rssi = FIELD_GET(MT_RXV3_WB_RSSI, rxv3); +	dev->test.last_ib_rssi[0] = FIELD_GET(MT_RXV3_IB_RSSI, rxv3); +	dev->test.last_wb_rssi[0] = FIELD_GET(MT_RXV3_WB_RSSI, rxv3);  #endif  } @@ -915,22 +915,20 @@ mt7615_mac_queue_rate_update(struct mt7615_phy *phy, struct mt7615_sta *sta,  			     struct ieee80211_tx_rate *rates)  {  	struct mt7615_dev *dev = phy->dev; -	struct mt7615_wtbl_desc *wd; +	struct mt7615_wtbl_rate_desc *wrd; -	if (work_pending(&dev->wtbl_work)) +	if (work_pending(&dev->rate_work))  		return -EBUSY; -	wd = kzalloc(sizeof(*wd), GFP_ATOMIC); -	if (!wd) +	wrd = kzalloc(sizeof(*wrd), GFP_ATOMIC); +	if (!wrd)  		return -ENOMEM; -	wd->type = MT7615_WTBL_RATE_DESC; -	wd->sta = sta; - +	wrd->sta = sta;  	mt7615_mac_update_rate_desc(phy, sta, probe_rate, rates, -				    &wd->rate); -	list_add_tail(&wd->node, &dev->wd_head); -	queue_work(dev->mt76.wq, &dev->wtbl_work); +				    &wrd->rate); +	list_add_tail(&wrd->node, &dev->wrd_head); +	queue_work(dev->mt76.wq, &dev->rate_work);  	return 0;  } @@ -1030,31 +1028,33 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,  }  EXPORT_SYMBOL_GPL(mt7615_mac_set_rates); -int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, -			       struct mt76_wcid *wcid, -			       u8 *key, u8 keylen, -			       enum mt7615_cipher_type cipher, -			       enum set_key_cmd cmd) +static int +mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, +			   struct ieee80211_key_conf *key, +			   enum mt7615_cipher_type cipher, +			   enum set_key_cmd cmd)  {  	u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;  	u8 data[32] = {}; -	if (keylen > sizeof(data)) +	if (key->keylen > sizeof(data))  		return -EINVAL;  	mt76_rr_copy(dev, addr, data, sizeof(data));  	if (cmd == SET_KEY) {  		if (cipher == MT_CIPHER_TKIP) {  			/* Rx/Tx MIC keys are swapped */ -			memcpy(data + 16, key + 24, 8); -			memcpy(data + 24, key + 16, 8); +			memcpy(data, key->key, 16); +			memcpy(data + 16, key->key + 24, 8); +			memcpy(data + 24, key->key + 16, 8); +		} else { +			if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher) +				memmove(data + 16, data, 16); +			if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) +				memcpy(data, key->key, key->keylen); +			else if (cipher == MT_CIPHER_BIP_CMAC_128) +				memcpy(data + 16, key->key, 16);  		} -		if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher) -			memmove(data + 16, data, 16); -		if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) -			memcpy(data, key, keylen); -		else if (cipher == MT_CIPHER_BIP_CMAC_128) -			memcpy(data + 16, key, 16);  	} else {  		if (wcid->cipher & ~BIT(cipher)) {  			if (cipher != MT_CIPHER_BIP_CMAC_128) @@ -1068,12 +1068,11 @@ int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev,  	return 0;  } -EXPORT_SYMBOL_GPL(mt7615_mac_wtbl_update_key); -int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, -			      struct mt76_wcid *wcid, -			      enum mt7615_cipher_type cipher, -			      int keyidx, enum set_key_cmd cmd) +static int +mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, +			  enum mt7615_cipher_type cipher, +			  int keyidx, enum set_key_cmd cmd)  {  	u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; @@ -1105,12 +1104,11 @@ int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev,  	return 0;  } -EXPORT_SYMBOL_GPL(mt7615_mac_wtbl_update_pk); -void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, -				   struct mt76_wcid *wcid, -				   enum mt7615_cipher_type cipher, -				   enum set_key_cmd cmd) +static void +mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, +			      enum mt7615_cipher_type cipher, +			      enum set_key_cmd cmd)  {  	u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); @@ -1128,12 +1126,11 @@ void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev,  			mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);  	}  } -EXPORT_SYMBOL_GPL(mt7615_mac_wtbl_update_cipher); -int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, -			    struct mt76_wcid *wcid, -			    struct ieee80211_key_conf *key, -			    enum set_key_cmd cmd) +int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, +			      struct mt76_wcid *wcid, +			      struct ieee80211_key_conf *key, +			      enum set_key_cmd cmd)  {  	enum mt7615_cipher_type cipher;  	int err; @@ -1142,25 +1139,32 @@ int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,  	if (cipher == MT_CIPHER_NONE)  		return -EOPNOTSUPP; -	spin_lock_bh(&dev->mt76.lock); -  	mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd); -	err = mt7615_mac_wtbl_update_key(dev, wcid, key->key, key->keylen, -					 cipher, cmd); +	err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd);  	if (err < 0) -		goto out; +		return err; -	err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, -					cmd); +	err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd);  	if (err < 0) -		goto out; +		return err;  	if (cmd == SET_KEY)  		wcid->cipher |= BIT(cipher);  	else  		wcid->cipher &= ~BIT(cipher); -out: +	return 0; +} + +int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, +			    struct mt76_wcid *wcid, +			    struct ieee80211_key_conf *key, +			    enum set_key_cmd cmd) +{ +	int err; + +	spin_lock_bh(&dev->mt76.lock); +	err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);  	spin_unlock_bh(&dev->mt76.lock);  	return err; @@ -1431,12 +1435,12 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb)  	struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data;  	u8 i, count; -	mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false); +	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);  	if (is_mt7615(&dev->mt76)) { -		mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false); +		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);  	} else {  		for (i = 0; i < IEEE80211_NUM_ACS; i++) -			mt76_queue_tx_cleanup(dev, i, false); +			mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);  	}  	count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl)); @@ -1969,49 +1973,6 @@ out:  	queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);  } -static void -mt7615_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ -	struct mt7615_phy *phy = priv; -	struct mt7615_dev *dev = phy->dev; -	bool ext_phy = phy != &dev->phy; - -	if (mt7615_mcu_set_bss_pm(dev, vif, dev->pm.enable)) -		return; - -	if (dev->pm.enable) { -		vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; -		mt76_set(dev, MT_WF_RFCR(ext_phy), -			 MT_WF_RFCR_DROP_OTHER_BEACON); -	} else { -		vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; -		mt76_clear(dev, MT_WF_RFCR(ext_phy), -			   MT_WF_RFCR_DROP_OTHER_BEACON); -	} -} - -int mt7615_pm_set_enable(struct mt7615_dev *dev, bool enable) -{ -	struct mt76_phy *mphy = dev->phy.mt76; - -	if (!mt7615_firmware_offload(dev) || !mt76_is_mmio(&dev->mt76)) -		return -EOPNOTSUPP; - -	mt7615_mutex_acquire(dev); - -	if (dev->pm.enable == enable) -		goto out; - -	dev->pm.enable = enable; -	ieee80211_iterate_active_interfaces(mphy->hw, -					    IEEE80211_IFACE_ITER_RESUME_ALL, -					    mt7615_pm_interface_iter, mphy->priv); -out: -	mt7615_mutex_release(dev); - -	return 0; -} -  void mt7615_mac_work(struct work_struct *work)  {  	struct mt7615_phy *phy; @@ -2083,8 +2044,9 @@ void mt7615_dma_reset(struct mt7615_dev *dev)  		   MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);  	usleep_range(1000, 2000); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true);  	for (i = 0; i < __MT_TXQ_MAX; i++) -		mt76_queue_tx_cleanup(dev, i, true); +		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);  	mt76_for_each_q_rx(&dev->mt76, i) {  		mt76_queue_rx_reset(dev, i); @@ -2314,3 +2276,46 @@ stop:  	mt7615_dfs_stop_radar_detector(phy);  	return 0;  } + +int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy, +				 struct ieee80211_vif *vif, +				 bool enable) +{ +	struct mt7615_dev *dev = phy->dev; +	bool ext_phy = phy != &dev->phy; +	int err; + +	if (!mt7615_firmware_offload(dev)) +		return -EOPNOTSUPP; + +	switch (vif->type) { +	case NL80211_IFTYPE_MONITOR: +		return 0; +	case NL80211_IFTYPE_MESH_POINT: +	case NL80211_IFTYPE_ADHOC: +	case NL80211_IFTYPE_AP: +		if (enable) +			phy->n_beacon_vif++; +		else +			phy->n_beacon_vif--; +		fallthrough; +	default: +		break; +	} + +	err = mt7615_mcu_set_bss_pm(dev, vif, !phy->n_beacon_vif); +	if (err) +		return err; + +	if (phy->n_beacon_vif) { +		vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; +		mt76_clear(dev, MT_WF_RFCR(ext_phy), +			   MT_WF_RFCR_DROP_OTHER_BEACON); +	} else { +		vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; +		mt76_set(dev, MT_WF_RFCR(ext_phy), +			 MT_WF_RFCR_DROP_OTHER_BEACON); +	} + +	return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 3186b7b2ca48..56dd0b4e4460 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -115,29 +115,50 @@ static void mt7615_stop(struct ieee80211_hw *hw)  	mt7615_mutex_release(dev);  } -static int get_omac_idx(enum nl80211_iftype type, u32 mask) +static inline int get_free_idx(u32 mask, u8 start, u8 end) +{ +	return ffs(~mask & GENMASK(end, start)); +} + +static int get_omac_idx(enum nl80211_iftype type, u64 mask)  {  	int i;  	switch (type) { -	case NL80211_IFTYPE_MONITOR: -	case NL80211_IFTYPE_AP:  	case NL80211_IFTYPE_MESH_POINT:  	case NL80211_IFTYPE_ADHOC: -		/* ap use hw bssid 0 and ext bssid */ +	case NL80211_IFTYPE_STATION: +		/* prefer hw bssid slot 1-3 */ +		i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3); +		if (i) +			return i - 1; + +		if (type != NL80211_IFTYPE_STATION) +			break; + +		/* next, try to find a free repeater entry for the sta */ +		i = get_free_idx(mask >> REPEATER_BSSID_START, 0, +				 REPEATER_BSSID_MAX - REPEATER_BSSID_START); +		if (i) +			return i + 32 - 1; + +		i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); +		if (i) +			return i - 1; +  		if (~mask & BIT(HW_BSSID_0))  			return HW_BSSID_0; -		for (i = EXT_BSSID_1; i < EXT_BSSID_END; i++) -			if (~mask & BIT(i)) -				return i; -  		break; -	case NL80211_IFTYPE_STATION: -		/* sta use hw bssid other than 0 */ -		for (i = HW_BSSID_1; i < HW_BSSID_MAX; i++) -			if (~mask & BIT(i)) -				return i; +	case NL80211_IFTYPE_MONITOR: +	case NL80211_IFTYPE_AP: +		/* ap uses hw bssid 0 and ext bssid */ +		if (~mask & BIT(HW_BSSID_0)) +			return HW_BSSID_0; + +		i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); +		if (i) +			return i - 1;  		break;  	default: @@ -187,8 +208,8 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,  		mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS;  	dev->mphy.vif_mask |= BIT(mvif->idx); -	dev->omac_mask |= BIT(mvif->omac_idx); -	phy->omac_mask |= BIT(mvif->omac_idx); +	dev->omac_mask |= BIT_ULL(mvif->omac_idx); +	phy->omac_mask |= BIT_ULL(mvif->omac_idx);  	mt7615_mcu_set_dbdc(dev); @@ -211,15 +232,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,  	if (ret)  		goto out; -	if (dev->pm.enable) { -		ret = mt7615_mcu_set_bss_pm(dev, vif, true); -		if (ret) -			goto out; - -		vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; -		mt76_set(dev, MT_WF_RFCR(ext_phy), -			 MT_WF_RFCR_DROP_OTHER_BEACON); -	} +	mt7615_mac_set_beacon_filter(phy, vif, true);  out:  	mt7615_mutex_release(dev); @@ -245,20 +258,14 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,  	mt7615_free_pending_tx_skbs(dev, msta); -	if (dev->pm.enable) { -		bool ext_phy = phy != &dev->phy; - -		mt7615_mcu_set_bss_pm(dev, vif, false); -		mt76_clear(dev, MT_WF_RFCR(ext_phy), -			   MT_WF_RFCR_DROP_OTHER_BEACON); -	} +	mt7615_mac_set_beacon_filter(phy, vif, false);  	mt7615_mcu_add_dev_info(dev, vif, false);  	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);  	dev->mphy.vif_mask &= ~BIT(mvif->idx); -	dev->omac_mask &= ~BIT(mvif->omac_idx); -	phy->omac_mask &= ~BIT(mvif->omac_idx); +	dev->omac_mask &= ~BIT_ULL(mvif->omac_idx); +	phy->omac_mask &= ~BIT_ULL(mvif->omac_idx);  	mt7615_mutex_release(dev); @@ -334,39 +341,6 @@ out:  	return ret;  } -static int -mt7615_queue_key_update(struct mt7615_dev *dev, enum set_key_cmd cmd, -			struct mt7615_sta *msta, -			struct ieee80211_key_conf *key) -{ -	struct mt7615_wtbl_desc *wd; - -	wd = kzalloc(sizeof(*wd), GFP_KERNEL); -	if (!wd) -		return -ENOMEM; - -	wd->type = MT7615_WTBL_KEY_DESC; -	wd->sta = msta; - -	wd->key.key = kmemdup(key->key, key->keylen, GFP_KERNEL); -	if (!wd->key.key) { -		kfree(wd); -		return -ENOMEM; -	} -	wd->key.cipher = key->cipher; -	wd->key.keyidx = key->keyidx; -	wd->key.keylen = key->keylen; -	wd->key.cmd = cmd; - -	spin_lock_bh(&dev->mt76.lock); -	list_add_tail(&wd->node, &dev->wd_head); -	spin_unlock_bh(&dev->mt76.lock); - -	queue_work(dev->mt76.wq, &dev->wtbl_work); - -	return 0; -} -  static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  			  struct ieee80211_vif *vif, struct ieee80211_sta *sta,  			  struct ieee80211_key_conf *key) @@ -393,8 +367,6 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  	case WLAN_CIPHER_SUITE_AES_CMAC:  		key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;  		break; -	case WLAN_CIPHER_SUITE_WEP40: -	case WLAN_CIPHER_SUITE_WEP104:  	case WLAN_CIPHER_SUITE_TKIP:  	case WLAN_CIPHER_SUITE_CCMP:  	case WLAN_CIPHER_SUITE_CCMP_256: @@ -402,6 +374,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  	case WLAN_CIPHER_SUITE_GCMP_256:  	case WLAN_CIPHER_SUITE_SMS4:  		break; +	case WLAN_CIPHER_SUITE_WEP40: +	case WLAN_CIPHER_SUITE_WEP104:  	default:  		return -EOPNOTSUPP;  	} @@ -420,7 +394,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  	if (mt76_is_mmio(&dev->mt76))  		err = mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);  	else -		err = mt7615_queue_key_update(dev, cmd, msta, key); +		err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);  	mt7615_mutex_release(dev); @@ -511,7 +485,6 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw,  	} while (0)  	phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | -			   MT_WF_RFCR_DROP_OTHER_BEACON |  			   MT_WF_RFCR_DROP_FRAME_REPORT |  			   MT_WF_RFCR_DROP_PROBEREQ |  			   MT_WF_RFCR_DROP_MCAST_FILTERED | @@ -522,6 +495,9 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw,  			   MT_WF_RFCR_DROP_UNWANTED_CTL |  			   MT_WF_RFCR_DROP_STBC_MULTI); +	if (phy->n_beacon_vif || !mt7615_firmware_offload(dev)) +		phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_BEACON; +  	MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |  			       MT_WF_RFCR_DROP_A3_MAC |  			       MT_WF_RFCR_DROP_A3_BSSID); @@ -1127,7 +1103,6 @@ static int mt7615_suspend(struct ieee80211_hw *hw,  {  	struct mt7615_dev *dev = mt7615_hw_dev(hw);  	struct mt7615_phy *phy = mt7615_hw_phy(hw); -	bool ext_phy = phy != &dev->phy;  	int err = 0;  	cancel_delayed_work_sync(&dev->pm.ps_work); @@ -1139,8 +1114,6 @@ static int mt7615_suspend(struct ieee80211_hw *hw,  	cancel_delayed_work_sync(&phy->scan_work);  	cancel_delayed_work_sync(&phy->mac_work); -	mt76_set(dev, MT_WF_RFCR(ext_phy), MT_WF_RFCR_DROP_OTHER_BEACON); -  	set_bit(MT76_STATE_SUSPEND, &phy->mt76->state);  	ieee80211_iterate_active_interfaces(hw,  					    IEEE80211_IFACE_ITER_RESUME_ALL, @@ -1158,7 +1131,7 @@ static int mt7615_resume(struct ieee80211_hw *hw)  {  	struct mt7615_dev *dev = mt7615_hw_dev(hw);  	struct mt7615_phy *phy = mt7615_hw_phy(hw); -	bool running, ext_phy = phy != &dev->phy; +	bool running;  	mt7615_mutex_acquire(dev); @@ -1182,7 +1155,6 @@ static int mt7615_resume(struct ieee80211_hw *hw)  	ieee80211_queue_delayed_work(hw, &phy->mac_work,  				     MT7615_WATCHDOG_TIME); -	mt76_clear(dev, MT_WF_RFCR(ext_phy), MT_WF_RFCR_DROP_OTHER_BEACON);  	mt7615_mutex_release(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 31b40fb83f6c..a44b7766dec6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -94,6 +94,9 @@ void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,  	__le32 *txd;  	u32 val; +	/* TODO: make dynamic based on msg type */ +	dev->mt76.mcu.timeout = 20 * HZ; +  	seq = ++dev->mt76.mcu.msg_seq & 0xf;  	if (!seq)  		seq = ++dev->mt76.mcu.msg_seq & 0xf; @@ -165,32 +168,22 @@ void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,  }  EXPORT_SYMBOL_GPL(mt7615_mcu_fill_msg); -static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, -				 int cmd, int *wait_seq) +int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd, +			      struct sk_buff *skb, int seq)  { -	enum mt76_txq_id qid; - -	mt7615_mcu_fill_msg(dev, skb, cmd, wait_seq); -	if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) -		qid = MT_TXQ_MCU; -	else -		qid = MT_TXQ_FWDL; - -	return mt76_tx_queue_skb_raw(dev, qid, skb, 0); -} - -static int -mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd, -			  struct sk_buff *skb, int seq) -{ -	struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data; +	struct mt7615_mcu_rxd *rxd;  	int ret = 0; -	if (seq != rxd->seq) { -		ret = -EAGAIN; -		goto out; +	if (!skb) { +		dev_err(mdev->dev, "Message %ld (seq %d) timeout\n", +			cmd & MCU_CMD_MASK, seq); +		return -ETIMEDOUT;  	} +	rxd = (struct mt7615_mcu_rxd *)skb->data; +	if (seq != rxd->seq) +		return -EAGAIN; +  	switch (cmd) {  	case MCU_CMD_PATCH_SEM_CONTROL:  		skb_pull(skb, sizeof(*rxd) - 4); @@ -228,69 +221,26 @@ mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd,  	default:  		break;  	} -out: -	dev_kfree_skb(skb); - -	return ret; -} - -int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq) -{ -	unsigned long expires = jiffies + 20 * HZ; -	struct sk_buff *skb; -	int ret = 0; - -	while (true) { -		skb = mt76_mcu_get_response(&dev->mt76, expires); -		if (!skb) { -			dev_err(dev->mt76.dev, "Message %ld (seq %d) timeout\n", -				cmd & MCU_CMD_MASK, seq); -			return -ETIMEDOUT; -		} - -		ret = mt7615_mcu_parse_response(dev, cmd, skb, seq); -		if (ret != -EAGAIN) -			break; -	}  	return ret;  } -EXPORT_SYMBOL_GPL(mt7615_mcu_wait_response); +EXPORT_SYMBOL_GPL(mt7615_mcu_parse_response);  static int  mt7615_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, -			int cmd, bool wait_resp) +			int cmd, int *seq)  {  	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); -	int ret, seq; - -	mutex_lock(&mdev->mcu.mutex); - -	ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); -	if (ret) -		goto out; - -	if (wait_resp) -		ret = mt7615_mcu_wait_response(dev, cmd, seq); - -out: -	mutex_unlock(&mdev->mcu.mutex); - -	return ret; -} - -int mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, -			int len, bool wait_resp) -{ -	struct sk_buff *skb; +	enum mt76_txq_id qid; -	skb = mt76_mcu_msg_alloc(mdev, data, len); -	if (!skb) -		return -ENOMEM; +	mt7615_mcu_fill_msg(dev, skb, cmd, seq); +	if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) +		qid = MT_MCUQ_WM; +	else +		qid = MT_MCUQ_FWDL; -	return __mt76_mcu_skb_send_msg(mdev, skb, cmd, wait_resp); +	return mt76_tx_queue_skb_raw(dev, dev->mt76.q_mcu[qid], skb, 0);  } -EXPORT_SYMBOL_GPL(mt7615_mcu_msg_send);  u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg)  { @@ -303,9 +253,9 @@ u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg)  		.address = cpu_to_le32(reg),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, -				   MCU_EXT_CMD_RF_REG_ACCESS | MCU_QUERY_PREFIX, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, +				 MCU_EXT_CMD_RF_REG_ACCESS | MCU_QUERY_PREFIX, +				 &req, sizeof(req), true);  }  int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val) @@ -320,8 +270,8 @@ int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val)  		.data = cpu_to_le32(val),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RF_REG_ACCESS, &req, -				   sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RF_REG_ACCESS, &req, +				 sizeof(req), false);  }  static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) @@ -645,8 +595,44 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr,  		.mode = cpu_to_le32(mode),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_TARGET_ADDRESS_LEN_REQ, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_TARGET_ADDRESS_LEN_REQ, +				 &req, sizeof(req), true); +} + +static int +mt7615_mcu_muar_config(struct mt7615_dev *dev, struct ieee80211_vif *vif, +		       bool bssid, bool enable) +{ +	struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; +	u32 idx = mvif->omac_idx - REPEATER_BSSID_START; +	u32 mask = dev->omac_mask >> 32 & ~BIT(idx); +	const u8 *addr = vif->addr; +	struct { +		u8 mode; +		u8 force_clear; +		u8 clear_bitmap[8]; +		u8 entry_count; +		u8 write; + +		u8 index; +		u8 bssid; +		u8 addr[ETH_ALEN]; +	} __packed req = { +		.mode = !!mask || enable, +		.entry_count = 1, +		.write = 1, + +		.index = idx * 2 + bssid, +	}; + +	if (bssid) +		addr = vif->bss_conf.bssid; + +	if (enable) +		ether_addr_copy(req.addr, addr); + +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MUAR_UPDATE, &req, +				 sizeof(req), true);  }  static int @@ -684,9 +670,12 @@ mt7615_mcu_add_dev(struct mt7615_dev *dev, struct ieee80211_vif *vif,  		},  	}; +	if (mvif->omac_idx >= REPEATER_BSSID_START) +		return mt7615_mcu_muar_config(dev, vif, false, enable); +  	memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, -				   &data, sizeof(data), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, +				 &data, sizeof(data), true);  }  static int @@ -750,8 +739,8 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,  	}  	dev_kfree_skb(skb); -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, &req, +				 sizeof(req), true);  }  static int @@ -781,8 +770,8 @@ mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)  		.band_idx = band,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, &req, +				 sizeof(req), true);  }  static struct sk_buff * @@ -1266,6 +1255,9 @@ mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,  	struct mt7615_dev *dev = phy->dev;  	struct sk_buff *skb; +	if (mvif->omac_idx >= REPEATER_BSSID_START) +		mt7615_mcu_muar_config(dev, vif, true, enable); +  	skb = mt7615_mcu_alloc_sta_req(dev, mvif, NULL);  	if (IS_ERR(skb))  		return PTR_ERR(skb); @@ -1275,11 +1267,12 @@ mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,  	mt7615_mcu_bss_basic_tlv(skb, vif, sta, enable); -	if (enable && mvif->omac_idx > EXT_BSSID_START) +	if (enable && mvif->omac_idx >= EXT_BSSID_START && +	    mvif->omac_idx < REPEATER_BSSID_START)  		mt7615_mcu_bss_ext_tlv(skb, mvif); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_BSS_INFO_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_BSS_INFO_UPDATE, true);  }  static int @@ -1299,8 +1292,8 @@ mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev,  	mt7615_mcu_wtbl_ba_tlv(skb, params, enable, true, NULL, wtbl_hdr); -	err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				      MCU_EXT_CMD_WTBL_UPDATE, true); +	err = mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, +				    true);  	if (err < 0)  		return err; @@ -1310,8 +1303,8 @@ mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev,  	mt7615_mcu_sta_ba_tlv(skb, params, enable, true); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_STA_REC_UPDATE, true);  }  static int @@ -1331,8 +1324,8 @@ mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev,  	mt7615_mcu_sta_ba_tlv(skb, params, enable, false); -	err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				      MCU_EXT_CMD_STA_REC_UPDATE, true); +	err = mt76_mcu_skb_send_msg(&dev->mt76, skb, +				    MCU_EXT_CMD_STA_REC_UPDATE, true);  	if (err < 0 || !enable)  		return err; @@ -1343,8 +1336,8 @@ mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev,  	mt7615_mcu_wtbl_ba_tlv(skb, params, enable, false, NULL, wtbl_hdr); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_WTBL_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, +				     true);  }  static int @@ -1383,7 +1376,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_dev *dev, struct ieee80211_vif *vif,  	cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE;  	skb = enable ? wskb : sskb; -	err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); +	err = mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);  	if (err < 0) {  		skb = enable ? sskb : wskb;  		dev_kfree_skb(skb); @@ -1394,7 +1387,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_dev *dev, struct ieee80211_vif *vif,  	cmd = enable ? MCU_EXT_CMD_STA_REC_UPDATE : MCU_EXT_CMD_WTBL_UPDATE;  	skb = enable ? sskb : wskb; -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);  }  static const struct mt7615_mcu_ops wtbl_update_ops = { @@ -1432,8 +1425,8 @@ mt7615_mcu_sta_ba(struct mt7615_dev *dev,  					     &skb);  	mt7615_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_STA_REC_UPDATE, true);  }  static int @@ -1484,7 +1477,7 @@ mt7615_mcu_add_sta_cmd(struct mt7615_dev *dev, struct ieee80211_vif *vif,  			mt7615_mcu_wtbl_ht_tlv(skb, sta, sta_wtbl, wtbl_hdr);  	} -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);  }  static int @@ -1586,7 +1579,7 @@ mt7615_mcu_uni_add_dev(struct mt7615_dev *dev,  	data = enable ? (void *)&dev_req : (void *)&basic_req;  	len = enable ? sizeof(dev_req) : sizeof(basic_req); -	err = __mt76_mcu_send_msg(&dev->mt76, cmd, data, len, true); +	err = mt76_mcu_send_msg(&dev->mt76, cmd, data, len, true);  	if (err < 0)  		return err; @@ -1594,7 +1587,7 @@ mt7615_mcu_uni_add_dev(struct mt7615_dev *dev,  	data = enable ? (void *)&basic_req : (void *)&dev_req;  	len = enable ? sizeof(basic_req) : sizeof(dev_req); -	return __mt76_mcu_send_msg(&dev->mt76, cmd, data, len, true); +	return mt76_mcu_send_msg(&dev->mt76, cmd, data, len, true);  }  static int @@ -1708,8 +1701,8 @@ mt7615_mcu_uni_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,  	basic_req.basic.sta_idx = cpu_to_le16(mvif->sta.wcid.idx);  	basic_req.basic.conn_state = !enable; -	err = __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, -				  &basic_req, sizeof(basic_req), true); +	err = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, +				&basic_req, sizeof(basic_req), true);  	if (err < 0)  		return err; @@ -1744,8 +1737,8 @@ mt7615_mcu_uni_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,  	else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan)  		rlm_req.rlm.sco = 3; /* SCB */ -	return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, -				   &rlm_req, sizeof(rlm_req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, +				 &rlm_req, sizeof(rlm_req), true);  }  static int @@ -1816,8 +1809,8 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,  	}  	dev_kfree_skb(skb); -	return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, +				 &req, sizeof(req), true);  }  static int @@ -1846,8 +1839,8 @@ mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev,  	mt7615_mcu_wtbl_ba_tlv(skb, params, enable, true, sta_wtbl,  			       wtbl_hdr); -	err =  __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_UNI_CMD_STA_REC_UPDATE, true); +	err =  mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_UNI_CMD_STA_REC_UPDATE, true);  	if (err < 0)  		return err; @@ -1857,8 +1850,8 @@ mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev,  	mt7615_mcu_sta_ba_tlv(skb, params, enable, true); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_UNI_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_UNI_CMD_STA_REC_UPDATE, true);  }  static int @@ -1879,8 +1872,8 @@ mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev,  	mt7615_mcu_sta_ba_tlv(skb, params, enable, false); -	err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				      MCU_UNI_CMD_STA_REC_UPDATE, true); +	err = mt76_mcu_skb_send_msg(&dev->mt76, skb, +				    MCU_UNI_CMD_STA_REC_UPDATE, true);  	if (err < 0 || !enable)  		return err; @@ -1898,8 +1891,8 @@ mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev,  	mt7615_mcu_wtbl_ba_tlv(skb, params, enable, false, sta_wtbl,  			       wtbl_hdr); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_UNI_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_UNI_CMD_STA_REC_UPDATE, true);  }  static int @@ -1922,29 +1915,6 @@ static const struct mt7615_mcu_ops uni_update_ops = {  	.set_fw_ctrl = mt7615_mcu_fw_pmctrl,  }; -static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, -				    int len) -{ -	int ret = 0, cur_len; - -	while (len > 0) { -		cur_len = min_t(int, 4096 - dev->mt76.mcu_ops->headroom, len); - -		ret = __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_SCATTER, -					  data, cur_len, false); -		if (ret) -			break; - -		data += cur_len; -		len -= cur_len; - -		if (mt76_is_mmio(&dev->mt76)) -			mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); -	} - -	return ret; -} -  static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr,  				     u32 option)  { @@ -1956,14 +1926,13 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr,  		.addr = cpu_to_le32(addr),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_START_REQ, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_START_REQ, &req, +				 sizeof(req), true);  }  int mt7615_mcu_restart(struct mt76_dev *dev)  { -	return __mt76_mcu_send_msg(dev, MCU_CMD_RESTART_DL_REQ, NULL, -				   0, true); +	return mt76_mcu_send_msg(dev, MCU_CMD_RESTART_DL_REQ, NULL, 0, true);  }  EXPORT_SYMBOL_GPL(mt7615_mcu_restart); @@ -1975,8 +1944,8 @@ static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get)  		.op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_SEM_CONTROL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_SEM_CONTROL, &req, +				 sizeof(req), true);  }  static int mt7615_mcu_start_patch(struct mt7615_dev *dev) @@ -1988,8 +1957,8 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev)  		.check_crc = 0,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_FINISH_REQ, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_FINISH_REQ, &req, +				 sizeof(req), true);  }  static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) @@ -2032,7 +2001,8 @@ static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name)  		goto out;  	} -	ret = mt7615_mcu_send_firmware(dev, fw->data + sizeof(*hdr), len); +	ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, +				     fw->data + sizeof(*hdr), len);  	if (ret) {  		dev_err(dev->mt76.dev, "Failed to send firmware to device\n");  		goto out; @@ -2092,7 +2062,8 @@ mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev,  			return err;  		} -		err = mt7615_mcu_send_firmware(dev, data + offset, len); +		err = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, +					     data + offset, len);  		if (err) {  			dev_err(dev->mt76.dev, "Failed to send firmware to device\n");  			return err; @@ -2285,8 +2256,8 @@ int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl)  		.ctrl_val = ctrl  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, -				   &data, sizeof(data), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, &data, +				 sizeof(data), true);  }  static int mt7663_load_n9(struct mt7615_dev *dev, const char *name) @@ -2333,7 +2304,8 @@ static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)  			goto out;  		} -		ret = mt7615_mcu_send_firmware(dev, fw->data + offset, len); +		ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER, +					     fw->data + offset, len);  		if (ret) {  			dev_err(dev->mt76.dev, "Failed to send firmware\n");  			goto out; @@ -2467,7 +2439,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev)  	static const struct mt76_mcu_ops mt7615_mcu_ops = {  		.headroom = sizeof(struct mt7615_mcu_txd),  		.mcu_skb_send_msg = mt7615_mcu_send_message, -		.mcu_send_msg = mt7615_mcu_msg_send, +		.mcu_parse_response = mt7615_mcu_parse_response,  		.mcu_restart = mt7615_mcu_restart,  	};  	int ret; @@ -2492,7 +2464,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev)  	if (ret)  		return ret; -	mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);  	dev_dbg(dev->mt76.dev, "Firmware init done\n");  	set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);  	mt7615_mcu_fw_log_2_host(dev, 0); @@ -2547,8 +2519,8 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev)  	skb_put_data(skb, &req_hdr, sizeof(req_hdr));  	skb_put_data(skb, eep + offset, eep_len); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_EFUSE_BUFFER_MODE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_EFUSE_BUFFER_MODE, true);  }  EXPORT_SYMBOL_GPL(mt7615_mcu_set_eeprom); @@ -2563,8 +2535,8 @@ int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable)  		.band = band,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, &req, +				 sizeof(req), true);  }  int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val) @@ -2583,8 +2555,8 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val)  		.pkt_thresh = cpu_to_le32(0x2),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, &req, +				 sizeof(req), true);  }  int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, @@ -2620,8 +2592,8 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue,  	if (params->cw_max)  		req.cw_max = cpu_to_le16(fls(params->cw_max)); -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, &req, +				 sizeof(req), true);  }  int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) @@ -2654,13 +2626,13 @@ int mt7615_mcu_set_dbdc(struct mt7615_dev *dev)  	} while (0)  	for (i = 0; i < 4; i++) { -		bool band = !!(ext_phy->omac_mask & BIT(i)); +		bool band = !!(ext_phy->omac_mask & BIT_ULL(i));  		ADD_DBDC_ENTRY(DBDC_TYPE_BSS, i, band);  	}  	for (i = 0; i < 14; i++) { -		bool band = !!(ext_phy->omac_mask & BIT(0x11 + i)); +		bool band = !!(ext_phy->omac_mask & BIT_ULL(0x11 + i));  		ADD_DBDC_ENTRY(DBDC_TYPE_MBSS, i, band);  	} @@ -2679,8 +2651,8 @@ int mt7615_mcu_set_dbdc(struct mt7615_dev *dev)  	ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 1, 1);  out: -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DBDC_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DBDC_CTRL, &req, +				 sizeof(req), true);  }  int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) @@ -2689,8 +2661,8 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev)  		.operation = WTBL_RESET_ALL,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, &req, +				 sizeof(req), true);  }  EXPORT_SYMBOL_GPL(mt7615_mcu_del_wtbl_all); @@ -2711,56 +2683,98 @@ int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev,  		.val = val,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, &req, +				 sizeof(req), true);  }  int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val)  {  	struct { -		u16 tag; -		u16 min_lpn; +		__le16 tag; +		__le16 min_lpn;  	} req = { -		.tag = 0x1, -		.min_lpn = val, +		.tag = cpu_to_le16(0x1), +		.min_lpn = cpu_to_le16(val),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, +				 sizeof(req), true);  }  int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,  			    const struct mt7615_dfs_pulse *pulse)  {  	struct { -		u16 tag; -		struct mt7615_dfs_pulse pulse; +		__le16 tag; +		__le32 max_width;	/* us */ +		__le32 max_pwr;		/* dbm */ +		__le32 min_pwr;		/* dbm */ +		__le32 min_stgr_pri;	/* us */ +		__le32 max_stgr_pri;	/* us */ +		__le32 min_cr_pri;	/* us */ +		__le32 max_cr_pri;	/* us */  	} req = { -		.tag = 0x3, +		.tag = cpu_to_le16(0x3), +#define __req_field(field) .field = cpu_to_le32(pulse->field) +		__req_field(max_width), +		__req_field(max_pwr), +		__req_field(min_pwr), +		__req_field(min_stgr_pri), +		__req_field(max_stgr_pri), +		__req_field(min_cr_pri), +		__req_field(max_cr_pri), +#undef  __req_field  	}; -	memcpy(&req.pulse, pulse, sizeof(*pulse)); - -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, +				 sizeof(req), true);  }  int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index,  			    const struct mt7615_dfs_pattern *pattern)  {  	struct { -		u16 tag; -		u16 radar_type; -		struct mt7615_dfs_pattern pattern; +		__le16 tag; +		__le16 radar_type; +		u8 enb; +		u8 stgr; +		u8 min_crpn; +		u8 max_crpn; +		u8 min_crpr; +		u8 min_pw; +		u8 max_pw; +		__le32 min_pri; +		__le32 max_pri; +		u8 min_crbn; +		u8 max_crbn; +		u8 min_stgpn; +		u8 max_stgpn; +		u8 min_stgpr;  	} req = { -		.tag = 0x2, -		.radar_type = index, +		.tag = cpu_to_le16(0x2), +		.radar_type = cpu_to_le16(index), +#define __req_field_u8(field) .field = pattern->field +#define __req_field_u32(field) .field = cpu_to_le32(pattern->field) +		__req_field_u8(enb), +		__req_field_u8(stgr), +		__req_field_u8(min_crpn), +		__req_field_u8(max_crpn), +		__req_field_u8(min_crpr), +		__req_field_u8(min_pw), +		__req_field_u8(max_pw), +		__req_field_u32(min_pri), +		__req_field_u32(max_pri), +		__req_field_u8(min_crbn), +		__req_field_u8(max_crbn), +		__req_field_u8(min_stgpn), +		__req_field_u8(max_stgpn), +		__req_field_u8(min_stgpr), +#undef __req_field_u8 +#undef __req_field_u32  	}; -	memcpy(&req.pattern, pattern, sizeof(*pattern)); - -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, +				 sizeof(req), true);  }  int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) @@ -2769,9 +2783,9 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev)  		u8 pulse_num;  		u8 rsv[3];  		struct { -			u32 start_time; -			u16 width; -			s16 power; +			__le32 start_time; +			__le16 width; +			__le16 power;  		} pattern[32];  	} req = {  		.pulse_num = dev->radar_pattern.n_pulses, @@ -2784,14 +2798,15 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev)  	/* TODO: add some noise here */  	for (i = 0; i < dev->radar_pattern.n_pulses; i++) { -		req.pattern[i].width = dev->radar_pattern.width; -		req.pattern[i].power = dev->radar_pattern.power; -		req.pattern[i].start_time = start_time + -					    i * dev->radar_pattern.period; +		u32 ts = start_time + i * dev->radar_pattern.period; + +		req.pattern[i].width = cpu_to_le16(dev->radar_pattern.width); +		req.pattern[i].power = cpu_to_le16(dev->radar_pattern.power); +		req.pattern[i].start_time = cpu_to_le32(ts);  	} -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_PATTERN, -				   &req, sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_PATTERN, +				 &req, sizeof(req), false);  }  static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) @@ -2885,7 +2900,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)  	else  		mt7615_mcu_set_txpower_sku(phy, req.txpower_sku); -	return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);  }  int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) @@ -2897,8 +2912,8 @@ int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index)  		.action = index,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req, -				   sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req, +				 sizeof(req), true);  }  int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode, @@ -2918,8 +2933,8 @@ int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode,  		.value = cpu_to_le32(val),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, -				   sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, +				 sizeof(req), false);  }  int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) @@ -2936,8 +2951,9 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable)  		.sku_enable = enable,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, -				   sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, +				 MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, +				 sizeof(req), true);  }  int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif) @@ -2957,8 +2973,8 @@ int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif)  	if (vif->type != NL80211_IFTYPE_STATION)  		return -ENOTSUPP; -	return __mt76_mcu_send_msg(&dev->mt76,  MCU_CMD_SET_PS_PROFILE, -				   &req, sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_PS_PROFILE, &req, +				 sizeof(req), false);  }  int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy) @@ -3018,8 +3034,8 @@ int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy)  		skb_put_data(skb, &channel, sizeof(channel));  	} -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_CMD_SET_CHAN_DOMAIN, false); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_CMD_SET_CHAN_DOMAIN, +				     false);  }  #define MT7615_SCAN_CHANNEL_TIME	60 @@ -3101,8 +3117,8 @@ int mt7615_mcu_hw_scan(struct mt7615_phy *phy, struct ieee80211_vif *vif,  		req->scan_func = 1;  	} -	err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_CMD_START_HW_SCAN, -				      false); +	err = mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_CMD_START_HW_SCAN, +				    false);  	if (err < 0)  		clear_bit(MT76_HW_SCANNING, &phy->mt76->state); @@ -3130,8 +3146,8 @@ int mt7615_mcu_cancel_hw_scan(struct mt7615_phy *phy,  		ieee80211_scan_completed(phy->mt76->hw, &info);  	} -	return __mt76_mcu_send_msg(&dev->mt76,  MCU_CMD_CANCEL_HW_SCAN, &req, -				   sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_CANCEL_HW_SCAN, &req, +				 sizeof(req), false);  }  int mt7615_mcu_sched_scan_req(struct mt7615_phy *phy, @@ -3202,8 +3218,8 @@ int mt7615_mcu_sched_scan_req(struct mt7615_phy *phy,  		memcpy(skb_put(skb, sreq->ie_len), sreq->ie, sreq->ie_len);  	} -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_CMD_SCHED_SCAN_REQ, false); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_CMD_SCHED_SCAN_REQ, +				     false);  }  int mt7615_mcu_sched_scan_enable(struct mt7615_phy *phy, @@ -3226,8 +3242,8 @@ int mt7615_mcu_sched_scan_enable(struct mt7615_phy *phy,  	else  		clear_bit(MT76_HW_SCHED_SCANNING, &phy->mt76->state); -	return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SCHED_SCAN_ENABLE, -				   &req, sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SCHED_SCAN_ENABLE, &req, +				 sizeof(req), false);  }  static int mt7615_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur) @@ -3366,8 +3382,8 @@ again:  out:  	req.center_freq = cpu_to_le16(center_freq); -	ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RXDCOC_CAL, &req, -				  sizeof(req), true); +	ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RXDCOC_CAL, &req, +				sizeof(req), true);  	if ((chandef->width == NL80211_CHAN_WIDTH_80P80 ||  	     chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) { @@ -3487,8 +3503,8 @@ again:  out:  	req.center_freq = cpu_to_le16(center_freq); -	ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXDPD_CAL, &req, -				  sizeof(req), true); +	ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXDPD_CAL, &req, +				sizeof(req), true);  	if ((chandef->width == NL80211_CHAN_WIDTH_80P80 ||  	     chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) { @@ -3528,17 +3544,16 @@ int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,  	};  	int err; -	if (vif->type != NL80211_IFTYPE_STATION || -	    !mt7615_firmware_offload(dev)) -		return -ENOTSUPP; +	if (vif->type != NL80211_IFTYPE_STATION) +		return 0; -	err = __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_ABORT, -				  &req_hdr, sizeof(req_hdr), false); +	err = mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_ABORT, &req_hdr, +				sizeof(req_hdr), false);  	if (err < 0 || !enable)  		return err; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_CONNECTED, -				   &req, sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_CONNECTED, &req, +				 sizeof(req), false);  }  #ifdef CONFIG_PM @@ -3569,9 +3584,11 @@ int mt7615_mcu_set_hif_suspend(struct mt7615_dev *dev, bool suspend)  		req.hdr.hif_type = 2;  	else if (mt76_is_usb(&dev->mt76))  		req.hdr.hif_type = 1; +	else if (mt76_is_sdio(&dev->mt76)) +		req.hdr.hif_type = 0; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_HIF_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_HIF_CTRL, &req, +				 sizeof(req), true);  }  EXPORT_SYMBOL_GPL(mt7615_mcu_set_hif_suspend); @@ -3587,6 +3604,7 @@ mt7615_mcu_set_wow_ctrl(struct mt7615_phy *phy, struct ieee80211_vif *vif,  			u8 pad[3];  		} __packed hdr;  		struct mt7615_wow_ctrl_tlv wow_ctrl_tlv; +		struct mt7615_wow_gpio_param_tlv gpio_tlv;  	} req = {  		.hdr = {  			.bss_idx = mvif->idx, @@ -3596,6 +3614,11 @@ mt7615_mcu_set_wow_ctrl(struct mt7615_phy *phy, struct ieee80211_vif *vif,  			.len = cpu_to_le16(sizeof(struct mt7615_wow_ctrl_tlv)),  			.cmd = suspend ? 1 : 2,  		}, +		.gpio_tlv = { +			.tag = cpu_to_le16(UNI_SUSPEND_WOW_GPIO_PARAM), +			.len = cpu_to_le16(sizeof(struct mt7615_wow_gpio_param_tlv)), +			.gpio_pin = 0xff, /* follow fw about GPIO pin */ +		},  	};  	if (wowlan->magic_pkt) @@ -3609,12 +3632,14 @@ mt7615_mcu_set_wow_ctrl(struct mt7615_phy *phy, struct ieee80211_vif *vif,  	}  	if (mt76_is_mmio(&dev->mt76)) -		req.wow_ctrl_tlv.wakeup_hif = 2; +		req.wow_ctrl_tlv.wakeup_hif = WOW_PCIE;  	else if (mt76_is_usb(&dev->mt76)) -		req.wow_ctrl_tlv.wakeup_hif = 1; +		req.wow_ctrl_tlv.wakeup_hif = WOW_USB; +	else if (mt76_is_sdio(&dev->mt76)) +		req.wow_ctrl_tlv.wakeup_hif = WOW_GPIO; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_SUSPEND, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_SUSPEND, &req, +				 sizeof(req), true);  }  static int @@ -3649,8 +3674,8 @@ mt7615_mcu_set_wow_pattern(struct mt7615_dev *dev,  	memcpy(ptlv->pattern, pattern->pattern, pattern->pattern_len);  	memcpy(ptlv->mask, pattern->mask, pattern->pattern_len / 8); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_UNI_CMD_SUSPEND, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_SUSPEND, +				     true);  }  static int @@ -3678,8 +3703,8 @@ mt7615_mcu_set_suspend_mode(struct mt7615_dev *dev,  		},  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_SUSPEND, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_SUSPEND, &req, +				 sizeof(req), true);  }  static int @@ -3705,8 +3730,8 @@ mt7615_mcu_set_gtk_rekey(struct mt7615_dev *dev,  		},  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_OFFLOAD, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_OFFLOAD, &req, +				 sizeof(req), true);  }  static int @@ -3731,8 +3756,8 @@ mt7615_mcu_set_arp_filter(struct mt7615_dev *dev, struct ieee80211_vif *vif,  		},  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_OFFLOAD, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_OFFLOAD, &req, +				 sizeof(req), true);  }  void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac, @@ -3744,8 +3769,6 @@ void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,  	struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config;  	int i; -	mt7615_mcu_set_bss_pm(phy->dev, vif, suspend); -  	mt7615_mcu_set_gtk_rekey(phy->dev, vif, suspend);  	mt7615_mcu_set_arp_filter(phy->dev, vif, suspend); @@ -3822,8 +3845,8 @@ int mt7615_mcu_update_gtk_rekey(struct ieee80211_hw *hw,  	memcpy(gtk_tlv->kck, key->kck, NL80211_KCK_LEN);  	memcpy(gtk_tlv->replay_ctr, key->replay_ctr, NL80211_REPLAY_CTR_LEN); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_UNI_CMD_OFFLOAD, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD, +				     true);  }  #endif /* CONFIG_PM */ @@ -3843,8 +3866,8 @@ int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,  	phy->roc_grant = false; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req, -				   sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req, +				 sizeof(req), false);  }  int mt7615_mcu_update_arp_filter(struct ieee80211_hw *hw, @@ -3890,8 +3913,8 @@ int mt7615_mcu_update_arp_filter(struct ieee80211_hw *hw,  		memcpy(addr, &info->arp_addr_list[i], sizeof(__be32));  	} -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_UNI_CMD_OFFLOAD, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD, +				     true);  }  int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, @@ -3912,8 +3935,8 @@ int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw,  	if (!mt7615_firmware_offload(dev))  		return -ENOTSUPP; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_P2P_OPPPS, -				   &req, sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_P2P_OPPPS, &req, +				 sizeof(req), false);  }  u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset) @@ -3925,8 +3948,8 @@ u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset)  		.addr = cpu_to_le32(offset),  	}; -	return __mt76_mcu_send_msg(dev, MCU_CMD_REG_READ, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(dev, MCU_CMD_REG_READ, &req, sizeof(req), +				 true);  }  EXPORT_SYMBOL_GPL(mt7615_mcu_reg_rr); @@ -3940,7 +3963,6 @@ void mt7615_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val)  		.val = cpu_to_le32(val),  	}; -	__mt76_mcu_send_msg(dev, MCU_CMD_REG_WRITE, -			    &req, sizeof(req), false); +	mt76_mcu_send_msg(dev, MCU_CMD_REG_WRITE, &req, sizeof(req), false);  }  EXPORT_SYMBOL_GPL(mt7615_mcu_reg_wr); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 7b856e9eee1e..6ef5670211d1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -275,6 +275,7 @@ enum {  	MCU_EXT_CMD_PROTECT_CTRL = 0x3e,  	MCU_EXT_CMD_DBDC_CTRL = 0x45,  	MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, +	MCU_EXT_CMD_MUAR_UPDATE = 0x48,  	MCU_EXT_CMD_BCN_OFFLOAD = 0x49,  	MCU_EXT_CMD_SET_RX_PATH = 0x4e,  	MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, @@ -477,6 +478,12 @@ struct mt7615_bss_qos_tlv {  	u8 pad[3];  } __packed; +enum { +	WOW_USB = 1, +	WOW_PCIE = 2, +	WOW_GPIO = 3, +}; +  struct mt7615_wow_ctrl_tlv {  	__le16 tag;  	__le16 len; @@ -501,6 +508,16 @@ struct mt7615_wow_ctrl_tlv {  	u8 rsv[4];  } __packed; +struct mt7615_wow_gpio_param_tlv { +	__le16 tag; +	__le16 len; +	u8 gpio_pin; +	u8 trigger_lvl; +	u8 pad[2]; +	__le32 gpio_interval; +	u8 rsv[4]; +} __packed; +  #define MT7615_WOW_MASK_MAX_LEN		16  #define MT7615_WOW_PATTEN_MAX_LEN	128  struct mt7615_wow_pattern_tlv { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index 6de492a4cf02..a7f92fa0488f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -98,9 +98,9 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)  	return IRQ_HANDLED;  } -static void mt7615_irq_tasklet(unsigned long data) +static void mt7615_irq_tasklet(struct tasklet_struct *t)  { -	struct mt7615_dev *dev = (struct mt7615_dev *)data; +	struct mt7615_dev *dev = from_tasklet(dev, t, irq_tasklet);  	u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev);  	mt76_wr(dev, MT_INT_MASK_CSR, 0); @@ -203,7 +203,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,  	dev = container_of(mdev, struct mt7615_dev, mt76);  	mt76_mmio_init(&dev->mt76, mem_base); -	tasklet_init(&dev->irq_tasklet, mt7615_irq_tasklet, (unsigned long)dev); +	tasklet_setup(&dev->irq_tasklet, mt7615_irq_tasklet);  	dev->reg_map = map;  	dev->ops = ops; @@ -240,7 +240,8 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,  	return 0;  error: -	ieee80211_free_hw(mt76_hw(dev)); +	mt76_free_device(&dev->mt76); +  	return ret;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 6a9f9187f76a..99b8abdbb08f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -11,7 +11,7 @@  #include "../mt76.h"  #include "regs.h" -#define MT7615_MAX_INTERFACES		4 +#define MT7615_MAX_INTERFACES		16  #define MT7615_MAX_WMM_SETS		4  #define MT7663_WTBL_SIZE		32  #define MT7615_WTBL_SIZE		128 @@ -106,29 +106,11 @@ struct mt7615_rate_desc {  	u8 bw;  }; -enum mt7615_wtbl_desc_type { -	MT7615_WTBL_RATE_DESC, -	MT7615_WTBL_KEY_DESC -}; - -struct mt7615_key_desc { -	enum set_key_cmd cmd; -	u32 cipher; -	s8 keyidx; -	u8 keylen; -	u8 *key; -}; - -struct mt7615_wtbl_desc { +struct mt7615_wtbl_rate_desc {  	struct list_head node; -	enum mt7615_wtbl_desc_type type; +	struct mt7615_rate_desc rate;  	struct mt7615_sta *sta; - -	union { -		struct mt7615_rate_desc rate; -		struct mt7615_key_desc key; -	};  };  struct mt7615_sta { @@ -175,8 +157,10 @@ struct mt7615_phy {  	struct ieee80211_vif *monitor_vif; +	u8 n_beacon_vif; +  	u32 rxfilter; -	u32 omac_mask; +	u64 omac_mask;  	u16 noise; @@ -254,7 +238,7 @@ struct mt7615_dev {  	struct tasklet_struct irq_tasklet;  	struct mt7615_phy phy; -	u32 omac_mask; +	u64 omac_mask;  	u16 chainmask; @@ -289,20 +273,22 @@ struct mt7615_dev {  	u8 fw_ver; -	struct work_struct wtbl_work; -	struct list_head wd_head; +	struct work_struct rate_work; +	struct list_head wrd_head;  	u32 debugfs_rf_wf;  	u32 debugfs_rf_reg; +	u32 muar_mask; +  #ifdef CONFIG_NL80211_TESTMODE  	struct {  		u32 *reg_backup;  		s16 last_freq_offset;  		u8 last_rcpi[4]; -		s8 last_ib_rssi; -		s8 last_wb_rssi; +		s8 last_ib_rssi[4]; +		s8 last_wb_rssi[4];  	} test;  #endif @@ -344,24 +330,13 @@ enum {  	HW_BSSID_1,  	HW_BSSID_2,  	HW_BSSID_3, -	HW_BSSID_MAX, +	HW_BSSID_MAX = HW_BSSID_3,  	EXT_BSSID_START = 0x10,  	EXT_BSSID_1, -	EXT_BSSID_2, -	EXT_BSSID_3, -	EXT_BSSID_4, -	EXT_BSSID_5, -	EXT_BSSID_6, -	EXT_BSSID_7, -	EXT_BSSID_8, -	EXT_BSSID_9, -	EXT_BSSID_10, -	EXT_BSSID_11, -	EXT_BSSID_12, -	EXT_BSSID_13, -	EXT_BSSID_14, -	EXT_BSSID_15, -	EXT_BSSID_END +	EXT_BSSID_15 = 0x1f, +	EXT_BSSID_MAX = EXT_BSSID_15, +	REPEATER_BSSID_START = 0x20, +	REPEATER_BSSID_MAX = 0x3f,  };  enum { @@ -452,7 +427,6 @@ bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev);  void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,  			  struct ieee80211_tx_rate *probe_rate,  			  struct ieee80211_tx_rate *rates); -int mt7615_pm_set_enable(struct mt7615_dev *dev, bool enable);  void mt7615_pm_wake_work(struct work_struct *work);  int mt7615_pm_wake(struct mt7615_dev *dev);  void mt7615_pm_power_save_sched(struct mt7615_dev *dev); @@ -542,7 +516,7 @@ static inline u8 mt7615_lmac_mapping(struct mt7615_dev *dev, u8 ac)  static inline u32 mt7615_tx_mcu_int_mask(struct mt7615_dev *dev)  { -	return MT_INT_TX_DONE(dev->mt76.q_tx[MT_TXQ_MCU]->hw_idx); +	return MT_INT_TX_DONE(dev->mt76.q_mcu[MT_MCUQ_WM]->hw_idx);  }  void mt7615_dma_reset(struct mt7615_dev *dev); @@ -568,28 +542,18 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,  			  struct ieee80211_sta *sta, int pid,  			  struct ieee80211_key_conf *key, bool beacon);  void mt7615_mac_set_timing(struct mt7615_phy *phy); +int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, +			      struct mt76_wcid *wcid, +			      struct ieee80211_key_conf *key, +			      enum set_key_cmd cmd);  int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,  			    struct ieee80211_key_conf *key,  			    enum set_key_cmd cmd); -int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, -			      struct mt76_wcid *wcid, -			      enum mt7615_cipher_type cipher, -			      int keyidx, enum set_key_cmd cmd); -void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, -				   struct mt76_wcid *wcid, -				   enum mt7615_cipher_type cipher, -				   enum set_key_cmd cmd); -int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, -			       struct mt76_wcid *wcid, -			       u8 *key, u8 keylen, -			       enum mt7615_cipher_type cipher, -			       enum set_key_cmd cmd);  void mt7615_mac_reset_work(struct work_struct *work);  u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid); -int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq); -int mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, -			int len, bool wait_resp); +int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd, +			      struct sk_buff *skb, int seq);  u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg);  int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val);  int mt7615_mcu_set_dbdc(struct mt7615_dev *dev); @@ -651,6 +615,9 @@ int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,  int mt7615_init_debugfs(struct mt7615_dev *dev);  int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq); +int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy, +				 struct ieee80211_vif *vif, +				 bool enable);  int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,  			  bool enable);  int mt7615_mcu_set_hif_suspend(struct mt7615_dev *dev, bool suspend); @@ -674,14 +641,13 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,  bool mt7663_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update);  void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,  				     struct mt76_queue_entry *e); -void mt7663_usb_sdio_wtbl_work(struct work_struct *work);  int mt7663_usb_sdio_register_device(struct mt7615_dev *dev);  int mt7663u_mcu_init(struct mt7615_dev *dev);  /* sdio */  u32 mt7663s_read_pcr(struct mt7615_dev *dev);  int mt7663s_mcu_init(struct mt7615_dev *dev); -void mt7663s_tx_work(struct work_struct *work); +void mt7663s_txrx_worker(struct mt76_worker *w);  void mt7663s_rx_work(struct work_struct *work);  void mt7663s_sdio_irq(struct sdio_func *func); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c index 06a0f8f7bc89..27fcb1374685 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c @@ -16,8 +16,15 @@ static void mt7615_init_work(struct work_struct *work)  {  	struct mt7615_dev *dev = container_of(work, struct mt7615_dev,  					      mcu_work); +	int i, ret; -	if (mt7615_mcu_init(dev)) +	ret = mt7615_mcu_init(dev); +	for (i = 0; (ret == -EAGAIN) && (i < 10); i++) { +		msleep(200); +		ret = mt7615_mcu_init(dev); +	} + +	if (ret)  		return;  	mt7615_mcu_set_eeprom(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 61623f480806..6e5db015b32c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -333,6 +333,9 @@ enum mt7615_reg_base {  #define MT_WF_RFCR_DROP_NDPA		BIT(20)  #define MT_WF_RFCR_DROP_UNWANTED_CTL	BIT(21) +#define MT_WF_RMAC_MORE(_band)		MT_WF_RMAC((_band) ? 0x124 : 0x024) +#define MT_WF_RMAC_MORE_MUAR_MODE	GENMASK(31, 30) +  #define MT_WF_RFCR1(_band)		MT_WF_RMAC((_band) ? 0x104 : 0x004)  #define MT_WF_RFCR1_DROP_ACK		BIT(4)  #define MT_WF_RFCR1_DROP_BF_POLL	BIT(5) @@ -342,6 +345,14 @@ enum mt7615_reg_base {  #define MT_CHFREQ(_band)		MT_WF_RMAC((_band) ? 0x130 : 0x030) +#define MT_WF_RMAC_MAR0			MT_WF_RMAC(0x025c) +#define MT_WF_RMAC_MAR1			MT_WF_RMAC(0x0260) +#define MT_WF_RMAC_MAR1_ADDR		GENMASK(15, 0) +#define MT_WF_RMAC_MAR1_START		BIT(16) +#define MT_WF_RMAC_MAR1_WRITE		BIT(17) +#define MT_WF_RMAC_MAR1_IDX		GENMASK(29, 24) +#define MT_WF_RMAC_MAR1_GROUP		GENMASK(31, 30) +  #define MT_WF_RMAC_MIB_TIME0		MT_WF_RMAC(0x03c4)  #define MT_WF_RMAC_MIB_RXTIME_CLR	BIT(31)  #define MT_WF_RMAC_MIB_RXTIME_EN	BIT(30) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c index 874c929d8552..347975eaba86 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c @@ -294,30 +294,6 @@ release:  	return ret;  } -static int mt7663s_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, -			   struct ieee80211_sta *sta) -{ -	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); -	struct mt76_sdio *sdio = &mdev->sdio; -	u32 pse, ple; -	int err; - -	err = mt7615_mac_sta_add(mdev, vif, sta); -	if (err < 0) -		return err; - -	/* init sched data quota */ -	pse = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); -	ple = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); - -	mutex_lock(&sdio->sched.lock); -	sdio->sched.pse_data_quota = pse; -	sdio->sched.ple_data_quota = ple; -	mutex_unlock(&sdio->sched.lock); - -	return 0; -} -  static int mt7663s_probe(struct sdio_func *func,  			 const struct sdio_device_id *id)  { @@ -329,7 +305,7 @@ static int mt7663s_probe(struct sdio_func *func,  		.tx_status_data = mt7663_usb_sdio_tx_status_data,  		.rx_skb = mt7615_queue_rx_skb,  		.sta_ps = mt7615_sta_ps, -		.sta_add = mt7663s_sta_add, +		.sta_add = mt7615_mac_sta_add,  		.sta_remove = mt7615_mac_sta_remove,  		.update_survey = mt7615_update_channel,  	}; @@ -366,14 +342,11 @@ static int mt7663s_probe(struct sdio_func *func,  	ret = mt76s_init(mdev, func, &mt7663s_ops);  	if (ret < 0) -		goto err_free; - -	INIT_WORK(&mdev->sdio.tx.xmit_work, mt7663s_tx_work); -	INIT_WORK(&mdev->sdio.rx.recv_work, mt7663s_rx_work); +		goto error;  	ret = mt7663s_hw_init(dev, func);  	if (ret) -		goto err_deinit; +		goto error;  	mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |  		    (mt76_rr(dev, MT_HW_REV) & 0xff); @@ -384,7 +357,7 @@ static int mt7663s_probe(struct sdio_func *func,  					    GFP_KERNEL);  	if (!mdev->sdio.intr_data) {  		ret = -ENOMEM; -		goto err_deinit; +		goto error;  	}  	for (i = 0; i < ARRAY_SIZE(mdev->sdio.xmit_buf); i++) { @@ -393,23 +366,29 @@ static int mt7663s_probe(struct sdio_func *func,  						      GFP_KERNEL);  		if (!mdev->sdio.xmit_buf[i]) {  			ret = -ENOMEM; -			goto err_deinit; +			goto error;  		}  	}  	ret = mt76s_alloc_queues(&dev->mt76);  	if (ret) -		goto err_deinit; +		goto error; + +	ret = mt76_worker_setup(mt76_hw(dev), &mdev->sdio.txrx_worker, +				mt7663s_txrx_worker, "sdio-txrx"); +	if (ret) +		goto error; + +	sched_set_fifo_low(mdev->sdio.txrx_worker.task);  	ret = mt7663_usb_sdio_register_device(dev);  	if (ret) -		goto err_deinit; +		goto error;  	return 0; -err_deinit: +error:  	mt76s_deinit(&dev->mt76); -err_free:  	mt76_free_device(&dev->mt76);  	return ret; @@ -432,6 +411,7 @@ static int mt7663s_suspend(struct device *dev)  {  	struct sdio_func *func = dev_to_sdio_func(dev);  	struct mt7615_dev *mdev = sdio_get_drvdata(func); +	int err;  	if (!test_bit(MT76_STATE_SUSPEND, &mdev->mphy.state) &&  	    mt7615_firmware_offload(mdev)) { @@ -444,9 +424,20 @@ static int mt7663s_suspend(struct device *dev)  	sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); -	mt76s_stop_txrx(&mdev->mt76); +	err = mt7615_mcu_set_fw_ctrl(mdev); +	if (err) +		return err; -	return mt7615_mcu_set_fw_ctrl(mdev); +	mt76_worker_disable(&mdev->mt76.sdio.txrx_worker); +	mt76_worker_disable(&mdev->mt76.sdio.status_worker); +	mt76_worker_disable(&mdev->mt76.sdio.net_worker); + +	cancel_work_sync(&mdev->mt76.sdio.stat_work); +	clear_bit(MT76_READING_STATS, &mdev->mphy.state); + +	mt76_tx_status_check(&mdev->mt76, NULL, true); + +	return 0;  }  static int mt7663s_resume(struct device *dev) @@ -455,6 +446,10 @@ static int mt7663s_resume(struct device *dev)  	struct mt7615_dev *mdev = sdio_get_drvdata(func);  	int err; +	mt76_worker_enable(&mdev->mt76.sdio.txrx_worker); +	mt76_worker_enable(&mdev->mt76.sdio.status_worker); +	mt76_worker_enable(&mdev->mt76.sdio.net_worker); +  	err = mt7615_mcu_set_drv_ctrl(mdev);  	if (err)  		return err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c index 38670c00380c..17fe4187d1de 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c @@ -19,46 +19,34 @@  static int mt7663s_mcu_init_sched(struct mt7615_dev *dev)  {  	struct mt76_sdio *sdio = &dev->mt76.sdio; -	u32 pse0, ple, pse1, txdwcnt; - -	pse0 = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); -	pse1 = mt76_get_field(dev, MT_PSE_PG_HIF1_GROUP, MT_HIF1_MIN_QUOTA); -	ple = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); +	u32 txdwcnt; + +	sdio->sched.pse_data_quota = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP, +						    MT_HIF0_MIN_QUOTA); +	sdio->sched.pse_mcu_quota = mt76_get_field(dev, MT_PSE_PG_HIF1_GROUP, +						   MT_HIF1_MIN_QUOTA); +	sdio->sched.ple_data_quota = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP, +						    MT_HIF0_MIN_QUOTA);  	txdwcnt = mt76_get_field(dev, MT_PP_TXDWCNT,  				 MT_PP_TXDWCNT_TX1_ADD_DW_CNT); - -	mutex_lock(&sdio->sched.lock); - -	sdio->sched.pse_data_quota = pse0; -	sdio->sched.ple_data_quota = ple; -	sdio->sched.pse_mcu_quota = pse1;  	sdio->sched.deficit = txdwcnt << 2; -	mutex_unlock(&sdio->sched.lock); -  	return 0;  }  static int  mt7663s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, -			 int cmd, bool wait_resp) +			 int cmd, int *seq)  {  	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); -	int ret, seq; - -	mutex_lock(&mdev->mcu.mutex); +	int ret; -	mt7615_mcu_fill_msg(dev, skb, cmd, &seq); -	ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0); +	mt7615_mcu_fill_msg(dev, skb, cmd, seq); +	ret = mt76_tx_queue_skb_raw(dev, mdev->q_mcu[MT_MCUQ_WM], skb, 0);  	if (ret) -		goto out; - -	mt76_queue_kick(dev, mdev->q_tx[MT_TXQ_MCU]); -	if (wait_resp) -		ret = mt7615_mcu_wait_response(dev, cmd, seq); +		return ret; -out: -	mutex_unlock(&mdev->mcu.mutex); +	mt76_queue_kick(dev, mdev->q_mcu[MT_MCUQ_WM]);  	return ret;  } @@ -127,7 +115,7 @@ int mt7663s_mcu_init(struct mt7615_dev *dev)  		.headroom = sizeof(struct mt7615_mcu_txd),  		.tailroom = MT_USB_TAIL_SIZE,  		.mcu_skb_send_msg = mt7663s_mcu_send_message, -		.mcu_send_msg = mt7615_mcu_msg_send, +		.mcu_parse_response = mt7615_mcu_parse_response,  		.mcu_restart = mt7615_mcu_restart,  		.mcu_rr = mt7615_mcu_reg_rr,  		.mcu_wr = mt7615_mcu_reg_wr, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c index 2486cda3243b..13d77f8fca86 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c @@ -46,11 +46,9 @@ static int mt7663s_refill_sched_quota(struct mt76_dev *dev, u32 *data)  	if (!pse_data_quota && !ple_data_quota && !pse_mcu_quota)  		return 0; -	mutex_lock(&sdio->sched.lock);  	sdio->sched.pse_mcu_quota += pse_mcu_quota;  	sdio->sched.pse_data_quota += pse_data_quota;  	sdio->sched.ple_data_quota += ple_data_quota; -	mutex_unlock(&sdio->sched.lock);  	return pse_data_quota + ple_data_quota + pse_mcu_quota;  } @@ -105,10 +103,7 @@ static int mt7663s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,  	buf = page_address(page); -	sdio_claim_host(sdio->func);  	err = sdio_readsb(sdio->func, buf, MCR_WRDR(qid), len); -	sdio_release_host(sdio->func); -  	if (err < 0) {  		dev_err(dev->dev, "sdio read data failed:%d\n", err);  		__free_pages(page, order); @@ -138,19 +133,52 @@ static int mt7663s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,  	return i;  } -static int mt7663s_tx_pick_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid, -				 int buf_sz, int *pse_size, int *ple_size) +static int mt7663s_rx_handler(struct mt76_dev *dev) +{ +	struct mt76_sdio *sdio = &dev->sdio; +	struct mt76s_intr *intr = sdio->intr_data; +	int nframes = 0, ret; + +	ret = sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(*intr)); +	if (ret < 0) +		return ret; + +	trace_dev_irq(dev, intr->isr, 0); + +	if (intr->isr & WHIER_RX0_DONE_INT_EN) { +		ret = mt7663s_rx_run_queue(dev, 0, intr); +		if (ret > 0) { +			mt76_worker_schedule(&sdio->net_worker); +			nframes += ret; +		} +	} + +	if (intr->isr & WHIER_RX1_DONE_INT_EN) { +		ret = mt7663s_rx_run_queue(dev, 1, intr); +		if (ret > 0) { +			mt76_worker_schedule(&sdio->net_worker); +			nframes += ret; +		} +	} + +	nframes += !!mt7663s_refill_sched_quota(dev, intr->tx.wtqcr); + +	return nframes; +} + +static int mt7663s_tx_pick_quota(struct mt76_sdio *sdio, bool mcu, int buf_sz, +				 int *pse_size, int *ple_size)  {  	int pse_sz;  	pse_sz = DIV_ROUND_UP(buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ); -	if (qid == MT_TXQ_MCU) { +	if (mcu) {  		if (sdio->sched.pse_mcu_quota < *pse_size + pse_sz)  			return -EBUSY;  	} else {  		if (sdio->sched.pse_data_quota < *pse_size + pse_sz || -		    sdio->sched.ple_data_quota < *ple_size) +		    sdio->sched.ple_data_quota < *ple_size + 1)  			return -EBUSY;  		*ple_size = *ple_size + 1; @@ -160,17 +188,15 @@ static int mt7663s_tx_pick_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid,  	return 0;  } -static void mt7663s_tx_update_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid, +static void mt7663s_tx_update_quota(struct mt76_sdio *sdio, bool mcu,  				    int pse_size, int ple_size)  { -	mutex_lock(&sdio->sched.lock); -	if (qid == MT_TXQ_MCU) { +	if (mcu) {  		sdio->sched.pse_mcu_quota -= pse_size;  	} else {  		sdio->sched.pse_data_quota -= pse_size;  		sdio->sched.ple_data_quota -= ple_size;  	} -	mutex_unlock(&sdio->sched.lock);  }  static int __mt7663s_xmit_queue(struct mt76_dev *dev, u8 *data, int len) @@ -181,22 +207,20 @@ static int __mt7663s_xmit_queue(struct mt76_dev *dev, u8 *data, int len)  	if (len > sdio->func->cur_blksize)  		len = roundup(len, sdio->func->cur_blksize); -	sdio_claim_host(sdio->func);  	err = sdio_writesb(sdio->func, MCR_WTDR1, data, len); -	sdio_release_host(sdio->func); -  	if (err)  		dev_err(dev->dev, "sdio write failed: %d\n", err);  	return err;  } -static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid) +static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)  { -	int err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0; -	struct mt76_queue *q = dev->q_tx[qid]; +	int qid, err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0; +	bool mcu = q == dev->q_mcu[MT_MCUQ_WM];  	struct mt76_sdio *sdio = &dev->sdio; +	qid = mcu ? ARRAY_SIZE(sdio->xmit_buf) - 1 : q->qid;  	while (q->first != q->head) {  		struct mt76_queue_entry *e = &q->entry[q->first];  		struct sk_buff *iter; @@ -214,7 +238,7 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid)  		if (len + e->skb->len + 4 > MT76S_XMIT_BUF_SZ)  			break; -		if (mt7663s_tx_pick_quota(sdio, qid, e->buf_sz, &pse_sz, +		if (mt7663s_tx_pick_quota(sdio, mcu, e->buf_sz, &pse_sz,  					  &ple_sz))  			break; @@ -240,78 +264,44 @@ next:  		if (err)  			return err;  	} -	mt7663s_tx_update_quota(sdio, qid, pse_sz, ple_sz); +	mt7663s_tx_update_quota(sdio, mcu, pse_sz, ple_sz); -	return nframes; -} - -void mt7663s_tx_work(struct work_struct *work) -{ -	struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, -					      tx.xmit_work); -	struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); -	int i, nframes = 0; +	mt76_worker_schedule(&sdio->status_worker); -	for (i = 0; i < MT_TXQ_MCU_WA; i++) { -		int ret; - -		ret = mt7663s_tx_run_queue(dev, i); -		if (ret < 0) -			break; - -		nframes += ret; -	} -	if (nframes) -		queue_work(sdio->txrx_wq, &sdio->tx.xmit_work); - -	queue_work(sdio->txrx_wq, &sdio->tx.status_work); +	return nframes;  } -void mt7663s_rx_work(struct work_struct *work) +void mt7663s_txrx_worker(struct mt76_worker *w)  { -	struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, -					      rx.recv_work); +	struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, +					      txrx_worker);  	struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); -	struct mt76s_intr *intr = sdio->intr_data; -	int nframes = 0, ret; +	int i, nframes, ret;  	/* disable interrupt */  	sdio_claim_host(sdio->func);  	sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL); -	ret = sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(*intr)); -	sdio_release_host(sdio->func); - -	if (ret < 0) -		goto out; -	trace_dev_irq(dev, intr->isr, 0); +	do { +		nframes = 0; -	if (intr->isr & WHIER_RX0_DONE_INT_EN) { -		ret = mt7663s_rx_run_queue(dev, 0, intr); -		if (ret > 0) { -			queue_work(sdio->txrx_wq, &sdio->rx.net_work); -			nframes += ret; +		/* tx */ +		for (i = 0; i <= MT_TXQ_PSD; i++) { +			ret = mt7663s_tx_run_queue(dev, dev->phy.q_tx[i]); +			if (ret > 0) +				nframes += ret;  		} -	} - -	if (intr->isr & WHIER_RX1_DONE_INT_EN) { -		ret = mt7663s_rx_run_queue(dev, 1, intr); -		if (ret > 0) { -			queue_work(sdio->txrx_wq, &sdio->rx.net_work); +		ret = mt7663s_tx_run_queue(dev, dev->q_mcu[MT_MCUQ_WM]); +		if (ret > 0)  			nframes += ret; -		} -	} -	if (mt7663s_refill_sched_quota(dev, intr->tx.wtqcr)) -		queue_work(sdio->txrx_wq, &sdio->tx.xmit_work); +		/* rx */ +		ret = mt7663s_rx_handler(dev); +		if (ret > 0) +			nframes += ret; +	} while (nframes > 0); -	if (nframes) { -		queue_work(sdio->txrx_wq, &sdio->rx.recv_work); -		return; -	} -out:  	/* enable interrupt */ -	sdio_claim_host(sdio->func);  	sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);  	sdio_release_host(sdio->func);  } @@ -324,5 +314,5 @@ void mt7663s_sdio_irq(struct sdio_func *func)  	if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.phy.state))  		return; -	queue_work(sdio->txrx_wq, &sdio->rx.recv_work); +	mt76_worker_schedule(&sdio->txrx_worker);  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c index e4dc62314bae..8fc97a52411a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/testmode.c @@ -90,8 +90,8 @@ mt7615_tm_set_tx_power(struct mt7615_phy *phy)  			data[ret - MT_EE_NIC_CONF_0] = tx_power[i];  	} -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_SET_TX_POWER_CTRL, false); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_SET_TX_POWER_CTRL, false);  }  static void @@ -335,9 +335,7 @@ mt7615_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)  	if (!rx)  		return -ENOMEM; -	if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, dev->test.last_freq_offset) || -	    nla_put_s32(msg, MT76_TM_RX_ATTR_IB_RSSI, dev->test.last_ib_rssi) || -	    nla_put_s32(msg, MT76_TM_RX_ATTR_WB_RSSI, dev->test.last_wb_rssi)) +	if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, dev->test.last_freq_offset))  		return -ENOMEM;  	rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RCPI); @@ -350,6 +348,26 @@ mt7615_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)  	nla_nest_end(msg, rssi); +	rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_IB_RSSI); +	if (!rssi) +		return -ENOMEM; + +	for (i = 0; i < ARRAY_SIZE(dev->test.last_ib_rssi); i++) +		if (nla_put_s8(msg, i, dev->test.last_ib_rssi[i])) +			return -ENOMEM; + +	nla_nest_end(msg, rssi); + +	rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_WB_RSSI); +	if (!rssi) +		return -ENOMEM; + +	for (i = 0; i < ARRAY_SIZE(dev->test.last_wb_rssi); i++) +		if (nla_put_s8(msg, i, dev->test.last_wb_rssi[i])) +			return -ENOMEM; + +	nla_nest_end(msg, rssi); +  	nla_nest_end(msg, rx);  	return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index f0ad83af9e00..a60cfa345521 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -126,21 +126,20 @@ static int mt7663u_probe(struct usb_interface *usb_intf,  alloc_queues:  	ret = mt76u_alloc_mcu_queue(&dev->mt76);  	if (ret) -		goto error_free_q; +		goto error;  	ret = mt76u_alloc_queues(&dev->mt76);  	if (ret) -		goto error_free_q; +		goto error;  	ret = mt7663_usb_sdio_register_device(dev);  	if (ret) -		goto error_free_q; +		goto error;  	return 0; -error_free_q: -	mt76u_queues_deinit(&dev->mt76);  error: +	mt76u_queues_deinit(&dev->mt76);  	usb_set_intfdata(usb_intf, NULL);  	usb_put_dev(interface_to_usbdev(usb_intf)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c index 4d8be366af31..c55698f9c49a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c @@ -15,14 +15,12 @@  static int  mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, -			 int cmd, bool wait_resp) +			 int cmd, int *seq)  {  	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); -	int ret, seq, ep, len, pad; +	int ret, ep, len, pad; -	mutex_lock(&mdev->mcu.mutex); - -	mt7615_mcu_fill_msg(dev, skb, cmd, &seq); +	mt7615_mcu_fill_msg(dev, skb, cmd, seq);  	if (cmd != MCU_CMD_FW_SCATTER)  		ep = MT_EP_OUT_INBAND_CMD;  	else @@ -37,14 +35,8 @@ mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,  	ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,  			     1000, ep); -	if (ret < 0) -		goto out; - -	if (wait_resp) -		ret = mt7615_mcu_wait_response(dev, cmd, seq);  out: -	mutex_unlock(&mdev->mcu.mutex);  	dev_kfree_skb(skb);  	return ret; @@ -56,7 +48,7 @@ int mt7663u_mcu_init(struct mt7615_dev *dev)  		.headroom = MT_USB_HDR_SIZE + sizeof(struct mt7615_mcu_txd),  		.tailroom = MT_USB_TAIL_SIZE,  		.mcu_skb_send_msg = mt7663u_mcu_send_message, -		.mcu_send_msg = mt7615_mcu_msg_send, +		.mcu_parse_response = mt7615_mcu_parse_response,  		.mcu_restart = mt7615_mcu_restart,  	};  	int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c index 3b29a6d3dc64..203256862dfd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c @@ -61,12 +61,11 @@ mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid,  	skb_push(skb, MT_USB_TXD_SIZE);  } -static int -mt7663_usb_sdio_set_rates(struct mt7615_dev *dev, -			  struct mt7615_wtbl_desc *wd) +static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev, +				     struct mt7615_wtbl_rate_desc *wrd)  { -	struct mt7615_rate_desc *rate = &wd->rate; -	struct mt7615_sta *sta = wd->sta; +	struct mt7615_rate_desc *rate = &wrd->rate; +	struct mt7615_sta *sta = wrd->sta;  	u32 w5, w27, addr, val;  	lockdep_assert_held(&dev->mt76.mutex); @@ -132,86 +131,30 @@ mt7663_usb_sdio_set_rates(struct mt7615_dev *dev,  	return 0;  } -static int -mt7663_usb_sdio_set_key(struct mt7615_dev *dev, -			struct mt7615_wtbl_desc *wd) +static void mt7663_usb_sdio_rate_work(struct work_struct *work)  { -	struct mt7615_key_desc *key = &wd->key; -	struct mt7615_sta *sta = wd->sta; -	enum mt7615_cipher_type cipher; -	struct mt76_wcid *wcid; -	int err; - -	lockdep_assert_held(&dev->mt76.mutex); - -	if (!sta) { -		err = -EINVAL; -		goto out; -	} - -	cipher = mt7615_mac_get_cipher(key->cipher); -	if (cipher == MT_CIPHER_NONE) { -		err = -EOPNOTSUPP; -		goto out; -	} - -	wcid = &wd->sta->wcid; - -	mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, key->cmd); -	err = mt7615_mac_wtbl_update_key(dev, wcid, key->key, key->keylen, -					 cipher, key->cmd); -	if (err < 0) -		goto out; - -	err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, -					key->cmd); -	if (err < 0) -		goto out; - -	if (key->cmd == SET_KEY) -		wcid->cipher |= BIT(cipher); -	else -		wcid->cipher &= ~BIT(cipher); -out: -	kfree(key->key); - -	return err; -} - -void mt7663_usb_sdio_wtbl_work(struct work_struct *work) -{ -	struct mt7615_wtbl_desc *wd, *wd_next; -	struct list_head wd_list; +	struct mt7615_wtbl_rate_desc *wrd, *wrd_next; +	struct list_head wrd_list;  	struct mt7615_dev *dev;  	dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev, -						wtbl_work); +						rate_work); -	INIT_LIST_HEAD(&wd_list); +	INIT_LIST_HEAD(&wrd_list);  	spin_lock_bh(&dev->mt76.lock); -	list_splice_init(&dev->wd_head, &wd_list); +	list_splice_init(&dev->wrd_head, &wrd_list);  	spin_unlock_bh(&dev->mt76.lock); -	list_for_each_entry_safe(wd, wd_next, &wd_list, node) { -		list_del(&wd->node); +	list_for_each_entry_safe(wrd, wrd_next, &wrd_list, node) { +		list_del(&wrd->node);  		mt7615_mutex_acquire(dev); - -		switch (wd->type) { -		case MT7615_WTBL_RATE_DESC: -			mt7663_usb_sdio_set_rates(dev, wd); -			break; -		case MT7615_WTBL_KEY_DESC: -			mt7663_usb_sdio_set_key(dev, wd); -			break; -		} - +		mt7663_usb_sdio_set_rates(dev, wrd);  		mt7615_mutex_release(dev); -		kfree(wd); +		kfree(wrd);  	}  } -EXPORT_SYMBOL_GPL(mt7663_usb_sdio_wtbl_work);  bool mt7663_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)  { @@ -357,8 +300,8 @@ int mt7663_usb_sdio_register_device(struct mt7615_dev *dev)  	struct ieee80211_hw *hw = mt76_hw(dev);  	int err; -	INIT_WORK(&dev->wtbl_work, mt7663_usb_sdio_wtbl_work); -	INIT_LIST_HEAD(&dev->wd_head); +	INIT_WORK(&dev->rate_work, mt7663_usb_sdio_rate_work); +	INIT_LIST_HEAD(&dev->wrd_head);  	mt7615_init_device(dev);  	err = mt7663_usb_sdio_init_hardware(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index 9087607b621e..dd66fd12a2e6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -52,15 +52,15 @@ static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)  	mt76x02_eeprom_parse_hw_cap(dev);  	dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n", -		dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz); +		dev->mphy.cap.has_2ghz, dev->mphy.cap.has_5ghz);  	if (dev->no_2ghz) { -		dev->mt76.cap.has_2ghz = false; +		dev->mphy.cap.has_2ghz = false;  		dev_dbg(dev->mt76.dev, "mask out 2GHz support\n");  	}  	if (is_mt7630(dev)) { -		dev->mt76.cap.has_5ghz = false; +		dev->mphy.cap.has_5ghz = false;  		dev_dbg(dev->mt76.dev, "mask out 5GHz support\n");  	} @@ -342,10 +342,10 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev)  	dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n",  		 version, fae); -	memcpy(dev->mt76.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR, +	memcpy(dev->mphy.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,  	       ETH_ALEN); -	mt76_eeprom_override(&dev->mt76); -	mt76x02_mac_setaddr(dev, dev->mt76.macaddr); +	mt76_eeprom_override(&dev->mphy); +	mt76x02_mac_setaddr(dev, dev->mphy.macaddr);  	mt76x0_set_chip_cap(dev);  	mt76x0_set_freq_offset(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index d78866bf41ba..0bac39bf3b66 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -245,7 +245,7 @@ int mt76x0_register_device(struct mt76x02_dev *dev)  	if (ret)  		return ret; -	if (dev->mt76.cap.has_5ghz) { +	if (dev->mphy.cap.has_5ghz) {  		struct ieee80211_supported_band *sband;  		sband = &dev->mphy.sband_5g.sband; @@ -253,7 +253,7 @@ int mt76x0_register_device(struct mt76x02_dev *dev)  		mt76x0_init_txpower(dev, sband);  	} -	if (dev->mt76.cap.has_2ghz) +	if (dev->mphy.cap.has_2ghz)  		mt76x0_init_txpower(dev, &dev->mphy.sband_2g.sband);  	mt76x02_init_debugfs(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index dda11c704aba..b87d8e136cb9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -194,7 +194,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	return 0;  error: -	ieee80211_free_hw(mt76_hw(dev)); +	mt76_free_device(&dev->mt76); +  	return ret;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c index 007c762c6db1..f0962507f72f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c @@ -117,6 +117,7 @@ int mt76x0e_mcu_init(struct mt76x02_dev *dev)  {  	static const struct mt76_mcu_ops mt76x0e_mcu_ops = {  		.mcu_send_msg = mt76x02_mcu_msg_send, +		.mcu_parse_response = mt76x02_mcu_parse_response,  	};  	int err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 3de33aadf794..e91c314cdfac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -447,11 +447,11 @@ static void mt76x0_phy_ant_select(struct mt76x02_dev *dev)  		else  			coex3 |= BIT(4);  		coex3 |= BIT(3); -		if (dev->mt76.cap.has_2ghz) +		if (dev->mphy.cap.has_2ghz)  			wlan |= BIT(6);  	} else {  		/* sigle antenna mode */ -		if (dev->mt76.cap.has_5ghz) { +		if (dev->mphy.cap.has_5ghz) {  			coex3 |= BIT(3) | BIT(4);  		} else {  			wlan |= BIT(6); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index ce6b286a8152..b12cb17cb43d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -277,6 +277,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,  err:  	usb_set_intfdata(usb_intf, NULL);  	usb_put_dev(interface_to_usbdev(usb_intf)); +	mt76u_queues_deinit(&dev->mt76);  	mt76_free_device(&dev->mt76);  	return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index b29cd39dc176..a601350531cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -609,10 +609,11 @@ static void mt76x02_dfs_check_event_window(struct mt76x02_dev *dev)  	}  } -static void mt76x02_dfs_tasklet(unsigned long arg) +static void mt76x02_dfs_tasklet(struct tasklet_struct *t)  { -	struct mt76x02_dev *dev = (struct mt76x02_dev *)arg; -	struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; +	struct mt76x02_dfs_pattern_detector *dfs_pd = from_tasklet(dfs_pd, t, +								   dfs_tasklet); +	struct mt76x02_dev *dev = container_of(dfs_pd, typeof(*dev), dfs_pd);  	u32 engine_mask;  	int i; @@ -860,8 +861,7 @@ void mt76x02_dfs_init_detector(struct mt76x02_dev *dev)  	INIT_LIST_HEAD(&dfs_pd->seq_pool);  	dev->mt76.region = NL80211_DFS_UNSET;  	dfs_pd->last_sw_check = jiffies; -	tasklet_init(&dfs_pd->dfs_tasklet, mt76x02_dfs_tasklet, -		     (unsigned long)dev); +	tasklet_setup(&dfs_pd->dfs_tasklet, mt76x02_dfs_tasklet);  }  static void diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c index c54c50fd639a..0acabba2d1a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c @@ -75,14 +75,14 @@ void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev)  	switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) {  	case BOARD_TYPE_5GHZ: -		dev->mt76.cap.has_5ghz = true; +		dev->mphy.cap.has_5ghz = true;  		break;  	case BOARD_TYPE_2GHZ: -		dev->mt76.cap.has_2ghz = true; +		dev->mphy.cap.has_2ghz = true;  		break;  	default: -		dev->mt76.cap.has_2ghz = true; -		dev->mt76.cap.has_5ghz = true; +		dev->mphy.cap.has_2ghz = true; +		dev->mphy.cap.has_5ghz = true;  		break;  	}  } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index da6d3f51f6d4..16b40a73fd1f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -727,24 +727,24 @@ void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr)  	static const u8 null_addr[ETH_ALEN] = {};  	int i; -	ether_addr_copy(dev->mt76.macaddr, addr); +	ether_addr_copy(dev->mphy.macaddr, addr); -	if (!is_valid_ether_addr(dev->mt76.macaddr)) { -		eth_random_addr(dev->mt76.macaddr); +	if (!is_valid_ether_addr(dev->mphy.macaddr)) { +		eth_random_addr(dev->mphy.macaddr);  		dev_info(dev->mt76.dev,  			 "Invalid MAC address, using random address %pM\n", -			 dev->mt76.macaddr); +			 dev->mphy.macaddr);  	} -	mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->mt76.macaddr)); +	mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->mphy.macaddr));  	mt76_wr(dev, MT_MAC_ADDR_DW1, -		get_unaligned_le16(dev->mt76.macaddr + 4) | +		get_unaligned_le16(dev->mphy.macaddr + 4) |  		FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));  	mt76_wr(dev, MT_MAC_BSSID_DW0, -		get_unaligned_le32(dev->mt76.macaddr)); +		get_unaligned_le32(dev->mphy.macaddr));  	mt76_wr(dev, MT_MAC_BSSID_DW1, -		get_unaligned_le16(dev->mt76.macaddr + 4) | +		get_unaligned_le16(dev->mphy.macaddr + 4) |  		FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 APs + 8 STAs */  		MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT);  	/* enable 7 additional beacon slots and control them with bypass mask */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index 267058086a90..4aa5c36afeaf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -10,6 +10,28 @@  #include "mt76x02_mcu.h" +int mt76x02_mcu_parse_response(struct mt76_dev *mdev, int cmd, +			       struct sk_buff *skb, int seq) +{ +	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); +	u32 *rxfce; + +	if (!skb) { +		dev_err(mdev->dev, +			"MCU message %d (seq %d) timed out\n", cmd, +			seq); +		dev->mcu_timeout = 1; +		return -ETIMEDOUT; +	} + +	rxfce = (u32 *)skb->cb; +	if (seq != FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, *rxfce)) +		return -EAGAIN; + +	return 0; +} +EXPORT_SYMBOL_GPL(mt76x02_mcu_parse_response); +  int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,  			 int len, bool wait_resp)  { @@ -39,31 +61,15 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,  		  FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) |  		  FIELD_PREP(MT_MCU_MSG_LEN, skb->len); -	ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, tx_info); +	ret = mt76_tx_queue_skb_raw(dev, mdev->q_mcu[MT_MCUQ_WM], skb, tx_info);  	if (ret)  		goto out;  	while (wait_resp) { -		u32 *rxfce; -		bool check_seq = false; -  		skb = mt76_mcu_get_response(&dev->mt76, expires); -		if (!skb) { -			dev_err(mdev->dev, -				"MCU message %d (seq %d) timed out\n", cmd, -				seq); -			ret = -ETIMEDOUT; -			dev->mcu_timeout = 1; -			break; -		} - -		rxfce = (u32 *)skb->cb; - -		if (seq == FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, *rxfce)) -			check_seq = true; - +		ret = mt76x02_mcu_parse_response(mdev, cmd, skb, seq);  		dev_kfree_skb(skb); -		if (check_seq) +		if (ret != -EAGAIN)  			break;  	} @@ -89,7 +95,8 @@ int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func,  	if (func != Q_SELECT)  		wait = true; -	return mt76_mcu_send_msg(dev, CMD_FUN_SET_OP, &msg, sizeof(msg), wait); +	return mt76_mcu_send_msg(&dev->mt76, CMD_FUN_SET_OP, &msg, +				 sizeof(msg), wait);  }  EXPORT_SYMBOL_GPL(mt76x02_mcu_function_select); @@ -103,8 +110,8 @@ int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on)  		.level = cpu_to_le32(0),  	}; -	return mt76_mcu_send_msg(dev, CMD_POWER_SAVING_OP, &msg, sizeof(msg), -				 false); +	return mt76_mcu_send_msg(&dev->mt76, CMD_POWER_SAVING_OP, &msg, +				 sizeof(msg), false);  }  EXPORT_SYMBOL_GPL(mt76x02_mcu_set_radio_state); @@ -123,8 +130,8 @@ int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param)  	if (is_mt76x2e)  		mt76_rmw(dev, MT_MCU_COM_REG0, BIT(31), 0); -	ret = mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg), -				true); +	ret = mt76_mcu_send_msg(&dev->mt76, CMD_CALIBRATION_OP, &msg, +				sizeof(msg), true);  	if (ret)  		return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h index 5fba1266c648..e187ed52968e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h @@ -89,6 +89,8 @@ int mt76x02_mcu_cleanup(struct mt76x02_dev *dev);  int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param);  int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,  			 int len, bool wait_resp); +int mt76x02_mcu_parse_response(struct mt76_dev *mdev, int cmd, +			       struct sk_buff *skb, int seq);  int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func,  				u32 val);  int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index cf68731bd094..e7e87311d355 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -11,10 +11,11 @@  #include "mt76x02_mcu.h"  #include "trace.h" -static void mt76x02_pre_tbtt_tasklet(unsigned long arg) +static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)  { -	struct mt76x02_dev *dev = (struct mt76x02_dev *)arg; -	struct mt76_queue *q = dev->mt76.q_tx[MT_TXQ_PSD]; +	struct mt76x02_dev *dev = from_tasklet(dev, t, mt76.pre_tbtt_tasklet); +	struct mt76_dev *mdev = &dev->mt76; +	struct mt76_queue *q = dev->mphy.q_tx[MT_TXQ_PSD];  	struct beacon_bc_data data = {};  	struct sk_buff *skb;  	int i; @@ -35,9 +36,9 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)  	mt76_wr(dev, MT_BCN_BYPASS_MASK,  		0xff00 | ~(0xff00 >> dev->beacon_data_count)); -	mt76_csa_check(&dev->mt76); +	mt76_csa_check(mdev); -	if (dev->mt76.csa_complete) +	if (mdev->csa_complete)  		return;  	mt76x02_enqueue_buffered_bc(dev, &data, 8); @@ -58,8 +59,7 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)  		struct ieee80211_vif *vif = info->control.vif;  		struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; -		mt76_tx_queue_skb(dev, MT_TXQ_PSD, skb, &mvif->group_wcid, -				  NULL); +		mt76_tx_queue_skb(dev, q, skb, &mvif->group_wcid, NULL);  	}  	spin_unlock_bh(&q->lock);  } @@ -104,27 +104,6 @@ void mt76x02e_init_beacon_config(struct mt76x02_dev *dev)  EXPORT_SYMBOL_GPL(mt76x02e_init_beacon_config);  static int -mt76x02_init_tx_queue(struct mt76x02_dev *dev, int qid, int idx, int n_desc) -{ -	struct mt76_queue *hwq; -	int err; - -	hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); -	if (!hwq) -		return -ENOMEM; - -	err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); -	if (err < 0) -		return err; - -	dev->mt76.q_tx[qid] = hwq; - -	mt76x02_irq_enable(dev, MT_INT_TX_DONE(idx)); - -	return 0; -} - -static int  mt76x02_init_rx_queue(struct mt76x02_dev *dev, struct mt76_queue *q,  		      int idx, int n_desc, int bufsize)  { @@ -169,14 +148,16 @@ static int mt76x02_poll_tx(struct napi_struct *napi, int budget)  	mt76x02_mac_poll_tx_status(dev, false); -	for (i = MT_TXQ_MCU; i >= 0; i--) -		mt76_queue_tx_cleanup(dev, i, false); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); +	for (i = MT_TXQ_PSD; i >= 0; i--) +		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);  	if (napi_complete_done(napi, 0))  		mt76x02_irq_enable(dev, MT_INT_TX_DONE_ALL); -	for (i = MT_TXQ_MCU; i >= 0; i--) -		mt76_queue_tx_cleanup(dev, i, false); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); +	for (i = MT_TXQ_PSD; i >= 0; i--) +		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);  	mt76_worker_schedule(&dev->mt76.tx_worker); @@ -198,8 +179,7 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)  		return -ENOMEM;  	dev->mt76.tx_worker.fn = mt76x02_tx_worker; -	tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet, -		     (unsigned long)dev); +	tasklet_setup(&dev->mt76.pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet);  	spin_lock_init(&dev->txstatus_fifo_lock);  	kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size); @@ -209,22 +189,31 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)  	mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);  	for (i = 0; i < IEEE80211_NUM_ACS; i++) { -		ret = mt76x02_init_tx_queue(dev, i, mt76_ac_to_hwq(i), -					    MT76x02_TX_RING_SIZE); +		ret = mt76_init_tx_queue(&dev->mphy, i, mt76_ac_to_hwq(i), +					 MT76x02_TX_RING_SIZE, +					 MT_TX_RING_BASE);  		if (ret)  			return ret;  	} -	ret = mt76x02_init_tx_queue(dev, MT_TXQ_PSD, -				    MT_TX_HW_QUEUE_MGMT, MT76x02_PSD_RING_SIZE); +	ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, +				 MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret; -	ret = mt76x02_init_tx_queue(dev, MT_TXQ_MCU, -				    MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE); +	ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT_TX_HW_QUEUE_MCU, +				  MT_MCU_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret; +	mt76x02_irq_enable(dev, +			   MT_INT_TX_DONE(IEEE80211_AC_VO) | +			   MT_INT_TX_DONE(IEEE80211_AC_VI) | +			   MT_INT_TX_DONE(IEEE80211_AC_BE) | +			   MT_INT_TX_DONE(IEEE80211_AC_BK) | +			   MT_INT_TX_DONE(MT_TX_HW_QUEUE_MGMT) | +			   MT_INT_TX_DONE(MT_TX_HW_QUEUE_MCU)); +  	ret = mt76x02_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,  				    MT_MCU_RING_SIZE, MT_RX_BUF_SIZE);  	if (ret) @@ -292,7 +281,7 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)  		if (dev->mt76.csa_complete)  			mt76_csa_finish(&dev->mt76);  		else -			mt76_queue_kick(dev, dev->mt76.q_tx[MT_TXQ_PSD]); +			mt76_queue_kick(dev, dev->mphy.q_tx[MT_TXQ_PSD]);  	}  	if (intr & MT_INT_TX_STAT) @@ -357,7 +346,7 @@ static bool mt76x02_tx_hang(struct mt76x02_dev *dev)  	int i;  	for (i = 0; i < 4; i++) { -		q = dev->mt76.q_tx[i]; +		q = dev->mphy.q_tx[i];  		if (!q->queued)  			continue; @@ -475,8 +464,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)  	if (restart)  		mt76_mcu_restart(dev); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true);  	for (i = 0; i < __MT_TXQ_MAX; i++) -		mt76_queue_tx_cleanup(dev, i, true); +		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);  	mt76_for_each_q_rx(&dev->mt76, i) {  		mt76_queue_rx_reset(dev, i); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 2c2f56112b57..efd70ddc2fd1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -67,7 +67,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,  			    struct mt76_tx_info *tx_info)  {  	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); -	int pid, len = tx_info->skb->len, ep = q2ep(mdev->q_tx[qid]->hw_idx); +	int pid, len = tx_info->skb->len, ep = q2ep(dev->mphy.q_tx[qid]->hw_idx);  	struct mt76x02_txwi *txwi;  	bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU;  	enum mt76_qsel qsel; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index e43d13d7c988..2953df7d8388 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -297,6 +297,7 @@ void mt76x02u_init_mcu(struct mt76_dev *dev)  		.headroom = MT_CMD_HDR_LEN,  		.tailroom = 8,  		.mcu_send_msg = mt76x02u_mcu_send_msg, +		.mcu_parse_response = mt76x02_mcu_parse_response,  		.mcu_wr_rp = mt76x02u_mcu_wr_rp,  		.mcu_rd_rp = mt76x02u_mcu_rd_rp,  	}; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 11b769af2f8f..7ac20d3c16d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -186,6 +186,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev)  	ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES);  	ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); +	ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);  	dev->mt76.global_wcid.idx = 255;  	dev->mt76.global_wcid.hw_key_idx = -1; @@ -304,12 +305,12 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)  	/* Allow to change address in HW if we create first interface. */  	if (!dev->mphy.vif_mask && -	    (((vif->addr[0] ^ dev->mt76.macaddr[0]) & ~GENMASK(4, 1)) || -	     memcmp(vif->addr + 1, dev->mt76.macaddr + 1, ETH_ALEN - 1))) +	    (((vif->addr[0] ^ dev->mphy.macaddr[0]) & ~GENMASK(4, 1)) || +	     memcmp(vif->addr + 1, dev->mphy.macaddr + 1, ETH_ALEN - 1)))  		mt76x02_mac_setaddr(dev, vif->addr);  	if (vif->addr[0] & BIT(1)) -		idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7); +		idx = 1 + (((dev->mphy.macaddr[0] ^ vif->addr[0]) >> 2) & 7);  	/*  	 * Client mode typically only has one configurable BSSID register, @@ -487,7 +488,7 @@ int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	u8 cw_min = 5, cw_max = 10, qid;  	u32 val; -	qid = dev->mt76.q_tx[queue]->hw_idx; +	qid = dev->mphy.q_tx[queue]->hw_idx;  	if (params->cw_min)  		cw_min = fls(params->cw_min); @@ -621,7 +622,7 @@ void mt76x02_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta,  	struct mt76x02_sta *msta = (struct mt76x02_sta *)sta->drv_priv;  	int idx = msta->wcid.idx; -	mt76_stop_tx_queues(&dev->mt76, sta, true); +	mt76_stop_tx_queues(&dev->mphy, sta, true);  	if (mt76_is_mmio(mdev))  		mt76x02_mac_wcid_set_drop(dev, idx, ps);  } @@ -677,7 +678,7 @@ void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev)  	for (i = 0; i < ARRAY_SIZE(dev->macaddr_list); i++) {  		u8 *addr = dev->macaddr_list[i].addr; -		memcpy(addr, dev->mt76.macaddr, ETH_ALEN); +		memcpy(addr, dev->mphy.macaddr, ETH_ALEN);  		if (!i)  			continue; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c index 410ffce3baff..c57e05a5c65e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c @@ -16,7 +16,7 @@ mt76x2_eeprom_get_macaddr(struct mt76x02_dev *dev)  {  	void *src = dev->mt76.eeprom.data + MT_EE_MAC_ADDR; -	memcpy(dev->mt76.macaddr, src, ETH_ALEN); +	memcpy(dev->mphy.macaddr, src, ETH_ALEN);  	return 0;  } @@ -502,8 +502,8 @@ int mt76x2_eeprom_init(struct mt76x02_dev *dev)  	mt76x02_eeprom_parse_hw_cap(dev);  	mt76x2_eeprom_get_macaddr(dev); -	mt76_eeprom_override(&dev->mt76); -	dev->mt76.macaddr[0] &= ~BIT(1); +	mt76_eeprom_override(&dev->mphy); +	dev->mphy.macaddr[0] &= ~BIT(1);  	return 0;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c index 9635c04ce032..3c2738903d7d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c @@ -33,13 +33,14 @@ int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw,  	};  	/* first set the channel without the extension channel info */ -	mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), true); +	mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg, +			  sizeof(msg), true);  	usleep_range(5000, 10000);  	msg.ext_chan = 0xe0 + bw_index; -	return mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), -				 true); +	return mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg, +				 sizeof(msg), true);  }  EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel); @@ -66,7 +67,8 @@ int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level,  	msg.cfg = cpu_to_le32(val);  	/* first set the channel without the extension channel info */ -	return mt76_mcu_send_msg(dev, CMD_LOAD_CR, &msg, sizeof(msg), true); +	return mt76_mcu_send_msg(&dev->mt76, CMD_LOAD_CR, &msg, sizeof(msg), +				 true);  }  EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr); @@ -84,8 +86,8 @@ int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain,  	if (force)  		msg.channel |= cpu_to_le32(BIT(31)); -	return mt76_mcu_send_msg(dev, CMD_INIT_GAIN_OP, &msg, sizeof(msg), -				 true); +	return mt76_mcu_send_msg(&dev->mt76, CMD_INIT_GAIN_OP, &msg, +				 sizeof(msg), true);  }  EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain); @@ -100,7 +102,7 @@ int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev,  		.data = *tssi_data,  	}; -	return mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg), -				 true); +	return mt76_mcu_send_msg(&dev->mt76, CMD_CALIBRATION_OP, &msg, +				 sizeof(msg), true);  }  EXPORT_SYMBOL_GPL(mt76x2_mcu_tssi_comp); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index 4d50dad29ddf..ecaf85b483ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -90,7 +90,8 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	return 0;  error: -	ieee80211_free_hw(mt76_hw(dev)); +	mt76_free_device(&dev->mt76); +  	return ret;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 48a3ebc9892a..620484390418 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -69,7 +69,7 @@ mt76x2_fixup_xtal(struct mt76x02_dev *dev)  int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)  { -	const u8 *macaddr = dev->mt76.macaddr; +	const u8 *macaddr = dev->mphy.macaddr;  	u32 val;  	int i, k; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c index ca6f968411ac..e5b6282d1a6c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c @@ -179,6 +179,7 @@ int mt76x2_mcu_init(struct mt76x02_dev *dev)  	static const struct mt76_mcu_ops mt76x2_mcu_ops = {  		.mcu_restart = mt76pci_mcu_restart,  		.mcu_send_msg = mt76x02_mcu_msg_send, +		.mcu_parse_response = mt76x02_mcu_parse_response,  	};  	int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index 4e003c7b62cf..2575369e44e2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -75,6 +75,7 @@ static int mt76x2u_probe(struct usb_interface *intf,  	return 0;  err: +	mt76u_queues_deinit(&dev->mt76);  	mt76_free_device(&dev->mt76);  	usb_set_intfdata(intf, NULL);  	usb_put_dev(udev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile index 57fe726cc38b..cc2054dffa98 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile @@ -4,3 +4,5 @@ obj-$(CONFIG_MT7915E) += mt7915e.o  mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \  	     debugfs.o + +mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index 1049927faf24..7d810fbf2862 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -48,32 +48,6 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL,  			 mt7915_radar_trigger, "%lld\n");  static int -mt7915_dbdc_set(void *data, u64 val) -{ -	struct mt7915_dev *dev = data; - -	if (val) -		mt7915_register_ext_phy(dev); -	else -		mt7915_unregister_ext_phy(dev); - -	return 0; -} - -static int -mt7915_dbdc_get(void *data, u64 *val) -{ -	struct mt7915_dev *dev = data; - -	*val = !!mt7915_ext_phy(dev); - -	return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7915_dbdc_get, -			 mt7915_dbdc_set, "%lld\n"); - -static int  mt7915_fw_debug_set(void *data, u64 val)  {  	struct mt7915_dev *dev = data; @@ -233,6 +207,7 @@ static const struct file_operations fops_tx_stats = {  	.read = seq_read,  	.llseek = seq_lseek,  	.release = single_release, +	.owner = THIS_MODULE,  };  static int mt7915_read_temperature(struct seq_file *s, void *data) @@ -279,19 +254,23 @@ static int  mt7915_queues_read(struct seq_file *s, void *data)  {  	struct mt7915_dev *dev = dev_get_drvdata(s->private); -	static const struct { +	struct mt76_phy *mphy_ext = dev->mt76.phy2; +	struct mt76_queue *ext_q = mphy_ext ? mphy_ext->q_tx[MT_TXQ_BE] : NULL; +	struct { +		struct mt76_queue *q;  		char *queue; -		int id;  	} queue_map[] = { -		{ "WFDMA0", MT_TXQ_BE }, -		{ "MCUWM", MT_TXQ_MCU }, -		{ "MCUWA", MT_TXQ_MCU_WA }, -		{ "MCUFWQ", MT_TXQ_FWDL }, +		{ dev->mphy.q_tx[MT_TXQ_BE],	 "WFDMA0" }, +		{ ext_q,			 "WFDMA1" }, +		{ dev->mphy.q_tx[MT_TXQ_BE],	 "WFDMA0" }, +		{ dev->mt76.q_mcu[MT_MCUQ_WM],	 "MCUWM"  }, +		{ dev->mt76.q_mcu[MT_MCUQ_WA],	 "MCUWA"  }, +		{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },  	};  	int i;  	for (i = 0; i < ARRAY_SIZE(queue_map); i++) { -		struct mt76_queue *q = dev->mt76.q_tx[queue_map[i].id]; +		struct mt76_queue *q = queue_map[i].q;  		if (!q)  			continue; @@ -375,7 +354,6 @@ int mt7915_init_debugfs(struct mt7915_dev *dev)  	debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,  				    mt7915_queues_acq);  	debugfs_create_file("tx_stats", 0400, dir, dev, &fops_tx_stats); -	debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc);  	debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);  	debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern);  	/* test knobs */ @@ -460,6 +438,7 @@ static const struct file_operations fops_sta_stats = {  	.read = seq_read,  	.llseek = seq_lseek,  	.release = single_release, +	.owner = THIS_MODULE,  };  void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index cfa12c4c671f..8c1f9c77b14f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -5,42 +5,16 @@  #include "../dma.h"  #include "mac.h" -static int -mt7915_init_tx_queues(struct mt7915_dev *dev, int n_desc) +int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc)  { -	struct mt76_queue *hwq; -	int err, i; +	int i, err; -	hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); -	if (!hwq) -		return -ENOMEM; - -	err = mt76_queue_alloc(dev, hwq, MT7915_TXQ_BAND0, n_desc, 0, -			       MT_TX_RING_BASE); -	if (err < 0) -		return err; - -	for (i = 0; i < MT_TXQ_MCU; i++) -		dev->mt76.q_tx[i] = hwq; - -	return 0; -} - -static int -mt7915_init_mcu_queue(struct mt7915_dev *dev, int qid, int idx, int n_desc) -{ -	struct mt76_queue *hwq; -	int err; - -	hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); -	if (!hwq) -		return -ENOMEM; - -	err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); +	err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE);  	if (err < 0)  		return err; -	dev->mt76.q_tx[qid] = hwq; +	for (i = 0; i <= MT_TXQ_PSD; i++) +		phy->mt76->q_tx[i] = phy->mt76->q_tx[0];  	return 0;  } @@ -61,6 +35,11 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,  	case PKT_TYPE_RX_EVENT:  		mt7915_mcu_rx_event(dev, skb);  		break; +#ifdef CONFIG_NL80211_TESTMODE +	case PKT_TYPE_TXRXV: +		mt7915_mac_fill_rx_vector(dev, skb); +		break; +#endif  	case PKT_TYPE_NORMAL:  		if (!mt7915_mac_fill_rx(dev, skb)) {  			mt76_rx(&dev->mt76, q, skb); @@ -76,8 +55,8 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,  static void  mt7915_tx_cleanup(struct mt7915_dev *dev)  { -	mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false); -	mt76_queue_tx_cleanup(dev, MT_TXQ_MCU_WA, false); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false);  }  static int mt7915_poll_tx(struct napi_struct *napi, int budget) @@ -257,25 +236,26 @@ int mt7915_dma_init(struct mt7915_dev *dev)  	mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0, 0);  	/* init tx queue */ -	ret = mt7915_init_tx_queues(dev, MT7915_TX_RING_SIZE); +	ret = mt7915_init_tx_queues(&dev->phy, MT7915_TXQ_BAND0, +				    MT7915_TX_RING_SIZE);  	if (ret)  		return ret;  	/* command to WM */ -	ret = mt7915_init_mcu_queue(dev, MT_TXQ_MCU, MT7915_TXQ_MCU_WM, -				    MT7915_TX_MCU_RING_SIZE); +	ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7915_TXQ_MCU_WM, +				  MT7915_TX_MCU_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret;  	/* command to WA */ -	ret = mt7915_init_mcu_queue(dev, MT_TXQ_MCU_WA, MT7915_TXQ_MCU_WA, -				    MT7915_TX_MCU_RING_SIZE); +	ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WA, MT7915_TXQ_MCU_WA, +				  MT7915_TX_MCU_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret;  	/* firmware download */ -	ret = mt7915_init_mcu_queue(dev, MT_TXQ_FWDL, MT7915_TXQ_FWDL, -				    MT7915_TX_FWDL_RING_SIZE); +	ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7915_TXQ_FWDL, +				  MT7915_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);  	if (ret)  		return ret; @@ -293,13 +273,21 @@ int mt7915_dma_init(struct mt7915_dev *dev)  	if (ret)  		return ret; -	/* rx data */ -	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, -			       MT7915_RX_RING_SIZE, rx_buf_size, -			       MT_RX_DATA_RING_BASE); +	/* rx data queue */ +	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], +			       MT7915_RXQ_BAND0, MT7915_RX_RING_SIZE, +			       rx_buf_size, MT_RX_DATA_RING_BASE);  	if (ret)  		return ret; +	if (dev->dbdc_support) { +		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT], +				       MT7915_RXQ_BAND1, MT7915_RX_RING_SIZE, +				       rx_buf_size, MT_RX_DATA_RING_BASE); +		if (ret) +			return ret; +	} +  	ret = mt76_init_queues(dev);  	if (ret < 0)  		return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 7deba7ebd68a..7a2be3f61398 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -4,16 +4,11 @@  #include "mt7915.h"  #include "eeprom.h" -static inline bool mt7915_efuse_valid(u8 val) -{ -	return !(val == 0xff); -} - -u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset) +static u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset)  {  	u8 *data = dev->mt76.eeprom.data; -	if (!mt7915_efuse_valid(data[offset])) +	if (data[offset] == 0xff)  		mt7915_mcu_get_eeprom(dev, offset);  	return data[offset]; @@ -34,10 +29,10 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)  static int mt7915_check_eeprom(struct mt7915_dev *dev)  { -	u16 val;  	u8 *eeprom = dev->mt76.eeprom.data; +	u16 val; -	mt7915_eeprom_read(dev, 0); +	mt7915_eeprom_read(dev, MT_EE_CHIP_ID);  	val = get_unaligned_le16(eeprom);  	switch (val) { @@ -48,35 +43,50 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev)  	}  } -static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev) +void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)  { -	u8 *eeprom = dev->mt76.eeprom.data; -	u8 tx_mask, max_nss = 4; -	u32 val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF); +	struct mt7915_dev *dev = phy->dev; +	bool ext_phy = phy != &dev->phy; +	u32 val; +	val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF + ext_phy);  	val = FIELD_GET(MT_EE_WIFI_CONF_BAND_SEL, val);  	switch (val) {  	case MT_EE_5GHZ: -		dev->mt76.cap.has_5ghz = true; +		phy->mt76->cap.has_5ghz = true;  		break;  	case MT_EE_2GHZ: -		dev->mt76.cap.has_2ghz = true; +		phy->mt76->cap.has_2ghz = true;  		break;  	default: -		dev->mt76.cap.has_2ghz = true; -		dev->mt76.cap.has_5ghz = true; +		phy->mt76->cap.has_2ghz = true; +		phy->mt76->cap.has_5ghz = true;  		break;  	} +} + +static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev) +{ +	u8 nss, tx_mask[2] = {}, *eeprom = dev->mt76.eeprom.data; + +	mt7915_eeprom_parse_band_config(&dev->phy);  	/* read tx mask from eeprom */ -	tx_mask =  FIELD_GET(MT_EE_WIFI_CONF_TX_MASK, -			     eeprom[MT_EE_WIFI_CONF]); -	if (!tx_mask || tx_mask > max_nss) -		tx_mask = max_nss; - -	dev->chainmask = BIT(tx_mask) - 1; -	dev->mphy.antenna_mask = dev->chainmask; -	dev->phy.chainmask = dev->chainmask; +	tx_mask[0] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK, +			       eeprom[MT_EE_WIFI_CONF]); +	if (dev->dbdc_support) +		tx_mask[1] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK, +				       eeprom[MT_EE_WIFI_CONF + 1]); + +	nss = tx_mask[0] + tx_mask[1]; +	if (!nss || nss > 4) { +		tx_mask[0] = 4; +		nss = 4; +	} + +	dev->chainmask = BIT(nss) - 1; +	dev->mphy.antenna_mask = BIT(tx_mask[0]) - 1; +	dev->phy.chainmask = dev->mphy.antenna_mask;  }  int mt7915_eeprom_init(struct mt7915_dev *dev) @@ -92,10 +102,10 @@ int mt7915_eeprom_init(struct mt7915_dev *dev)  		return ret;  	mt7915_eeprom_parse_hw_cap(dev); -	memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, +	memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,  	       ETH_ALEN); -	mt76_eeprom_override(&dev->mt76); +	mt76_eeprom_override(&dev->mphy);  	return 0;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h index 4e31d6ab4fa6..6712032b40df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h @@ -15,6 +15,7 @@ enum mt7915_eeprom_field {  	MT_EE_CHIP_ID =		0x000,  	MT_EE_VERSION =		0x002,  	MT_EE_MAC_ADDR =	0x004, +	MT_EE_MAC_ADDR2 =	0x00a,  	MT_EE_DDIE_FT_VERSION =	0x050,  	MT_EE_WIFI_CONF =	0x190,  	MT_EE_TX0_POWER_2G =	0x2fc, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 0232b66acb4f..ed4635bd151a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -6,6 +6,113 @@  #include "mac.h"  #include "eeprom.h" +#define CCK_RATE(_idx, _rate) {						\ +	.bitrate = _rate,						\ +	.flags = IEEE80211_RATE_SHORT_PREAMBLE,				\ +	.hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx),			\ +	.hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)),	\ +} + +#define OFDM_RATE(_idx, _rate) {					\ +	.bitrate = _rate,						\ +	.hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx),			\ +	.hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx),		\ +} + +static struct ieee80211_rate mt7915_rates[] = { +	CCK_RATE(0, 10), +	CCK_RATE(1, 20), +	CCK_RATE(2, 55), +	CCK_RATE(3, 110), +	OFDM_RATE(11, 60), +	OFDM_RATE(15, 90), +	OFDM_RATE(10, 120), +	OFDM_RATE(14, 180), +	OFDM_RATE(9,  240), +	OFDM_RATE(13, 360), +	OFDM_RATE(8,  480), +	OFDM_RATE(12, 540), +}; + +static const struct ieee80211_iface_limit if_limits[] = { +	{ +		.max = 1, +		.types = BIT(NL80211_IFTYPE_ADHOC) +	}, { +		.max = 16, +		.types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH +			 BIT(NL80211_IFTYPE_MESH_POINT) +#endif +	}, { +		.max = MT7915_MAX_INTERFACES, +		.types = BIT(NL80211_IFTYPE_STATION) +	} +}; + +static const struct ieee80211_iface_combination if_comb[] = { +	{ +		.limits = if_limits, +		.n_limits = ARRAY_SIZE(if_limits), +		.max_interfaces = MT7915_MAX_INTERFACES, +		.num_different_channels = 1, +		.beacon_int_infra_match = true, +		.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | +				       BIT(NL80211_CHAN_WIDTH_20) | +				       BIT(NL80211_CHAN_WIDTH_40) | +				       BIT(NL80211_CHAN_WIDTH_80) | +				       BIT(NL80211_CHAN_WIDTH_160) | +				       BIT(NL80211_CHAN_WIDTH_80P80), +	} +}; + +static void +mt7915_regd_notifier(struct wiphy *wiphy, +		     struct regulatory_request *request) +{ +	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); +	struct mt7915_dev *dev = mt7915_hw_dev(hw); +	struct mt76_phy *mphy = hw->priv; +	struct mt7915_phy *phy = mphy->priv; +	struct cfg80211_chan_def *chandef = &mphy->chandef; + +	dev->mt76.region = request->dfs_region; + +	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) +		return; + +	mt7915_dfs_init_radar_detector(phy); +} + +static void +mt7915_init_wiphy(struct ieee80211_hw *hw) +{ +	struct mt7915_phy *phy = mt7915_hw_phy(hw); +	struct wiphy *wiphy = hw->wiphy; + +	hw->queues = 4; +	hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; +	hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + +	phy->slottime = 9; + +	hw->sta_data_size = sizeof(struct mt7915_sta); +	hw->vif_data_size = sizeof(struct mt7915_vif); + +	wiphy->iface_combinations = if_comb; +	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); +	wiphy->reg_notifier = mt7915_regd_notifier; +	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + +	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + +	ieee80211_hw_set(hw, HAS_RATE_CONTROL); +	ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); +	ieee80211_hw_set(hw, WANT_MONITOR_VIF); + +	hw->max_tx_fragments = 4; +} +  static void  mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)  { @@ -35,25 +142,26 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)  	mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);  	mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); + +	mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536); +	/* disable rx rate report by default due to hw issues */ +	mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);  }  static void mt7915_mac_init(struct mt7915_dev *dev)  {  	int i; -	mt76_rmw_field(dev, MT_DMA_DCR0, MT_DMA_DCR0_MAX_RX_LEN, 1536);  	mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536); -	/* enable rx rate report */ -	mt76_set(dev, MT_DMA_DCR0, MT_DMA_DCR0_RXD_G5_EN);  	/* disable hardware de-agg */  	mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);  	for (i = 0; i < MT7915_WTBL_SIZE; i++)  		mt7915_mac_wtbl_update(dev, i,  				       MT_WTBL_UPDATE_ADM_COUNT_CLEAR); +	for (i = 0; i < 2; i++) +		mt7915_mac_init_band(dev, i); -	mt7915_mac_init_band(dev, 0); -	mt7915_mac_init_band(dev, 1);  	mt7915_mcu_set_rts_thresh(&dev->phy, 0x92b);  } @@ -108,6 +216,60 @@ static void mt7915_init_txpower(struct mt7915_dev *dev)  	mt7915_eeprom_init_sku(dev);  } +static int mt7915_register_ext_phy(struct mt7915_dev *dev) +{ +	struct mt7915_phy *phy = mt7915_ext_phy(dev); +	struct mt76_phy *mphy; +	int ret; + +	if (!dev->dbdc_support) +		return 0; + +	if (phy) +		return 0; + +	mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); +	if (!mphy) +		return -ENOMEM; + +	phy = mphy->priv; +	phy->dev = dev; +	phy->mt76 = mphy; +	phy->chainmask = dev->chainmask & ~dev->phy.chainmask; +	mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; +	mt7915_init_wiphy(mphy->hw); + +	INIT_LIST_HEAD(&phy->stats_list); +	INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work); + +	mt7915_eeprom_parse_band_config(phy); +	mt7915_set_stream_vht_txbf_caps(phy); +	mt7915_set_stream_he_caps(phy); + +	memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR2, +	       ETH_ALEN); +	mt76_eeprom_override(mphy); + +	/* The second interface does not get any packets unless it has a vif */ +	ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF); + +	ret = mt7915_init_tx_queues(phy, MT7915_TXQ_BAND1, +				    MT7915_TX_RING_SIZE); +	if (ret) +		goto error; + +	ret = mt76_register_phy(mphy, true, mt7915_rates, +				ARRAY_SIZE(mt7915_rates)); +	if (ret) +		goto error; + +	return 0; + +error: +	ieee80211_free_hw(mphy->hw); +	return ret; +} +  static void mt7915_init_work(struct work_struct *work)  {  	struct mt7915_dev *dev = container_of(work, struct mt7915_dev, @@ -117,6 +279,7 @@ static void mt7915_init_work(struct work_struct *work)  	mt7915_mac_init(dev);  	mt7915_init_txpower(dev);  	mt7915_txbf_init(dev); +	mt7915_register_ext_phy(dev);  }  static int mt7915_init_hardware(struct mt7915_dev *dev) @@ -129,6 +292,8 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)  	spin_lock_init(&dev->token_lock);  	idr_init(&dev->token); +	dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5)); +  	ret = mt7915_dma_init(dev);  	if (ret)  		return ret; @@ -162,109 +327,6 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)  	return 0;  } -#define CCK_RATE(_idx, _rate) {						\ -	.bitrate = _rate,						\ -	.flags = IEEE80211_RATE_SHORT_PREAMBLE,				\ -	.hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx),			\ -	.hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)),	\ -} - -#define OFDM_RATE(_idx, _rate) {					\ -	.bitrate = _rate,						\ -	.hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx),			\ -	.hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx),		\ -} - -static struct ieee80211_rate mt7915_rates[] = { -	CCK_RATE(0, 10), -	CCK_RATE(1, 20), -	CCK_RATE(2, 55), -	CCK_RATE(3, 110), -	OFDM_RATE(11, 60), -	OFDM_RATE(15, 90), -	OFDM_RATE(10, 120), -	OFDM_RATE(14, 180), -	OFDM_RATE(9,  240), -	OFDM_RATE(13, 360), -	OFDM_RATE(8,  480), -	OFDM_RATE(12, 540), -}; - -static const struct ieee80211_iface_limit if_limits[] = { -	{ -		.max = 1, -		.types = BIT(NL80211_IFTYPE_ADHOC) -	}, { -		.max = MT7915_MAX_INTERFACES, -		.types = BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH -			 BIT(NL80211_IFTYPE_MESH_POINT) | -#endif -			 BIT(NL80211_IFTYPE_STATION) -	} -}; - -static const struct ieee80211_iface_combination if_comb[] = { -	{ -		.limits = if_limits, -		.n_limits = ARRAY_SIZE(if_limits), -		.max_interfaces = 4, -		.num_different_channels = 1, -		.beacon_int_infra_match = true, -		.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | -				       BIT(NL80211_CHAN_WIDTH_20) | -				       BIT(NL80211_CHAN_WIDTH_40) | -				       BIT(NL80211_CHAN_WIDTH_80) | -				       BIT(NL80211_CHAN_WIDTH_160) | -				       BIT(NL80211_CHAN_WIDTH_80P80), -	} -}; - -static void -mt7915_regd_notifier(struct wiphy *wiphy, -		     struct regulatory_request *request) -{ -	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); -	struct mt7915_dev *dev = mt7915_hw_dev(hw); -	struct mt76_phy *mphy = hw->priv; -	struct mt7915_phy *phy = mphy->priv; -	struct cfg80211_chan_def *chandef = &mphy->chandef; - -	dev->mt76.region = request->dfs_region; - -	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) -		return; - -	mt7915_dfs_init_radar_detector(phy); -} - -static void -mt7915_init_wiphy(struct ieee80211_hw *hw) -{ -	struct mt7915_phy *phy = mt7915_hw_phy(hw); -	struct wiphy *wiphy = hw->wiphy; - -	hw->queues = 4; -	hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; -	hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; - -	phy->slottime = 9; - -	hw->sta_data_size = sizeof(struct mt7915_sta); -	hw->vif_data_size = sizeof(struct mt7915_vif); - -	wiphy->iface_combinations = if_comb; -	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); -	wiphy->reg_notifier = mt7915_regd_notifier; -	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; - -	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); - -	ieee80211_hw_set(hw, HAS_RATE_CONTROL); - -	hw->max_tx_fragments = 4; -} -  void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)  {  	int nss = hweight8(phy->chainmask); @@ -342,7 +404,7 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,  	elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;  	/* num_snd_dim */ -	c = (nss - 1) | (max_t(int, mcs->tx_mcs_160, 1) << 3); +	c = (nss - 1) | (max_t(int, le16_to_cpu(mcs->tx_mcs_160), 1) << 3);  	elem->phy_cap_info[5] |= c;  	c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | @@ -354,35 +416,24 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,  }  static void -mt7915_gen_ppe_thresh(u8 *he_ppet) +mt7915_gen_ppe_thresh(u8 *he_ppet, int nss)  { -	int ru, nss, max_nss = 1, max_ru = 3; -	u8 bit = 7, ru_bit_mask = 0x7; +	u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */  	u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; -	he_ppet[0] = max_nss & IEEE80211_PPE_THRES_NSS_MASK; -	he_ppet[0] |= (ru_bit_mask << -		       IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) & -			IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK; - -	for (nss = 0; nss <= max_nss; nss++) { -		for (ru = 0; ru < max_ru; ru++) { -			u8 val; -			int i; - -			if (!(ru_bit_mask & BIT(ru))) -				continue; - -			val = (ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) & -			       0x3f; -			val = ((val >> 3) & 0x7) | ((val & 0x7) << 3); -			for (i = 5; i >= 0; i--) { -				he_ppet[bit / 8] |= -					((val >> i) & 0x1) << ((bit % 8)); -				bit++; -			} -		} -	} +	he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | +		     FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, +				ru_bit_mask); + +	ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE * +		    nss * hweight8(ru_bit_mask) * 2; +	ppet_size = DIV_ROUND_UP(ppet_bits, 8); + +	for (i = 0; i < ppet_size - 1; i++) +		he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3]; + +	he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] & +			 (0xff >> (8 - (ppet_bits - 1) % 8));  }  static int @@ -513,7 +564,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,  		memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));  		if (he_cap_elem->phy_cap_info[6] &  		    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { -			mt7915_gen_ppe_thresh(he_cap->ppe_thres); +			mt7915_gen_ppe_thresh(he_cap->ppe_thres, nss);  		} else {  			he_cap_elem->phy_cap_info[9] |=  				IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US; @@ -528,10 +579,9 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)  {  	struct ieee80211_sband_iftype_data *data;  	struct ieee80211_supported_band *band; -	struct mt76_dev *mdev = &phy->dev->mt76;  	int n; -	if (mdev->cap.has_2ghz) { +	if (phy->mt76->cap.has_2ghz) {  		data = phy->iftype[NL80211_BAND_2GHZ];  		n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data); @@ -540,7 +590,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)  		band->n_iftype_data = n;  	} -	if (mdev->cap.has_5ghz) { +	if (phy->mt76->cap.has_5ghz) {  		data = phy->iftype[NL80211_BAND_5GHZ];  		n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data); @@ -550,95 +600,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)  	}  } -static void -mt7915_cap_dbdc_enable(struct mt7915_dev *dev) -{ -	dev->mphy.sband_5g.sband.vht_cap.cap &= -			~(IEEE80211_VHT_CAP_SHORT_GI_160 | -			  IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); - -	if (dev->chainmask == 0xf) -		dev->mphy.antenna_mask = dev->chainmask >> 2; -	else -		dev->mphy.antenna_mask = dev->chainmask >> 1; - -	dev->phy.chainmask = dev->mphy.antenna_mask; -	dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask; -	dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask; - -	mt76_set_stream_caps(&dev->mphy, true); -	mt7915_set_stream_vht_txbf_caps(&dev->phy); -	mt7915_set_stream_he_caps(&dev->phy); -} - -static void -mt7915_cap_dbdc_disable(struct mt7915_dev *dev) -{ -	dev->mphy.sband_5g.sband.vht_cap.cap |= -			IEEE80211_VHT_CAP_SHORT_GI_160 | -			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; - -	dev->mphy.antenna_mask = dev->chainmask; -	dev->phy.chainmask = dev->chainmask; -	dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask; -	dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask; - -	mt76_set_stream_caps(&dev->mphy, true); -	mt7915_set_stream_vht_txbf_caps(&dev->phy); -	mt7915_set_stream_he_caps(&dev->phy); -} - -int mt7915_register_ext_phy(struct mt7915_dev *dev) -{ -	struct mt7915_phy *phy = mt7915_ext_phy(dev); -	struct mt76_phy *mphy; -	int ret; -	bool bound; - -	/* TODO: enble DBDC */ -	bound = mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5); -	if (!bound) -		return -EINVAL; - -	if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) -		return -EINVAL; - -	if (phy) -		return 0; - -	mt7915_cap_dbdc_enable(dev); -	mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); -	if (!mphy) -		return -ENOMEM; - -	phy = mphy->priv; -	phy->dev = dev; -	phy->mt76 = mphy; -	phy->chainmask = dev->chainmask & ~dev->phy.chainmask; -	mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; -	mt7915_init_wiphy(mphy->hw); - -	INIT_LIST_HEAD(&phy->stats_list); -	INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work); - -	/* -	 * Make the secondary PHY MAC address local without overlapping with -	 * the usual MAC address allocation scheme on multiple virtual interfaces -	 */ -	mphy->hw->wiphy->perm_addr[0] |= 2; -	mphy->hw->wiphy->perm_addr[0] ^= BIT(7); - -	/* The second interface does not get any packets unless it has a vif */ -	ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF); - -	ret = mt76_register_phy(mphy); -	if (ret) -		ieee80211_free_hw(mphy->hw); - -	return ret; -} - -void mt7915_unregister_ext_phy(struct mt7915_dev *dev) +static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)  {  	struct mt7915_phy *phy = mt7915_ext_phy(dev);  	struct mt76_phy *mphy = dev->mt76.phy2; @@ -646,7 +608,6 @@ void mt7915_unregister_ext_phy(struct mt7915_dev *dev)  	if (!phy)  		return; -	mt7915_cap_dbdc_disable(dev);  	mt76_unregister_phy(mphy);  	ieee80211_free_hw(mphy->hw);  } @@ -683,9 +644,22 @@ int mt7915_register_device(struct mt7915_dev *dev)  	dev->mphy.sband_5g.sband.vht_cap.cap |=  			IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |  			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; -	mt7915_cap_dbdc_disable(dev); +	if (!dev->dbdc_support) +		dev->mphy.sband_5g.sband.vht_cap.cap |= +			IEEE80211_VHT_CAP_SHORT_GI_160 | +			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; +	dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask; +	dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask; + +	mt76_set_stream_caps(&dev->mphy, true); +	mt7915_set_stream_vht_txbf_caps(&dev->phy); +	mt7915_set_stream_he_caps(&dev->phy);  	dev->phy.dfs_state = -1; +#ifdef CONFIG_NL80211_TESTMODE +	dev->mt76.test_ops = &mt7915_testmode_ops; +#endif +  	ret = mt76_register_device(&dev->mt76, true, mt7915_rates,  				   ARRAY_SIZE(mt7915_rates));  	if (ret) @@ -716,6 +690,7 @@ void mt7915_unregister_device(struct mt7915_dev *dev)  			ieee80211_free_txskb(hw, txwi->skb);  		}  		mt76_put_txwi(&dev->mt76, txwi); +		dev->token_count--;  	}  	spin_unlock_bh(&dev->token_lock);  	idr_destroy(&dev->token); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 6f159d99a596..f504eeb221f9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -562,21 +562,271 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)  	return 0;  } +#ifdef CONFIG_NL80211_TESTMODE +void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb) +{ +	__le32 *rxd = (__le32 *)skb->data; +	__le32 *rxv = rxd + 4; +	u32 rcpi, ib_rssi, wb_rssi, v20, v21; +	s32 foe; +	u8 snr; +	int i; + +	rcpi = le32_to_cpu(rxv[6]); +	ib_rssi = le32_to_cpu(rxv[7]); +	wb_rssi = le32_to_cpu(rxv[8]) >> 5; + +	for (i = 0; i < 4; i++, rcpi >>= 8, ib_rssi >>= 8, wb_rssi >>= 9) { +		if (i == 3) +			wb_rssi = le32_to_cpu(rxv[9]); + +		dev->test.last_rcpi[i] = rcpi & 0xff; +		dev->test.last_ib_rssi[i] = ib_rssi & 0xff; +		dev->test.last_wb_rssi[i] = wb_rssi & 0xff; +	} + +	v20 = le32_to_cpu(rxv[20]); +	v21 = le32_to_cpu(rxv[21]); + +	foe = FIELD_GET(MT_CRXV_FOE_LO, v20) | +	      (FIELD_GET(MT_CRXV_FOE_HI, v21) << MT_CRXV_FOE_SHIFT); + +	snr = FIELD_GET(MT_CRXV_SNR, v20) - 16; + +	dev->test.last_freq_offset = foe; +	dev->test.last_snr = snr; + +	dev_kfree_skb(skb); +} +#endif + +static void +mt7915_mac_write_txwi_tm(struct mt7915_dev *dev, struct mt76_phy *mphy, +			 __le32 *txwi, struct sk_buff *skb) +{ +#ifdef CONFIG_NL80211_TESTMODE +	struct mt76_testmode_data *td = &dev->mt76.test; +	u8 rate_idx = td->tx_rate_idx; +	u8 nss = td->tx_rate_nss; +	u8 bw, mode; +	u16 rateval = 0; +	u32 val; + +	if (skb != dev->mt76.test.tx_skb) +		return; + +	switch (td->tx_rate_mode) { +	case MT76_TM_TX_MODE_CCK: +		mode = MT_PHY_TYPE_CCK; +		break; +	case MT76_TM_TX_MODE_HT: +		nss = 1 + (rate_idx >> 3); +		mode = MT_PHY_TYPE_HT; +		break; +	case MT76_TM_TX_MODE_VHT: +		mode = MT_PHY_TYPE_VHT; +		break; +	case MT76_TM_TX_MODE_HE_SU: +		mode = MT_PHY_TYPE_HE_SU; +		break; +	case MT76_TM_TX_MODE_HE_EXT_SU: +		mode = MT_PHY_TYPE_HE_EXT_SU; +		break; +	case MT76_TM_TX_MODE_HE_TB: +		mode = MT_PHY_TYPE_HE_TB; +		break; +	case MT76_TM_TX_MODE_HE_MU: +		mode = MT_PHY_TYPE_HE_MU; +		break; +	case MT76_TM_TX_MODE_OFDM: +	default: +		mode = MT_PHY_TYPE_OFDM; +		break; +	} + +	switch (mphy->chandef.width) { +	case NL80211_CHAN_WIDTH_40: +		bw = 1; +		break; +	case NL80211_CHAN_WIDTH_80: +		bw = 2; +		break; +	case NL80211_CHAN_WIDTH_80P80: +	case NL80211_CHAN_WIDTH_160: +		bw = 3; +		break; +	default: +		bw = 0; +		break; +	} + +	if (td->tx_rate_stbc && nss == 1) { +		nss++; +		rateval |= MT_TX_RATE_STBC; +	} + +	rateval |= FIELD_PREP(MT_TX_RATE_IDX, rate_idx) | +		   FIELD_PREP(MT_TX_RATE_MODE, mode) | +		   FIELD_PREP(MT_TX_RATE_NSS, nss - 1); + +	txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); + +	le32p_replace_bits(&txwi[3], 1, MT_TXD3_REM_TX_COUNT); +	if (td->tx_rate_mode < MT76_TM_TX_MODE_HT) +		txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); + +	val = MT_TXD6_FIXED_BW | +	      FIELD_PREP(MT_TXD6_BW, bw) | +	      FIELD_PREP(MT_TXD6_TX_RATE, rateval) | +	      FIELD_PREP(MT_TXD6_SGI, td->tx_rate_sgi); + +	/* for HE_SU/HE_EXT_SU PPDU +	 * - 1x, 2x, 4x LTF + 0.8us GI +	 * - 2x LTF + 1.6us GI, 4x LTF + 3.2us GI +	 * for HE_MU PPDU +	 * - 2x, 4x LTF + 0.8us GI +	 * - 2x LTF + 1.6us GI, 4x LTF + 3.2us GI +	 * for HE_TB PPDU +	 * - 1x, 2x LTF + 1.6us GI +	 * - 4x LTF + 3.2us GI +	 */ +	if (mode >= MT_PHY_TYPE_HE_SU) +		val |= FIELD_PREP(MT_TXD6_HELTF, td->tx_ltf); + +	if (td->tx_rate_ldpc) +		val |= MT_TXD6_LDPC; + +	txwi[6] |= cpu_to_le32(val); +	txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, +					  dev->test.spe_idx)); +#endif +} + +static void +mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi, +			   struct sk_buff *skb, struct mt76_wcid *wcid) +{ + +	u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; +	u8 fc_type, fc_stype; +	bool wmm = false; +	u32 val; + +	if (wcid->sta) { +		struct ieee80211_sta *sta; + +		sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); +		wmm = sta->wme; +	} + +	val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | +	      FIELD_PREP(MT_TXD1_TID, tid); + +	if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN) +		val |= MT_TXD1_ETH_802_3; + +	txwi[1] |= cpu_to_le32(val); + +	fc_type = IEEE80211_FTYPE_DATA >> 2; +	fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; + +	val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | +	      FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); + +	txwi[2] |= cpu_to_le32(val); + +	val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | +	      FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); +	txwi[7] |= cpu_to_le32(val); +} + +static void +mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi, +			    struct sk_buff *skb, struct ieee80211_key_conf *key) +{ +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; +	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +	bool multicast = is_multicast_ether_addr(hdr->addr1); +	u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; +	__le16 fc = hdr->frame_control; +	u8 fc_type, fc_stype; +	u32 val; + +	if (ieee80211_is_action(fc) && +	    mgmt->u.action.category == WLAN_CATEGORY_BACK && +	    mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { +		u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); + +		txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA); +		tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK; +	} else if (ieee80211_is_back_req(hdr->frame_control)) { +		struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr; +		u16 control = le16_to_cpu(bar->control); + +		tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control); +	} + +	val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | +	      FIELD_PREP(MT_TXD1_HDR_INFO, +			 ieee80211_get_hdrlen_from_skb(skb) / 2) | +	      FIELD_PREP(MT_TXD1_TID, tid); +	txwi[1] |= cpu_to_le32(val); + +	fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; +	fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; + +	val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | +	      FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | +	      FIELD_PREP(MT_TXD2_MULTICAST, multicast); + +	if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && +	    key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { +		val |= MT_TXD2_BIP; +		txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); +	} + +	if (!ieee80211_is_data(fc) || multicast) +		val |= MT_TXD2_FIX_RATE; + +	txwi[2] |= cpu_to_le32(val); + +	if (ieee80211_is_beacon(fc)) { +		txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); +		txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); +	} + +	if (info->flags & IEEE80211_TX_CTL_INJECTED) { +		u16 seqno = le16_to_cpu(hdr->seq_ctrl); + +		if (ieee80211_is_back_req(hdr->frame_control)) { +			struct ieee80211_bar *bar; + +			bar = (struct ieee80211_bar *)skb->data; +			seqno = le16_to_cpu(bar->start_seq_num); +		} + +		val = MT_TXD3_SN_VALID | +		      FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); +		txwi[3] |= cpu_to_le32(val); +	} + +	val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | +	      FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); +	txwi[7] |= cpu_to_le32(val); +} +  void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,  			   struct sk_buff *skb, struct mt76_wcid *wcid,  			   struct ieee80211_key_conf *key, bool beacon)  {  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; -	bool multicast = is_multicast_ether_addr(hdr->addr1);  	struct ieee80211_vif *vif = info->control.vif;  	struct mt76_phy *mphy = &dev->mphy;  	bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY; -	u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; -	__le16 fc = hdr->frame_control; -	u16 tx_count = 15, seqno = 0; -	u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; +	u8 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;  	if (vif) { @@ -589,13 +839,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,  	if (ext_phy && dev->mt76.phy2)  		mphy = dev->mt76.phy2; -	fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; -	fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; - -	txwi[4] = 0; -	txwi[5] = 0; -	txwi[6] = 0; -  	if (beacon) {  		p_fmt = MT_TX_TYPE_FW;  		q_idx = MT_LMAC_BCN0; @@ -608,20 +851,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,  			mt7915_lmac_mapping(dev, skb_get_queue_mapping(skb));  	} -	if (ieee80211_is_action(fc) && -	    mgmt->u.action.category == WLAN_CATEGORY_BACK && -	    mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { -		u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); - -		txwi[5] |= cpu_to_le32(MT_TXD5_ADD_BA); -		tid = (capab >> 2) & IEEE80211_QOS_CTL_TID_MASK; -	} else if (ieee80211_is_back_req(hdr->frame_control)) { -		struct ieee80211_bar *bar = (struct ieee80211_bar *)hdr; -		u16 control = le16_to_cpu(bar->control); - -		tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control); -	} -  	val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) |  	      FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |  	      FIELD_PREP(MT_TXD0_Q_IDX, q_idx); @@ -629,10 +858,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,  	val = MT_TXD1_LONG_FORMAT |  	      FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | -	      FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | -	      FIELD_PREP(MT_TXD1_HDR_INFO, -			 ieee80211_get_hdrlen_from_skb(skb) / 2) | -	      FIELD_PREP(MT_TXD1_TID, tid) |  	      FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);  	if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) @@ -640,27 +865,31 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,  	txwi[1] = cpu_to_le32(val); -	val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | -	      FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | -	      FIELD_PREP(MT_TXD2_MULTICAST, multicast); -	if (key) { -		if (multicast && ieee80211_is_robust_mgmt_frame(skb) && -		    key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { -			val |= MT_TXD2_BIP; -			txwi[3] = 0; -		} else { -			txwi[3] = cpu_to_le32(MT_TXD3_PROTECT_FRAME); -		} -	} else { -		txwi[3] = 0; -	} -	txwi[2] = cpu_to_le32(val); +	txwi[2] = 0; + +	val = MT_TXD3_SW_POWER_MGMT | +	      FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); +	if (key) +		val |= MT_TXD3_PROTECT_FRAME; +	if (info->flags & IEEE80211_TX_CTL_NO_ACK) +		val |= MT_TXD3_NO_ACK; -	if (!ieee80211_is_data(fc) || multicast) { +	txwi[3] = cpu_to_le32(val); +	txwi[4] = 0; +	txwi[5] = 0; +	txwi[6] = 0; +	txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; + +	if (is_8023) +		mt7915_mac_write_txwi_8023(dev, txwi, skb, wcid); +	else +		mt7915_mac_write_txwi_80211(dev, txwi, skb, key); + +	if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) {  		u16 rate;  		/* hardware won't add HTC for mgmt/ctrl frame */ -		txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE | MT_TXD2_HTC_VLD); +		txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD);  		if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)  			rate = MT7915_5G_RATE_DEFAULT; @@ -673,35 +902,28 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,  		txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);  	} -	if (!ieee80211_is_beacon(fc)) -		txwi[3] |= cpu_to_le32(MT_TXD3_SW_POWER_MGMT); -	else -		tx_count = 0x1f; - -	if (info->flags & IEEE80211_TX_CTL_NO_ACK) -		txwi[3] |= cpu_to_le32(MT_TXD3_NO_ACK); - -	val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | -	      FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); -	if (wcid->amsdu) -		val |= MT_TXD7_HW_AMSDU; -	txwi[7] = cpu_to_le32(val); - -	val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); -	if (info->flags & IEEE80211_TX_CTL_INJECTED) { -		seqno = le16_to_cpu(hdr->seq_ctrl); +	if (mt76_testmode_enabled(&dev->mt76)) +		mt7915_mac_write_txwi_tm(dev, mphy, txwi, skb); +} -		if (ieee80211_is_back_req(hdr->frame_control)) { -			struct ieee80211_bar *bar; +static void +mt7915_set_tx_blocked(struct mt7915_dev *dev, bool blocked) +{ +	struct mt76_phy *mphy = &dev->mphy, *mphy2 = dev->mt76.phy2; +	struct mt76_queue *q, *q2 = NULL; -			bar = (struct ieee80211_bar *)skb->data; -			seqno = le16_to_cpu(bar->start_seq_num); -		} +	q = mphy->q_tx[0]; +	if (blocked == q->blocked) +		return; -		val |= MT_TXD3_SN_VALID | -		       FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); +	q->blocked = blocked; +	if (mphy2) { +		q2 = mphy2->q_tx[0]; +		q2->blocked = blocked;  	} -	txwi[3] |= cpu_to_le32(val); + +	if (!blocked) +		mt76_worker_schedule(&dev->mt76.tx_worker);  }  int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -723,11 +945,11 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,  	if (!wcid)  		wcid = &dev->mt76.global_wcid; -	cb->wcid = wcid->idx; -  	mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,  			      false); +	cb->wcid = wcid->idx; +  	txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE);  	for (i = 0; i < nbuf; i++) {  		txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); @@ -740,12 +962,13 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,  	tx_info->buf[1].skip_unmap = true;  	tx_info->nbuf = MT_CT_DMA_BUF_NUM; -	txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD); +	txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD | MT_CT_INFO_FROM_HOST);  	if (!key)  		txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); -	if (ieee80211_is_mgmt(hdr->frame_control)) +	if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && +	    ieee80211_is_mgmt(hdr->frame_control))  		txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);  	if (vif) { @@ -759,12 +982,21 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,  	spin_lock_bh(&dev->token_lock);  	id = idr_alloc(&dev->token, t, 0, MT7915_TOKEN_SIZE, GFP_ATOMIC); +	if (id >= 0) +		dev->token_count++; + +	if (dev->token_count >= MT7915_TOKEN_SIZE - MT7915_TOKEN_FREE_THR) +		mt7915_set_tx_blocked(dev, true);  	spin_unlock_bh(&dev->token_lock); +  	if (id < 0)  		return id;  	txp->token = cpu_to_le16(id); -	txp->rept_wds_wcid = 0xff; +	if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) +		txp->rept_wds_wcid = cpu_to_le16(wcid->idx); +	else +		txp->rept_wds_wcid = cpu_to_le16(0x3ff);  	tx_info->skb = DMA_DUMMY_DATA;  	return 0; @@ -795,17 +1027,19 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)  		ieee80211_start_tx_ba_session(sta, tid, 0);  } -static inline void -mt7915_tx_status(struct ieee80211_sta *sta, struct ieee80211_hw *hw, -		 struct ieee80211_tx_info *info, struct sk_buff *skb) +static void +mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb, +			  struct ieee80211_sta *sta, u8 stat, +			  struct list_head *free_list)  { +	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);  	struct ieee80211_tx_status status = {  		.sta = sta,  		.info = info, +		.skb = skb, +		.free_list = free_list,  	}; - -	if (skb) -		status.skb = skb; +	struct ieee80211_hw *hw;  	if (sta) {  		struct mt7915_sta *msta; @@ -814,18 +1048,19 @@ mt7915_tx_status(struct ieee80211_sta *sta, struct ieee80211_hw *hw,  		status.rate = &msta->stats.tx_rate;  	} -	/* use status_ext to report HE rate */ -	ieee80211_tx_status_ext(hw, &status); -} +	hw = mt76_tx_status_get_hw(mdev, skb); -static void -mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb, -			  struct ieee80211_sta *sta, u8 stat) -{ -	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -	struct ieee80211_hw *hw; +#ifdef CONFIG_NL80211_TESTMODE +	if (skb == mdev->test.tx_skb) { +		struct mt7915_phy *phy = mt7915_hw_phy(hw); +		struct ieee80211_vif *vif = phy->monitor_vif; +		struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; -	hw = mt76_tx_status_get_hw(mdev, skb); +		mt76_tx_complete_skb(mdev, mvif->sta.wcid.idx, skb); + +		return; +	} +#endif  	if (info->flags & IEEE80211_TX_CTL_AMPDU)  		info->flags |= IEEE80211_TX_STAT_AMPDU; @@ -837,16 +1072,7 @@ mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb,  		info->flags |= IEEE80211_TX_STAT_ACK;  	info->status.tx_time = 0; - -	if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { -		mt7915_tx_status(sta, hw, info, skb); -		return; -	} - -	if (sta || !(info->flags & IEEE80211_TX_CTL_NO_ACK)) -		mt7915_tx_status(sta, hw, info, NULL); - -	ieee80211_free_txskb(hw, skb); +	ieee80211_tx_status_ext(hw, &status);  }  void mt7915_txp_skb_unmap(struct mt76_dev *dev, @@ -865,13 +1091,21 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)  {  	struct mt7915_tx_free *free = (struct mt7915_tx_free *)skb->data;  	struct mt76_dev *mdev = &dev->mt76; +	struct mt76_phy *mphy_ext = mdev->phy2;  	struct mt76_txwi_cache *txwi;  	struct ieee80211_sta *sta = NULL; +	LIST_HEAD(free_list); +	struct sk_buff *tmp;  	u8 i, count; +	bool wake = false;  	/* clean DMA queues and unmap buffers first */ -	mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false); -	mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false); +	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); +	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); +	if (mphy_ext) { +		mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false); +		mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false); +	}  	/*  	 * TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE, @@ -908,6 +1142,7 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)  			if (list_empty(&msta->poll_list))  				list_add_tail(&msta->poll_list, &dev->sta_poll_list);  			spin_unlock_bh(&dev->sta_poll_lock); +			continue;  		}  		msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); @@ -915,6 +1150,11 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)  		spin_lock_bh(&dev->token_lock);  		txwi = idr_remove(&dev->token, msdu); +		if (txwi) +			dev->token_count--; +		if (dev->token_count < MT7915_TOKEN_SIZE - MT7915_TOKEN_FREE_THR && +		    dev->mphy.q_tx[0]->blocked) +			wake = true;  		spin_unlock_bh(&dev->token_lock);  		if (!txwi) @@ -937,16 +1177,29 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)  					atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);  			} -			mt7915_tx_complete_status(mdev, txwi->skb, sta, stat); +			mt7915_tx_complete_status(mdev, txwi->skb, sta, stat, &free_list);  			txwi->skb = NULL;  		}  		mt76_put_txwi(mdev, txwi);  	} -	dev_kfree_skb(skb);  	mt7915_mac_sta_poll(dev); + +	if (wake) { +		spin_lock_bh(&dev->token_lock); +		mt7915_set_tx_blocked(dev, false); +		spin_unlock_bh(&dev->token_lock); +	} +  	mt76_worker_schedule(&dev->mt76.tx_worker); + +	napi_consume_skb(skb, 1); + +	list_for_each_entry_safe(skb, tmp, &free_list, list) { +		skb_list_del_init(skb); +		napi_consume_skb(skb, 1); +	}  }  void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) @@ -979,7 +1232,8 @@ void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)  		wcid = rcu_dereference(dev->mt76.wcid[cb->wcid]); -		mt7915_tx_complete_status(mdev, e->skb, wcid_to_sta(wcid), 0); +		mt7915_tx_complete_status(mdev, e->skb, wcid_to_sta(wcid), 0, +					  NULL);  	}  } @@ -1081,17 +1335,48 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)  		   MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);  } -/* - * TODO: mib counters are read-clear and there're many HE functionalities need - * such info, hence firmware prepares a task to read the fields out to a shared - * structure. User should switch to use event format to avoid race condition. - */ +void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy) +{ +	mt7915_l2_set(dev, MT_WF_PHY_RXTD12(ext_phy), +		      MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY | +		      MT_WF_PHY_RXTD12_IRPI_SW_CLR); + +	mt7915_l2_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy), +		      FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5)); +} + +static u8 +mt7915_phy_get_nf(struct mt7915_phy *phy, int idx) +{ +	static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 }; +	struct mt7915_dev *dev = phy->dev; +	u32 val, sum = 0, n = 0; +	int nss, i; + +	for (nss = 0; nss < hweight8(phy->chainmask); nss++) { +		u32 reg = MT_WF_IRPI(nss + (idx << dev->dbdc_support)); + +		for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { +			val = mt7915_l2_rr(dev, reg); +			sum += val * nf_power[i]; +			n += val; +		} +	} + +	if (!n) +		return 0; + +	return sum / n; +} +  static void  mt7915_phy_update_channel(struct mt76_phy *mphy, int idx)  {  	struct mt7915_dev *dev = container_of(mphy->dev, struct mt7915_dev, mt76); +	struct mt7915_phy *phy = (struct mt7915_phy *)mphy->priv;  	struct mt76_channel_state *state;  	u64 busy_time, tx_time, rx_time, obss_time; +	int nf;  	busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx),  				   MT_MIB_SDR9_BUSY_MASK); @@ -1102,12 +1387,18 @@ mt7915_phy_update_channel(struct mt76_phy *mphy, int idx)  	obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx),  				   MT_MIB_OBSSTIME_MASK); -	/* TODO: state->noise */ +	nf = mt7915_phy_get_nf(phy, idx); +	if (!phy->noise) +		phy->noise = nf << 4; +	else if (nf) +		phy->noise += nf - (phy->noise >> 4); +  	state = mphy->chan_state;  	state->cc_busy += busy_time;  	state->cc_tx += tx_time;  	state->cc_rx += rx_time + obss_time;  	state->cc_bss_rx += rx_time; +	state->noise = -(phy->noise >> 4);  }  void mt7915_update_channel(struct mt76_dev *mdev) @@ -1162,8 +1453,10 @@ mt7915_update_beacons(struct mt7915_dev *dev)  }  static void -mt7915_dma_reset(struct mt7915_dev *dev) +mt7915_dma_reset(struct mt7915_phy *phy)  { +	struct mt7915_dev *dev = phy->dev; +	struct mt76_phy *mphy_ext = dev->mt76.phy2;  	int i;  	mt76_clear(dev, MT_WFDMA0_GLO_CFG, @@ -1172,8 +1465,12 @@ mt7915_dma_reset(struct mt7915_dev *dev)  		   MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);  	usleep_range(1000, 2000); -	for (i = 0; i < __MT_TXQ_MAX; i++) -		mt76_queue_tx_cleanup(dev, i, true); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true); +	for (i = 0; i < __MT_TXQ_MAX; i++) { +		mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true); +		if (mphy_ext) +			mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true); +	}  	mt76_for_each_q_rx(&dev->mt76, i) {  		mt76_queue_rx_reset(dev, i); @@ -1229,7 +1526,7 @@ void mt7915_mac_reset_work(struct work_struct *work)  	mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);  	if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { -		mt7915_dma_reset(dev); +		mt7915_dma_reset(&dev->phy);  		mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT);  		mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); @@ -1329,7 +1626,7 @@ mt7915_mac_sta_stats_work(struct mt7915_phy *phy)  		spin_unlock_bh(&dev->sta_poll_lock);  		/* use MT_TX_FREE_RATE to report Tx rate for further devices */ -		mt7915_mcu_get_rate_info(dev, RATE_CTRL_RU_INFO, msta->wcid.idx); +		mt7915_mcu_get_tx_rate(dev, RATE_CTRL_RU_INFO, msta->wcid.idx);  		spin_lock_bh(&dev->sta_poll_lock);  	} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index c8bb5ea96c60..d420392b952d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -128,6 +128,11 @@ enum rx_pkt_type {  #define MT_CRXV_HE_BEAM_CHNG		BIT(13)  #define MT_CRXV_HE_DOPPLER		BIT(16) +#define MT_CRXV_SNR		GENMASK(18, 13) +#define MT_CRXV_FOE_LO		GENMASK(31, 19) +#define MT_CRXV_FOE_HI		GENMASK(6, 0) +#define MT_CRXV_FOE_SHIFT	13 +  enum tx_header_format {  	MT_HDR_FORMAT_802_3,  	MT_HDR_FORMAT_CMD, @@ -160,6 +165,7 @@ enum tx_mcu_port_q_idx {  #define MT_CT_INFO_MGMT_FRAME		BIT(2)  #define MT_CT_INFO_NONE_CIPHER_FRAME	BIT(3)  #define MT_CT_INFO_HSR2_TX		BIT(4) +#define MT_CT_INFO_FROM_HOST		BIT(7)  #define MT_TXD_SIZE			(8 * 4) @@ -176,6 +182,7 @@ enum tx_mcu_port_q_idx {  #define MT_TXD1_HDR_PAD			GENMASK(19, 18)  #define MT_TXD1_HDR_FORMAT		GENMASK(17, 16)  #define MT_TXD1_HDR_INFO		GENMASK(15, 11) +#define MT_TXD1_ETH_802_3		BIT(15)  #define MT_TXD1_VTA			BIT(10)  #define MT_TXD1_WLAN_IDX		GENMASK(9, 0) @@ -229,7 +236,7 @@ enum tx_mcu_port_q_idx {  #define MT_TXD6_ANT_ID			GENMASK(7, 4)  #define MT_TXD6_DYN_BW			BIT(3)  #define MT_TXD6_FIXED_BW		BIT(2) -#define MT_TXD6_BW			GENMASK(2, 0) +#define MT_TXD6_BW			GENMASK(1, 0)  #define MT_TXD7_TXD_LEN			GENMASK(31, 30)  #define MT_TXD7_UDP_TCP_SUM		BIT(29) @@ -246,7 +253,9 @@ enum tx_mcu_port_q_idx {  #define MT_TX_RATE_STBC			BIT(13)  #define MT_TX_RATE_NSS			GENMASK(12, 10)  #define MT_TX_RATE_MODE			GENMASK(9, 6) -#define MT_TX_RATE_IDX			GENMASK(5, 0) +#define MT_TX_RATE_SU_EXT_TONE		BIT(5) +#define MT_TX_RATE_DCM			BIT(4) +#define MT_TX_RATE_IDX			GENMASK(3, 0)  #define MT_TXP_MAX_BUF_NUM		6 @@ -254,8 +263,7 @@ struct mt7915_txp {  	__le16 flags;  	__le16 token;  	u8 bss_idx; -	u8 rept_wds_wcid; -	u8 rsv; +	__le16 rept_wds_wcid;  	u8 nbuf;  	__le32 buf[MT_TXP_MAX_BUF_NUM];  	__le16 len[MT_TXP_MAX_BUF_NUM]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index c48158392057..0c82aa2ef219 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -34,21 +34,24 @@ static int mt7915_start(struct ieee80211_hw *hw)  		mt7915_mcu_set_pm(dev, 0, 0);  		mt7915_mcu_set_mac(dev, 0, true, false);  		mt7915_mcu_set_scs(dev, 0, true); +		mt7915_mac_enable_nf(dev, 0);  	}  	if (phy != &dev->phy) {  		mt7915_mcu_set_pm(dev, 1, 0);  		mt7915_mcu_set_mac(dev, 1, true, false);  		mt7915_mcu_set_scs(dev, 1, true); +		mt7915_mac_enable_nf(dev, 1);  	} -	mt7915_mcu_set_sku_en(phy, true); +	mt7915_mcu_set_sku_en(phy, !mt76_testmode_enabled(&dev->mt76));  	mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);  	set_bit(MT76_STATE_RUNNING, &phy->mt76->state); -	ieee80211_queue_delayed_work(hw, &phy->mac_work, -				     MT7915_WATCHDOG_TIME); +	if (!mt76_testmode_enabled(&dev->mt76)) +		ieee80211_queue_delayed_work(hw, &phy->mac_work, +					     MT7915_WATCHDOG_TIME);  	if (!running)  		mt7915_mac_reset_counters(phy); @@ -67,6 +70,8 @@ static void mt7915_stop(struct ieee80211_hw *hw)  	mutex_lock(&dev->mt76.mutex); +	mt76_testmode_reset(&dev->mt76, true); +  	clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);  	if (phy != &dev->phy) { @@ -82,28 +87,51 @@ static void mt7915_stop(struct ieee80211_hw *hw)  	mutex_unlock(&dev->mt76.mutex);  } -static int get_omac_idx(enum nl80211_iftype type, u32 mask) +static inline int get_free_idx(u32 mask, u8 start, u8 end) +{ +	return ffs(~mask & GENMASK(end, start)); +} + +static int get_omac_idx(enum nl80211_iftype type, u64 mask)  {  	int i;  	switch (type) { +	case NL80211_IFTYPE_MESH_POINT: +	case NL80211_IFTYPE_ADHOC: +	case NL80211_IFTYPE_STATION: +		/* prefer hw bssid slot 1-3 */ +		i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3); +		if (i) +			return i - 1; + +		if (type != NL80211_IFTYPE_STATION) +			break; + +		/* next, try to find a free repeater entry for the sta */ +		i = get_free_idx(mask >> REPEATER_BSSID_START, 0, +				 REPEATER_BSSID_MAX - REPEATER_BSSID_START); +		if (i) +			return i + 32 - 1; + +		i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); +		if (i) +			return i - 1; + +		if (~mask & BIT(HW_BSSID_0)) +			return HW_BSSID_0; + +		break;  	case NL80211_IFTYPE_MONITOR:  	case NL80211_IFTYPE_AP:  		/* ap uses hw bssid 0 and ext bssid */  		if (~mask & BIT(HW_BSSID_0))  			return HW_BSSID_0; -		for (i = EXT_BSSID_1; i < EXT_BSSID_END; i++) -			if (~mask & BIT(i)) -				return i; -		break; -	case NL80211_IFTYPE_MESH_POINT: -	case NL80211_IFTYPE_ADHOC: -	case NL80211_IFTYPE_STATION: -		/* station uses hw bssid other than 0 */ -		for (i = HW_BSSID_1; i < HW_BSSID_MAX; i++) -			if (~mask & BIT(i)) -				return i; +		i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); +		if (i) +			return i - 1; +  		break;  	default:  		WARN_ON(1); @@ -125,6 +153,12 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,  	mutex_lock(&dev->mt76.mutex); +	mt76_testmode_reset(&dev->mt76, true); + +	if (vif->type == NL80211_IFTYPE_MONITOR && +	    is_zero_ether_addr(vif->addr)) +		phy->monitor_vif = vif; +  	mvif->idx = ffs(~phy->mt76->vif_mask) - 1;  	if (mvif->idx >= MT7915_MAX_INTERFACES) {  		ret = -ENOSPC; @@ -146,12 +180,12 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,  	else  		mvif->wmm_idx = mvif->idx % MT7915_MAX_WMM_SETS; -	ret = mt7915_mcu_add_dev_info(dev, vif, true); +	ret = mt7915_mcu_add_dev_info(phy, vif, true);  	if (ret)  		goto out;  	phy->mt76->vif_mask |= BIT(mvif->idx); -	phy->omac_mask |= BIT(mvif->omac_idx); +	phy->omac_mask |= BIT_ULL(mvif->omac_idx);  	idx = MT7915_WTBL_RESERVED - mvif->idx; @@ -171,6 +205,11 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,  		mtxq->wcid = &mvif->sta.wcid;  	} +	if (vif->type != NL80211_IFTYPE_AP && +	    (!mvif->omac_idx || mvif->omac_idx > 3)) +		vif->offload_flags = 0; +	vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; +  out:  	mutex_unlock(&dev->mt76.mutex); @@ -188,13 +227,20 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,  	/* TODO: disable beacon for the bss */ -	mt7915_mcu_add_dev_info(dev, vif, false); +	mutex_lock(&dev->mt76.mutex); +	mt76_testmode_reset(&dev->mt76, true); +	mutex_unlock(&dev->mt76.mutex); + +	if (vif == phy->monitor_vif) +		phy->monitor_vif = NULL; + +	mt7915_mcu_add_dev_info(phy, vif, false);  	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);  	mutex_lock(&dev->mt76.mutex);  	phy->mt76->vif_mask &= ~BIT(mvif->idx); -	phy->omac_mask &= ~BIT(mvif->omac_idx); +	phy->omac_mask &= ~BIT_ULL(mvif->omac_idx);  	mutex_unlock(&dev->mt76.mutex);  	spin_lock_bh(&dev->sta_poll_lock); @@ -222,7 +268,7 @@ static void mt7915_init_dfs_state(struct mt7915_phy *phy)  	phy->dfs_state = -1;  } -static int mt7915_set_channel(struct mt7915_phy *phy) +int mt7915_set_channel(struct mt7915_phy *phy)  {  	struct mt7915_dev *dev = phy->dev;  	int ret; @@ -251,8 +297,10 @@ out:  	mutex_unlock(&dev->mt76.mutex);  	mt76_txq_schedule_all(phy->mt76); -	ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work, -				     MT7915_WATCHDOG_TIME); + +	if (!mt76_testmode_enabled(&dev->mt76)) +		ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work, +					     MT7915_WATCHDOG_TIME);  	return ret;  } @@ -283,8 +331,6 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  	case WLAN_CIPHER_SUITE_AES_CMAC:  		key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;  		break; -	case WLAN_CIPHER_SUITE_WEP40: -	case WLAN_CIPHER_SUITE_WEP104:  	case WLAN_CIPHER_SUITE_TKIP:  	case WLAN_CIPHER_SUITE_CCMP:  	case WLAN_CIPHER_SUITE_CCMP_256: @@ -292,6 +338,8 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  	case WLAN_CIPHER_SUITE_GCMP_256:  	case WLAN_CIPHER_SUITE_SMS4:  		break; +	case WLAN_CIPHER_SUITE_WEP40: +	case WLAN_CIPHER_SUITE_WEP104:  	default:  		return -EOPNOTSUPP;  	} @@ -316,6 +364,13 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)  	int ret;  	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { +#ifdef CONFIG_NL80211_TESTMODE +		if (dev->mt76.test.state != MT76_TM_STATE_OFF) { +			mutex_lock(&dev->mt76.mutex); +			mt76_testmode_reset(&dev->mt76, false); +			mutex_unlock(&dev->mt76.mutex); +		} +#endif  		ieee80211_stop_queues(hw);  		ret = mt7915_set_channel(phy);  		if (ret) @@ -332,11 +387,16 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)  	mutex_lock(&dev->mt76.mutex);  	if (changed & IEEE80211_CONF_CHANGE_MONITOR) { -		if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) +		bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); + +		if (!enabled)  			phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;  		else  			phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; +		mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN, +			       enabled); +		mt76_testmode_reset(&dev->mt76, true);  		mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);  	} @@ -764,9 +824,13 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,  				  struct ieee80211_sta *sta,  				  struct station_info *sinfo)  { +	struct mt7915_phy *phy = mt7915_hw_phy(hw);  	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;  	struct mt7915_sta_stats *stats = &msta->stats; +	if (mt7915_mcu_get_rx_rate(phy, vif, sta, &sinfo->rxrate) == 0) +		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); +  	if (!stats->tx_rate.legacy && !stats->tx_rate.flags)  		return; @@ -802,6 +866,22 @@ mt7915_sta_rc_update(struct ieee80211_hw *hw,  	ieee80211_queue_work(hw, &dev->rc_work);  } +static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, +				 struct ieee80211_vif *vif, +				 struct ieee80211_sta *sta, +				 bool enabled) +{ +	struct mt7915_dev *dev = mt7915_hw_dev(hw); +	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + +	if (enabled) +		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); +	else +		clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); + +	mt7915_mcu_sta_update_hdr_trans(dev, vif, sta); +} +  const struct ieee80211_ops mt7915_ops = {  	.tx = mt7915_tx,  	.start = mt7915_start, @@ -833,6 +913,9 @@ const struct ieee80211_ops mt7915_ops = {  	.set_antenna = mt7915_set_antenna,  	.set_coverage_class = mt7915_set_coverage_class,  	.sta_statistics = mt7915_sta_statistics, +	.sta_set_4addr = mt7915_sta_set_4addr, +	CFG80211_TESTMODE_CMD(mt76_testmode_cmd) +	CFG80211_TESTMODE_DUMP(mt76_testmode_dump)  #ifdef CONFIG_MAC80211_DEBUGFS  	.sta_add_debugfs = mt7915_sta_add_debugfs,  #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index a3ccc1785661..5fdd1a6d32ee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -215,32 +215,71 @@ mt7915_mcu_get_sta_nss(u16 mcs_map)  	return nss - 1;  } -static int __mt7915_mcu_msg_send(struct mt7915_dev *dev, struct sk_buff *skb, -				 int cmd, int *wait_seq) +static int +mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd, +			  struct sk_buff *skb, int seq)  { +	struct mt7915_mcu_rxd *rxd; +	int ret = 0; + +	if (!skb) { +		dev_err(mdev->dev, "Message %d (seq %d) timeout\n", +			cmd, seq); +		return -ETIMEDOUT; +	} + +	rxd = (struct mt7915_mcu_rxd *)skb->data; +	if (seq != rxd->seq) +		return -EAGAIN; + +	switch (cmd) { +	case -MCU_CMD_PATCH_SEM_CONTROL: +		skb_pull(skb, sizeof(*rxd) - 4); +		ret = *skb->data; +		break; +	case MCU_EXT_CMD_THERMAL_CTRL: +		skb_pull(skb, sizeof(*rxd) + 4); +		ret = le32_to_cpu(*(__le32 *)skb->data); +		break; +	default: +		skb_pull(skb, sizeof(struct mt7915_mcu_rxd)); +		break; +	} + +	return ret; +} + +static int +mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, +			int cmd, int *wait_seq) +{ +	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);  	struct mt7915_mcu_txd *mcu_txd;  	u8 seq, pkt_fmt, qidx;  	enum mt76_txq_id txq;  	__le32 *txd;  	u32 val; +	/* TODO: make dynamic based on msg type */ +	mdev->mcu.timeout = 20 * HZ; +  	seq = ++dev->mt76.mcu.msg_seq & 0xf;  	if (!seq)  		seq = ++dev->mt76.mcu.msg_seq & 0xf;  	if (cmd == -MCU_CMD_FW_SCATTER) { -		txq = MT_TXQ_FWDL; +		txq = MT_MCUQ_FWDL;  		goto exit;  	}  	mcu_txd = (struct mt7915_mcu_txd *)skb_push(skb, sizeof(*mcu_txd));  	if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) { -		txq = MT_TXQ_MCU_WA; +		txq = MT_MCUQ_WA;  		qidx = MT_TX_MCU_PORT_RX_Q0;  		pkt_fmt = MT_TX_TYPE_CMD;  	} else { -		txq = MT_TXQ_MCU; +		txq = MT_MCUQ_WM;  		qidx = MT_TX_MCU_PORT_RX_Q0;  		pkt_fmt = MT_TX_TYPE_CMD;  	} @@ -276,7 +315,10 @@ static int __mt7915_mcu_msg_send(struct mt7915_dev *dev, struct sk_buff *skb,  			mcu_txd->set_query = MCU_Q_SET;  	} -	mcu_txd->s2d_index = MCU_S2D_H2N; +	if (cmd == MCU_EXT_CMD_MWDS_SUPPORT) +		mcu_txd->s2d_index = MCU_S2D_H2C; +	else +		mcu_txd->s2d_index = MCU_S2D_H2N;  	WARN_ON(cmd == MCU_EXT_CMD_EFUSE_ACCESS &&  		mcu_txd->set_query != MCU_Q_QUERY); @@ -284,116 +326,7 @@ exit:  	if (wait_seq)  		*wait_seq = seq; -	return mt76_tx_queue_skb_raw(dev, txq, skb, 0); -} - -static int -mt7915_mcu_parse_eeprom(struct mt7915_dev *dev, struct sk_buff *skb) -{ -	struct mt7915_mcu_eeprom_info *res; -	u8 *buf; - -	if (!skb) -		return -EINVAL; - -	skb_pull(skb, sizeof(struct mt7915_mcu_rxd)); - -	res = (struct mt7915_mcu_eeprom_info *)skb->data; -	buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); -	memcpy(buf, res->data, 16); - -	return 0; -} - -static int -mt7915_mcu_parse_response(struct mt7915_dev *dev, int cmd, -			  struct sk_buff *skb, int seq) -{ -	struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; -	int ret = 0; - -	if (seq != rxd->seq) { -		ret = -EAGAIN; -		goto out; -	} - -	switch (cmd) { -	case -MCU_CMD_PATCH_SEM_CONTROL: -		skb_pull(skb, sizeof(*rxd) - 4); -		ret = *skb->data; -		break; -	case MCU_EXT_CMD_THERMAL_CTRL: -		skb_pull(skb, sizeof(*rxd) + 4); -		ret = le32_to_cpu(*(__le32 *)skb->data); -		break; -	case MCU_EXT_CMD_EFUSE_ACCESS: -		ret = mt7915_mcu_parse_eeprom(dev, skb); -		break; -	default: -		break; -	} -out: -	dev_kfree_skb(skb); - -	return ret; -} - -static int -mt7915_mcu_wait_response(struct mt7915_dev *dev, int cmd, int seq) -{ -	unsigned long expires = jiffies + 20 * HZ; -	struct sk_buff *skb; -	int ret = 0; - -	while (true) { -		skb = mt76_mcu_get_response(&dev->mt76, expires); -		if (!skb) { -			dev_err(dev->mt76.dev, "Message %d (seq %d) timeout\n", -				cmd, seq); -			return -ETIMEDOUT; -		} - -		ret = mt7915_mcu_parse_response(dev, cmd, skb, seq); -		if (ret != -EAGAIN) -			break; -	} - -	return ret; -} - -static int -mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, -			int cmd, bool wait_resp) -{ -	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); -	int ret, seq; - -	mutex_lock(&mdev->mcu.mutex); - -	ret = __mt7915_mcu_msg_send(dev, skb, cmd, &seq); -	if (ret) -		goto out; - -	if (wait_resp) -		ret = mt7915_mcu_wait_response(dev, cmd, seq); - -out: -	mutex_unlock(&mdev->mcu.mutex); - -	return ret; -} - -static int -mt7915_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, -		    int len, bool wait_resp) -{ -	struct sk_buff *skb; - -	skb = mt76_mcu_msg_alloc(mdev, data, len); -	if (!skb) -		return -ENOMEM; - -	return __mt76_mcu_skb_send_msg(mdev, skb, cmd, wait_resp); +	return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0);  }  static void @@ -419,8 +352,8 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)  }  static void -mt7915_mcu_tx_rate_cal(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra, -		       struct rate_info *rate, u16 r) +mt7915_mcu_tx_rate_parse(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra, +			 struct rate_info *rate, u16 r)  {  	struct ieee80211_supported_band *sband;  	u16 ru_idx = le16_to_cpu(ra->ru_idx); @@ -532,11 +465,11 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb)  		mphy = dev->mt76.phy2;  	/* current rate */ -	mt7915_mcu_tx_rate_cal(mphy, ra, &rate, curr); +	mt7915_mcu_tx_rate_parse(mphy, ra, &rate, curr);  	stats->tx_rate = rate;  	/* probing rate */ -	mt7915_mcu_tx_rate_cal(mphy, ra, &prob_rate, probe); +	mt7915_mcu_tx_rate_parse(mphy, ra, &prob_rate, probe);  	stats->prob_rate = prob_rate;  	if (attempts) { @@ -1005,18 +938,42 @@ mt7915_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7915_phy *phy)  	}  } -static void -mt7915_mcu_bss_sync_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +static int +mt7915_mcu_muar_config(struct mt7915_phy *phy, struct ieee80211_vif *vif, +		       bool bssid, bool enable)  { -	struct bss_info_sync_mode *sync; -	struct tlv *tlv; +	struct mt7915_dev *dev = phy->dev; +	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; +	u32 idx = mvif->omac_idx - REPEATER_BSSID_START; +	u32 mask = phy->omac_mask >> 32 & ~BIT(idx); +	const u8 *addr = vif->addr; +	struct { +		u8 mode; +		u8 force_clear; +		u8 clear_bitmap[8]; +		u8 entry_count; +		u8 write; +		u8 band; -	tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_SYNC_MODE, sizeof(*sync)); +		u8 index; +		u8 bssid; +		u8 addr[ETH_ALEN]; +	} __packed req = { +		.mode = !!mask || enable, +		.entry_count = 1, +		.write = 1, +		.band = phy != &dev->phy, +		.index = idx * 2 + bssid, +	}; -	sync = (struct bss_info_sync_mode *)tlv; -	sync->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); -	sync->dtim_period = vif->bss_conf.dtim_period; -	sync->enable = true; +	if (bssid) +		addr = vif->bss_conf.bssid; + +	if (enable) +		ether_addr_copy(req.addr, addr); + +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MUAR_UPDATE, &req, +				 sizeof(req), true);  }  int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, @@ -1025,6 +982,9 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,  	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;  	struct sk_buff *skb; +	if (mvif->omac_idx >= REPEATER_BSSID_START) +		mt7915_mcu_muar_config(phy, vif, true, enable); +  	skb = mt7915_mcu_alloc_sta_req(phy->dev, mvif, NULL,  				       MT7915_BSS_UPDATE_MAX_SIZE);  	if (IS_ERR(skb)) @@ -1045,14 +1005,13 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,  		if (vif->bss_conf.he_support)  			mt7915_mcu_bss_he_tlv(skb, vif, phy); -		if (mvif->omac_idx > HW_BSSID_MAX) +		if (mvif->omac_idx >= EXT_BSSID_START && +		    mvif->omac_idx < REPEATER_BSSID_START)  			mt7915_mcu_bss_ext_tlv(skb, mvif); -		else -			mt7915_mcu_bss_sync_tlv(skb, vif);  	} -	return __mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, -				       MCU_EXT_CMD_BSS_INFO_UPDATE, true); +	return mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, +				     MCU_EXT_CMD_BSS_INFO_UPDATE, true);  }  /** starec & wtbl **/ @@ -1133,8 +1092,8 @@ int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif,  	if (ret)  		return ret; -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_STA_REC_UPDATE, true);  }  static void @@ -1213,8 +1172,8 @@ mt7915_mcu_sta_ba(struct mt7915_dev *dev,  					     &skb);  	mt7915_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); -	ret = __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				      MCU_EXT_CMD_STA_REC_UPDATE, true); +	ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, +				    MCU_EXT_CMD_STA_REC_UPDATE, true);  	if (ret)  		return ret; @@ -1225,8 +1184,8 @@ mt7915_mcu_sta_ba(struct mt7915_dev *dev,  	mt7915_mcu_sta_ba_tlv(skb, params, enable, tx); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_STA_REC_UPDATE, true);  }  int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, @@ -1508,9 +1467,7 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)  	muru = (struct sta_rec_muru *)tlv;  	muru->cfg.ofdma_dl_en = true; -	muru->cfg.ofdma_ul_en = true;  	muru->cfg.mimo_dl_en = true; -	muru->cfg.mimo_ul_en = true;  	muru->ofdma_dl.punc_pream_rx =  		HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]); @@ -1563,8 +1520,8 @@ mt7915_mcu_add_mu(struct mt7915_dev *dev, struct ieee80211_vif *vif,  	/* starec muru */  	mt7915_mcu_sta_muru_tlv(skb, sta); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_STA_REC_UPDATE, true);  }  static void @@ -1662,7 +1619,7 @@ mt7915_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,  		tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht),  						wtbl_tlv, sta_wtbl);  		ht = (struct wtbl_ht *)tlv; -		ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; +		ht->ldpc = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING);  		ht->af = sta->ht_cap.ampdu_factor;  		ht->mm = sta->ht_cap.ampdu_density;  		ht->ht = true; @@ -1676,7 +1633,7 @@ mt7915_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,  		tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_VHT, sizeof(*vht),  						wtbl_tlv, sta_wtbl);  		vht = (struct wtbl_vht *)tlv; -		vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC, +		vht->ldpc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);  		vht->vht = true;  		af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, @@ -1688,6 +1645,53 @@ mt7915_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,  	mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_tlv);  } +static void +mt7915_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, +			      struct ieee80211_sta *sta, +			      void *sta_wtbl, void *wtbl_tlv) +{ +	struct mt7915_sta *msta; +	struct wtbl_hdr_trans *htr = NULL; +	struct tlv *tlv; + +	tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_HDR_TRANS, sizeof(*htr), +					wtbl_tlv, sta_wtbl); +	htr = (struct wtbl_hdr_trans *)tlv; +	htr->no_rx_trans = true; +	if (vif->type == NL80211_IFTYPE_STATION) +		htr->to_ds = true; +	else +		htr->from_ds = true; + +	if (!sta) +		return; + +	msta = (struct mt7915_sta *)sta->drv_priv; +	if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags)) { +		htr->to_ds = true; +		htr->from_ds = true; +	} +} + +int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, +				    struct ieee80211_vif *vif, +				    struct ieee80211_sta *sta) +{ +	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; +	struct wtbl_req_hdr *wtbl_hdr; +	struct sk_buff *skb; + +	skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, MT7915_WTBL_UPDATE_MAX_SIZE); +	if (!skb) +		return -ENOMEM; + +	wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, NULL, &skb); +	mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr); + +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, +				     true); +} +  int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,  			struct ieee80211_sta *sta)  { @@ -1708,8 +1712,8 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,  					     &skb);  	mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_STA_REC_UPDATE, true);  }  static void @@ -2010,8 +2014,8 @@ mt7915_mcu_add_txbf(struct mt7915_dev *dev, struct ieee80211_vif *vif,  		mt7915_mcu_sta_bfer_tlv(skb, sta, vif, phy, enable); -		r = __mt76_mcu_skb_send_msg(&dev->mt76, skb, -					    MCU_EXT_CMD_STA_REC_UPDATE, true); +		r = mt76_mcu_skb_send_msg(&dev->mt76, skb, +					  MCU_EXT_CMD_STA_REC_UPDATE, true);  		if (r)  			return r;  	} @@ -2026,8 +2030,8 @@ mt7915_mcu_add_txbf(struct mt7915_dev *dev, struct ieee80211_vif *vif,  		mt7915_mcu_sta_bfee_tlv(skb, sta, phy); -		r = __mt76_mcu_skb_send_msg(&dev->mt76, skb, -					    MCU_EXT_CMD_STA_REC_UPDATE, true); +		r = mt76_mcu_skb_send_msg(&dev->mt76, skb, +					  MCU_EXT_CMD_STA_REC_UPDATE, true);  		if (r)  			return r;  	} @@ -2194,8 +2198,8 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,  	mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta); -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_STA_REC_UPDATE, true);  }  static int @@ -2217,11 +2221,11 @@ mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif,  		.action = cpu_to_le32(MT_STA_BSS_GROUP),  		.wlan_idx_lo = to_wcid_lo(msta->wcid.idx),  		.wlan_idx_hi = to_wcid_hi(msta->wcid.idx), -		.val = cpu_to_le32(mvif->idx), +		.val = cpu_to_le32(mvif->idx % 16),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_DRR_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_DRR_CTRL, &req, +				 sizeof(req), true);  }  int mt7915_mcu_add_sta_adv(struct mt7915_dev *dev, struct ieee80211_vif *vif, @@ -2277,12 +2281,13 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,  					     sta_wtbl, &skb);  	if (enable) {  		mt7915_mcu_wtbl_generic_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); +		mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr);  		if (sta)  			mt7915_mcu_wtbl_ht_tlv(skb, sta, sta_wtbl, wtbl_hdr);  	} -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_STA_REC_UPDATE, true);  }  int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev, @@ -2327,13 +2332,14 @@ int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev,  		ra->phy.sgi = ra->phy.mcs * 15;  out: -	return __mt76_mcu_skb_send_msg(&dev->mt76, skb, -				       MCU_EXT_CMD_STA_REC_UPDATE, true); +	return mt76_mcu_skb_send_msg(&dev->mt76, skb, +				     MCU_EXT_CMD_STA_REC_UPDATE, true);  } -int mt7915_mcu_add_dev_info(struct mt7915_dev *dev, +int mt7915_mcu_add_dev_info(struct mt7915_phy *phy,  			    struct ieee80211_vif *vif, bool enable)  { +	struct mt7915_dev *dev = phy->dev;  	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;  	struct {  		struct req_hdr { @@ -2365,9 +2371,12 @@ int mt7915_mcu_add_dev_info(struct mt7915_dev *dev,  		},  	}; +	if (mvif->omac_idx >= REPEATER_BSSID_START) +		return mt7915_mcu_muar_config(phy, vif, false, enable); +  	memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, -				   &data, sizeof(data), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, +				 &data, sizeof(data), true);  }  static void @@ -2458,30 +2467,8 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,  	mt7915_mcu_beacon_cont(dev, rskb, skb, bcn, &offs);  	dev_kfree_skb(skb); -	return __mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, -				       MCU_EXT_CMD_BSS_INFO_UPDATE, true); -} - -static int mt7915_mcu_send_firmware(struct mt7915_dev *dev, const void *data, -				    int len) -{ -	int ret = 0, cur_len; - -	while (len > 0) { -		cur_len = min_t(int, 4096 - sizeof(struct mt7915_mcu_txd), -				len); - -		ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, -					  data, cur_len, false); -		if (ret) -			break; - -		data += cur_len; -		len -= cur_len; -		mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); -	} - -	return ret; +	return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, +				     MCU_EXT_CMD_BSS_INFO_UPDATE, true);  }  static int mt7915_mcu_start_firmware(struct mt7915_dev *dev, u32 addr, @@ -2495,8 +2482,8 @@ static int mt7915_mcu_start_firmware(struct mt7915_dev *dev, u32 addr,  		.addr = cpu_to_le32(addr),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, &req, +				 sizeof(req), true);  }  static int mt7915_mcu_restart(struct mt76_dev *dev) @@ -2508,8 +2495,8 @@ static int mt7915_mcu_restart(struct mt76_dev *dev)  		.power_mode = 1,  	}; -	return __mt76_mcu_send_msg(dev, -MCU_CMD_NIC_POWER_CTRL, &req, -				   sizeof(req), false); +	return mt76_mcu_send_msg(dev, -MCU_CMD_NIC_POWER_CTRL, &req, +				 sizeof(req), false);  }  static int mt7915_mcu_patch_sem_ctrl(struct mt7915_dev *dev, bool get) @@ -2520,8 +2507,8 @@ static int mt7915_mcu_patch_sem_ctrl(struct mt7915_dev *dev, bool get)  		.op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_SEM_CONTROL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_SEM_CONTROL, &req, +				 sizeof(req), true);  }  static int mt7915_mcu_start_patch(struct mt7915_dev *dev) @@ -2533,8 +2520,8 @@ static int mt7915_mcu_start_patch(struct mt7915_dev *dev)  		.check_crc = 0,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_FINISH_REQ, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_FINISH_REQ, &req, +				 sizeof(req), true);  }  static int mt7915_driver_own(struct mt7915_dev *dev) @@ -2570,7 +2557,7 @@ static int mt7915_mcu_init_download(struct mt7915_dev *dev, u32 addr,  	else  		attr = -MCU_CMD_TARGET_ADDRESS_LEN_REQ; -	return __mt76_mcu_send_msg(&dev->mt76, attr, &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, attr, &req, sizeof(req), true);  }  static int mt7915_load_patch(struct mt7915_dev *dev) @@ -2629,7 +2616,8 @@ static int mt7915_load_patch(struct mt7915_dev *dev)  			goto out;  		} -		ret = mt7915_mcu_send_firmware(dev, dl, len); +		ret = mt76_mcu_send_firmware(&dev->mt76, -MCU_CMD_FW_SCATTER, +					     dl, len);  		if (ret) {  			dev_err(dev->mt76.dev, "Failed to send patch\n");  			goto out; @@ -2697,7 +2685,8 @@ mt7915_mcu_send_ram_firmware(struct mt7915_dev *dev,  			return err;  		} -		err = mt7915_mcu_send_firmware(dev, data + offset, len); +		err = mt76_mcu_send_firmware(&dev->mt76, -MCU_CMD_FW_SCATTER, +					     data + offset, len);  		if (err) {  			dev_err(dev->mt76.dev, "Failed to send firmware.\n");  			return err; @@ -2810,7 +2799,7 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)  		return -EIO;  	} -	mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); +	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);  	dev_dbg(dev->mt76.dev, "Firmware init done\n"); @@ -2826,8 +2815,8 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl)  		.ctrl_val = ctrl  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, -				   &data, sizeof(data), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, &data, +				 sizeof(data), true);  }  int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level) @@ -2835,7 +2824,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level)  	struct {  		u8 ver;  		u8 pad; -		u16 len; +		__le16 len;  		u8 level;  		u8 rsv[3];  		__le32 module_idx; @@ -2844,8 +2833,21 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level)  		.level = level,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_DBG_CTRL, -				   &data, sizeof(data), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_DBG_CTRL, &data, +				 sizeof(data), false); +} + +static int mt7915_mcu_set_mwds(struct mt7915_dev *dev, bool enabled) +{ +	struct { +		u8 enable; +		u8 _rsv[3]; +	} __packed req = { +		.enable = enabled +	}; + +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MWDS_SUPPORT, &req, +				 sizeof(req), false);  }  int mt7915_mcu_init(struct mt7915_dev *dev) @@ -2853,12 +2855,12 @@ int mt7915_mcu_init(struct mt7915_dev *dev)  	static const struct mt76_mcu_ops mt7915_mcu_ops = {  		.headroom = sizeof(struct mt7915_mcu_txd),  		.mcu_skb_send_msg = mt7915_mcu_send_message, -		.mcu_send_msg = mt7915_mcu_msg_send, +		.mcu_parse_response = mt7915_mcu_parse_response,  		.mcu_restart = mt7915_mcu_restart,  	};  	int ret; -	dev->mt76.mcu_ops = &mt7915_mcu_ops, +	dev->mt76.mcu_ops = &mt7915_mcu_ops;  	ret = mt7915_driver_own(dev);  	if (ret) @@ -2870,6 +2872,7 @@ int mt7915_mcu_init(struct mt7915_dev *dev)  	set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);  	mt7915_mcu_fw_log_2_host(dev, 0); +	mt7915_mcu_set_mwds(dev, 1);  	return 0;  } @@ -2916,13 +2919,13 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band,  	};  	int ret; -	ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS, -				  &req_trans, sizeof(req_trans), false); +	ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS, +				&req_trans, sizeof(req_trans), false);  	if (ret)  		return ret; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, -				   &req_mac, sizeof(req_mac), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, +				 &req_mac, sizeof(req_mac), true);  }  int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable) @@ -2937,8 +2940,8 @@ int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable)  		.enable = enable + 1,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SCS_CTRL, &req, -				   sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SCS_CTRL, &req, +				 sizeof(req), false);  }  int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val) @@ -2957,8 +2960,8 @@ int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val)  		.pkt_thresh = cpu_to_le32(0x2),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, &req, +				 sizeof(req), true);  }  int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif) @@ -3011,8 +3014,8 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif)  		else  			e->cw_max = cpu_to_le16(10);  	} -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, -				  &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, &req, +				 sizeof(req), true);  }  int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter) @@ -3042,8 +3045,8 @@ int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter)  		.band_idx = band,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, &req, +				 sizeof(req), true);  }  int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, @@ -3063,57 +3066,106 @@ int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev,  		.val = val,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, &req, +				 sizeof(req), true);  }  int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val)  {  	struct { -		u32 tag; -		u16 min_lpn; +		__le32 tag; +		__le16 min_lpn;  		u8 rsv[2];  	} __packed req = { -		.tag = 0x1, -		.min_lpn = val, +		.tag = cpu_to_le32(0x1), +		.min_lpn = cpu_to_le16(val),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, +				 sizeof(req), true);  }  int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,  			    const struct mt7915_dfs_pulse *pulse)  {  	struct { -		u32 tag; -		struct mt7915_dfs_pulse pulse; +		__le32 tag; + +		__le32 max_width;		/* us */ +		__le32 max_pwr;			/* dbm */ +		__le32 min_pwr;			/* dbm */ +		__le32 min_stgr_pri;		/* us */ +		__le32 max_stgr_pri;		/* us */ +		__le32 min_cr_pri;		/* us */ +		__le32 max_cr_pri;		/* us */  	} __packed req = { -		.tag = 0x3, +		.tag = cpu_to_le32(0x3), + +#define __req_field(field) .field = cpu_to_le32(pulse->field) +		__req_field(max_width), +		__req_field(max_pwr), +		__req_field(min_pwr), +		__req_field(min_stgr_pri), +		__req_field(max_stgr_pri), +		__req_field(min_cr_pri), +		__req_field(max_cr_pri), +#undef __req_field  	}; -	memcpy(&req.pulse, pulse, sizeof(*pulse)); - -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, +				 sizeof(req), true);  }  int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,  			    const struct mt7915_dfs_pattern *pattern)  {  	struct { -		u32 tag; -		u16 radar_type; -		struct mt7915_dfs_pattern pattern; +		__le32 tag; +		__le16 radar_type; + +		u8 enb; +		u8 stgr; +		u8 min_crpn; +		u8 max_crpn; +		u8 min_crpr; +		u8 min_pw; +		u32 min_pri; +		u32 max_pri; +		u8 max_pw; +		u8 min_crbn; +		u8 max_crbn; +		u8 min_stgpn; +		u8 max_stgpn; +		u8 min_stgpr; +		u8 rsv[2]; +		u32 min_stgpr_diff;  	} __packed req = { -		.tag = 0x2, -		.radar_type = index, +		.tag = cpu_to_le32(0x2), +		.radar_type = cpu_to_le16(index), + +#define __req_field_u8(field) .field = pattern->field +#define __req_field_u32(field) .field = cpu_to_le32(pattern->field) +		__req_field_u8(enb), +		__req_field_u8(stgr), +		__req_field_u8(min_crpn), +		__req_field_u8(max_crpn), +		__req_field_u8(min_crpr), +		__req_field_u8(min_pw), +		__req_field_u32(min_pri), +		__req_field_u32(max_pri), +		__req_field_u8(max_pw), +		__req_field_u8(min_crbn), +		__req_field_u8(max_crbn), +		__req_field_u8(min_stgpn), +		__req_field_u8(max_stgpn), +		__req_field_u8(min_stgpr), +		__req_field_u32(min_stgpr_diff), +#undef __req_field_u8 +#undef __req_field_u32  	}; -	memcpy(&req.pattern, pattern, sizeof(*pattern)); - -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, +				 sizeof(req), true);  }  int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) @@ -3143,11 +3195,20 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)  		.center_ch = ieee80211_frequency_to_channel(freq1),  		.bw = mt7915_mcu_chan_bw(chandef),  		.tx_streams_num = hweight8(phy->mt76->antenna_mask), -		.rx_streams = phy->chainmask, +		.rx_streams = phy->mt76->antenna_mask,  		.band_idx = phy != &dev->phy,  		.channel_band = chandef->chan->band,  	}; +#ifdef CONFIG_NL80211_TESTMODE +	if (dev->mt76.test.tx_antenna_mask && +	    (dev->mt76.test.state == MT76_TM_STATE_TX_FRAMES || +	     dev->mt76.test.state == MT76_TM_STATE_RX_FRAMES)) { +		req.tx_streams_num = fls(dev->mt76.test.tx_antenna_mask); +		req.rx_streams = dev->mt76.test.tx_antenna_mask; +	} +#endif +  	if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)  		req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;  	else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && @@ -3165,7 +3226,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)  		req.center_ch2 = ieee80211_frequency_to_channel(freq2);  	} -	return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);  }  int mt7915_mcu_set_eeprom(struct mt7915_dev *dev) @@ -3179,8 +3240,8 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)  		.format = EE_FORMAT_WHOLE,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, +				 &req, sizeof(req), true);  }  int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset) @@ -3188,9 +3249,22 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)  	struct mt7915_mcu_eeprom_info req = {  		.addr = cpu_to_le32(round_down(offset, 16)),  	}; +	struct mt7915_mcu_eeprom_info *res; +	struct sk_buff *skb; +	int ret; +	u8 *buf; + +	ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_ACCESS, &req, +				sizeof(req), true, &skb); +	if (ret) +		return ret; + +	res = (struct mt7915_mcu_eeprom_info *)skb->data; +	buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); +	memcpy(buf, res->data, 16); +	dev_kfree_skb(skb); -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_ACCESS, &req, -				   sizeof(req), true); +	return 0;  }  int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index) @@ -3205,11 +3279,11 @@ int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index)  		.action = index,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_THERMAL_CTRL, &req, -				   sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_THERMAL_CTRL, &req, +				 sizeof(req), true);  } -int mt7915_mcu_get_rate_info(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx) +int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx)  {  	struct {  		__le32 cmd; @@ -3223,8 +3297,8 @@ int mt7915_mcu_get_rate_info(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx)  		.dump_group = cpu_to_le16(1),  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RATE_CTRL, &req, -				   sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RATE_CTRL, &req, +				 sizeof(req), false);  }  int mt7915_mcu_set_sku(struct mt7915_phy *phy) @@ -3251,9 +3325,31 @@ int mt7915_mcu_set_sku(struct mt7915_phy *phy)  	for (i = 0; i < MT7915_SKU_RATE_NUM; i++)  		req.val[i] = hw->conf.power_level * 2 + delta[i]; -	return __mt76_mcu_send_msg(&dev->mt76, -				   MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, +				 MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, +				 sizeof(req), true); +} + +int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, +			      u8 en) +{ +	struct { +		u8 test_mode_en; +		u8 param_idx; +		u8 _rsv[2]; + +		u8 enable; +		u8 _rsv2[3]; + +		u8 pad[8]; +	} __packed req = { +		.test_mode_en = test_mode, +		.param_idx = param, +		.enable = en, +	}; + +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, +				 sizeof(req), false);  }  int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable) @@ -3270,9 +3366,9 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)  		.sku_enable = enable,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, -				   MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, +				 MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, +				 sizeof(req), true);  }  int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band) @@ -3288,8 +3384,8 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)  		.band = band,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SER_TRIGGER, -				   &req, sizeof(req), false); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SER_TRIGGER, +				 &req, sizeof(req), false);  }  int mt7915_mcu_set_txbf_type(struct mt7915_dev *dev) @@ -3306,8 +3402,8 @@ int mt7915_mcu_set_txbf_type(struct mt7915_dev *dev)  		.ibf = false,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, &req, +				 sizeof(req), true);  }  int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev) @@ -3325,8 +3421,8 @@ int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev)  		.snd_mode = MT_BF_PROCESSING,  	}; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, -				   &req, sizeof(req), true); +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, &req, +				 sizeof(req), true);  }  int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, @@ -3342,14 +3438,112 @@ int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,  		u8 drop_tx_idx;  		u8 sta_idx;	/* 256 sta */  		u8 rsv[2]; -		u32 val; +		__le32 val;  	} __packed req = {  		.action = MT_SPR_ENABLE,  		.arg_num = 1,  		.band_idx = mvif->band_idx, -		.val = enable, +		.val = cpu_to_le32(enable), +	}; + +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR, &req, +				 sizeof(req), true); +} + +int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, +			   struct ieee80211_sta *sta, struct rate_info *rate) +{ +	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; +	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; +	struct mt7915_dev *dev = phy->dev; +	struct mt76_phy *mphy = phy->mt76; +	struct { +		u8 category; +		u8 band; +		__le16 wcid; +	} __packed req = { +		.category = MCU_PHY_STATE_CONTENTION_RX_RATE, +		.band = mvif->band_idx, +		.wcid = cpu_to_le16(msta->wcid.idx),  	}; +	struct ieee80211_supported_band *sband; +	struct mt7915_mcu_phy_rx_info *res; +	struct sk_buff *skb; +	u16 flags = 0; +	int ret; +	int i; + +	ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD_PHY_STAT_INFO, +					&req, sizeof(req), true, &skb); +	if (ret) +		return ret; + +	res = (struct mt7915_mcu_phy_rx_info *)skb->data; + +	rate->mcs = res->rate; +	rate->nss = res->nsts + 1; + +	switch (res->mode) { +	case MT_PHY_TYPE_CCK: +	case MT_PHY_TYPE_OFDM: +		if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) +			sband = &mphy->sband_5g.sband; +		else +			sband = &mphy->sband_2g.sband; + +		for (i = 0; i < sband->n_bitrates; i++) { +			if (rate->mcs != (sband->bitrates[i].hw_value & 0xf)) +				continue; + +			rate->legacy = sband->bitrates[i].bitrate; +			break; +		} +		break; +	case MT_PHY_TYPE_HT: +	case MT_PHY_TYPE_HT_GF: +		if (rate->mcs > 31) +			return -EINVAL; -	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR, -				   &req, sizeof(req), true); +		flags |= RATE_INFO_FLAGS_MCS; + +		if (res->gi) +			flags |= RATE_INFO_FLAGS_SHORT_GI; +		break; +	case MT_PHY_TYPE_VHT: +		flags |= RATE_INFO_FLAGS_VHT_MCS; + +		if (res->gi) +			flags |= RATE_INFO_FLAGS_SHORT_GI; +		break; +	case MT_PHY_TYPE_HE_SU: +	case MT_PHY_TYPE_HE_EXT_SU: +	case MT_PHY_TYPE_HE_TB: +	case MT_PHY_TYPE_HE_MU: +		rate->he_gi = res->gi; + +		flags |= RATE_INFO_FLAGS_HE_MCS; +		break; +	default: +		break; +	} +	rate->flags = flags; + +	switch (res->bw) { +	case IEEE80211_STA_RX_BW_160: +		rate->bw = RATE_INFO_BW_160; +		break; +	case IEEE80211_STA_RX_BW_80: +		rate->bw = RATE_INFO_BW_80; +		break; +	case IEEE80211_STA_RX_BW_40: +		rate->bw = RATE_INFO_BW_40; +		break; +	default: +		rate->bw = RATE_INFO_BW_20; +		break; +	} + +	dev_kfree_skb(skb); + +	return 0;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index c656d66385c4..cd1a4256c843 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -46,6 +46,11 @@ enum {  	MCU_EXT_EVENT_RATE_REPORT = 0x87,  }; +enum { +	MCU_ATE_SET_TRX = 0x1, +	MCU_ATE_SET_FREQ_OFFSET = 0xa, +}; +  struct mt7915_mcu_rxd {  	__le32 rxd[6]; @@ -153,6 +158,18 @@ struct mt7915_mcu_ra_info {  	u8 prob_down_pending;  } __packed; + +struct mt7915_mcu_phy_rx_info { +	u8 category; +	u8 rate; +	u8 mode; +	u8 nsts; +	u8 gi; +	u8 coding; +	u8 stbc; +	u8 bw; +}; +  #define MT_RA_RATE_NSS			GENMASK(8, 6)  #define MT_RA_RATE_MCS			GENMASK(3, 0)  #define MT_RA_RATE_TX_MODE		GENMASK(12, 9) @@ -201,19 +218,24 @@ enum {  	MCU_EXT_CMD_EDCA_UPDATE = 0x27,  	MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A,  	MCU_EXT_CMD_THERMAL_CTRL = 0x2c, +	MCU_EXT_CMD_WTBL_UPDATE = 0x32,  	MCU_EXT_CMD_SET_DRR_CTRL = 0x36,  	MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, +	MCU_EXT_CMD_ATE_CTRL = 0x3d,  	MCU_EXT_CMD_PROTECT_CTRL = 0x3e,  	MCU_EXT_CMD_MAC_INIT_CTRL = 0x46,  	MCU_EXT_CMD_RX_HDR_TRANS = 0x47, +	MCU_EXT_CMD_MUAR_UPDATE = 0x48,  	MCU_EXT_CMD_SET_RX_PATH = 0x4e,  	MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, +	MCU_EXT_CMD_MWDS_SUPPORT = 0x80,  	MCU_EXT_CMD_SET_SER_TRIGGER = 0x81,  	MCU_EXT_CMD_SCS_CTRL = 0x82,  	MCU_EXT_CMD_RATE_CTRL = 0x87,  	MCU_EXT_CMD_FW_DBG_CTRL = 0x95,  	MCU_EXT_CMD_SET_RDD_TH = 0x9d,  	MCU_EXT_CMD_SET_SPR = 0xa8, +	MCU_EXT_CMD_PHY_STAT_INFO = 0xad,  };  enum { @@ -247,6 +269,14 @@ enum {  	EE_FORMAT_MULTIPLE,  }; +enum { +	MCU_PHY_STATE_TX_RATE, +	MCU_PHY_STATE_RX_RATE, +	MCU_PHY_STATE_RSSI, +	MCU_PHY_STATE_CONTENTION_RX_RATE, +	MCU_PHY_STATE_OFDMLQ_CNINFO, +}; +  #define STA_TYPE_STA			BIT(0)  #define STA_TYPE_AP			BIT(1)  #define STA_TYPE_ADHOC			BIT(2) @@ -354,15 +384,6 @@ struct bss_info_ext_bss {  	u8 rsv[8];  } __packed; -struct bss_info_sync_mode { -	__le16 tag; -	__le16 len; -	__le16 bcn_interval; -	u8 enable; -	u8 dtim_period; -	u8 rsv[8]; -} __packed; -  struct bss_info_bmc_rate {  	__le16 tag;  	__le16 len; @@ -480,7 +501,7 @@ enum {  	BSS_INFO_LQ_RM,		/* obsoleted */  	BSS_INFO_EXT_BSS,  	BSS_INFO_BMC_RATE,	/* for bmc rate control in CR4 */ -	BSS_INFO_SYNC_MODE, +	BSS_INFO_SYNC_MODE,	/* obsoleted */  	BSS_INFO_RA,  	BSS_INFO_HW_AMSDU,  	BSS_INFO_BSS_COLOR, @@ -551,6 +572,15 @@ struct wtbl_vht {  	u8 rsv[4];  } __packed; +struct wtbl_hdr_trans { +	__le16 tag; +	__le16 len; +	u8 to_ds; +	u8 from_ds; +	u8 no_rx_trans; +	u8 _rsv; +}; +  enum {  	MT_BA_TYPE_INVALID,  	MT_BA_TYPE_ORIGINATOR, @@ -972,6 +1002,7 @@ enum {  					 sizeof(struct wtbl_rx) +	\  					 sizeof(struct wtbl_ht) +	\  					 sizeof(struct wtbl_vht) +	\ +					 sizeof(struct wtbl_hdr_trans) +\  					 sizeof(struct wtbl_ba) +	\  					 sizeof(struct wtbl_smps)) @@ -997,8 +1028,7 @@ enum {  					 sizeof(struct bss_info_hw_amsdu) +\  					 sizeof(struct bss_info_he) +	\  					 sizeof(struct bss_info_bmc_rate) +\ -					 sizeof(struct bss_info_ext_bss) +\ -					 sizeof(struct bss_info_sync_mode)) +					 sizeof(struct bss_info_ext_bss))  #define MT7915_BEACON_UPDATE_SIZE	(sizeof(struct sta_req_hdr) +	\  					 sizeof(struct bss_info_bcn_csa) + \ diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 4b8908fa7eda..0339abf360d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -9,7 +9,7 @@  #include "../mt76.h"  #include "regs.h" -#define MT7915_MAX_INTERFACES		4 +#define MT7915_MAX_INTERFACES		32  #define MT7915_MAX_WMM_SETS		4  #define MT7915_WTBL_SIZE		288  #define MT7915_WTBL_RESERVED		(MT7915_WTBL_SIZE - 1) @@ -32,6 +32,7 @@  #define MT7915_EEPROM_SIZE		3584  #define MT7915_TOKEN_SIZE		8192 +#define MT7915_TOKEN_FREE_THR		64  #define MT7915_CFEND_RATE_DEFAULT	0x49	/* OFDM 24M */  #define MT7915_CFEND_RATE_11B		0x03	/* 11B LP, 11M */ @@ -112,8 +113,10 @@ struct mt7915_phy {  	struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES]; +	struct ieee80211_vif *monitor_vif; +  	u32 rxfilter; -	u32 omac_mask; +	u64 omac_mask;  	u16 noise;  	u16 chainmask; @@ -159,11 +162,27 @@ struct mt7915_dev {  	u32 hw_pattern;  	spinlock_t token_lock; +	int token_count;  	struct idr token;  	s8 **rate_power; /* TODO: use mt76_rate_power */ +	bool dbdc_support;  	bool fw_debug; + +#ifdef CONFIG_NL80211_TESTMODE +	struct { +		u32 *reg_backup; + +		s32 last_freq_offset; +		u8 last_rcpi[4]; +		s8 last_ib_rssi[4]; +		s8 last_wb_rssi[4]; +		u8 last_snr; + +		u8 spe_idx; +	} test; +#endif  };  enum { @@ -171,24 +190,13 @@ enum {  	HW_BSSID_1,  	HW_BSSID_2,  	HW_BSSID_3, -	HW_BSSID_MAX, +	HW_BSSID_MAX = HW_BSSID_3,  	EXT_BSSID_START = 0x10,  	EXT_BSSID_1, -	EXT_BSSID_2, -	EXT_BSSID_3, -	EXT_BSSID_4, -	EXT_BSSID_5, -	EXT_BSSID_6, -	EXT_BSSID_7, -	EXT_BSSID_8, -	EXT_BSSID_9, -	EXT_BSSID_10, -	EXT_BSSID_11, -	EXT_BSSID_12, -	EXT_BSSID_13, -	EXT_BSSID_14, -	EXT_BSSID_15, -	EXT_BSSID_END +	EXT_BSSID_15 = 0x1f, +	EXT_BSSID_MAX = EXT_BSSID_15, +	REPEATER_BSSID_START = 0x20, +	REPEATER_BSSID_MAX = 0x3f,  };  enum { @@ -264,15 +272,14 @@ static inline u8 mt7915_lmac_mapping(struct mt7915_dev *dev, u8 ac)  extern const struct ieee80211_ops mt7915_ops;  extern struct pci_driver mt7915_pci_driver; +extern const struct mt76_testmode_ops mt7915_testmode_ops;  u32 mt7915_reg_map(struct mt7915_dev *dev, u32 addr);  int mt7915_register_device(struct mt7915_dev *dev);  void mt7915_unregister_device(struct mt7915_dev *dev); -int mt7915_register_ext_phy(struct mt7915_dev *dev); -void mt7915_unregister_ext_phy(struct mt7915_dev *dev);  int mt7915_eeprom_init(struct mt7915_dev *dev); -u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset); +void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy);  int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,  				   struct ieee80211_channel *chan,  				   u8 chain_idx); @@ -281,7 +288,7 @@ int mt7915_dma_init(struct mt7915_dev *dev);  void mt7915_dma_prefetch(struct mt7915_dev *dev);  void mt7915_dma_cleanup(struct mt7915_dev *dev);  int mt7915_mcu_init(struct mt7915_dev *dev); -int mt7915_mcu_add_dev_info(struct mt7915_dev *dev, +int mt7915_mcu_add_dev_info(struct mt7915_phy *phy,  			    struct ieee80211_vif *vif, bool enable);  int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,  			    struct ieee80211_vif *vif, int enable); @@ -289,6 +296,9 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,  		       struct ieee80211_sta *sta, bool enable);  int mt7915_mcu_add_sta_adv(struct mt7915_dev *dev, struct ieee80211_vif *vif,  			   struct ieee80211_sta *sta, bool enable); +int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, +				    struct ieee80211_vif *vif, +				    struct ieee80211_sta *sta);  int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev,  			 struct ieee80211_ampdu_params *params,  			 bool add); @@ -306,6 +316,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,  			     struct ieee80211_sta *sta);  int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,  			struct ieee80211_sta *sta); +int mt7915_set_channel(struct mt7915_phy *phy);  int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd);  int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif);  int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev, @@ -314,6 +325,8 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);  int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);  int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,  		       bool hdr_trans); +int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, +			      u8 en);  int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable);  int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band);  int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val); @@ -327,8 +340,10 @@ int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,  			    const struct mt7915_dfs_pulse *pulse);  int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,  			    const struct mt7915_dfs_pattern *pattern); -int mt7915_mcu_get_rate_info(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx);  int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index); +int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx); +int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, +			   struct ieee80211_sta *sta, struct rate_info *rate);  int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, enum mt7915_rdd_cmd cmd,  		       u8 index, u8 rx_sel, u8 val);  int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl); @@ -428,11 +443,13 @@ mt7915_l2_rmw(struct mt7915_dev *dev, u32 addr, u32 mask, u32 val)  bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask);  void mt7915_mac_reset_counters(struct mt7915_phy *phy);  void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy); +void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy);  void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,  			   struct sk_buff *skb, struct mt76_wcid *wcid,  			   struct ieee80211_key_conf *key, bool beacon);  void mt7915_mac_set_timing(struct mt7915_phy *phy);  int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb); +void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb);  void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb);  int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,  		       struct ieee80211_sta *sta); @@ -446,6 +463,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,  			  struct ieee80211_sta *sta,  			  struct mt76_tx_info *tx_info);  void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); +int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc);  void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,  			 struct sk_buff *skb);  void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c index fe62b4d853e4..aeb86fbea41c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -21,8 +21,14 @@ static void  mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)  {  	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); +	static const u32 rx_irq_mask[] = { +		[MT_RXQ_MAIN] = MT_INT_RX_DONE_DATA0, +		[MT_RXQ_EXT] = MT_INT_RX_DONE_DATA1, +		[MT_RXQ_MCU] = MT_INT_RX_DONE_WM, +		[MT_RXQ_MCU_WA] = MT_INT_RX_DONE_WA, +	}; -	mt7915_irq_enable(dev, MT_INT_RX_DONE(q)); +	mt7915_irq_enable(dev, rx_irq_mask[q]);  }  /* TODO: support 2/4/6/8 MSI-X vectors */ @@ -49,14 +55,17 @@ static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)  	if (intr & MT_INT_TX_DONE_MCU)  		napi_schedule(&dev->mt76.tx_napi); -	if (intr & MT_INT_RX_DONE_DATA) -		napi_schedule(&dev->mt76.napi[0]); +	if (intr & MT_INT_RX_DONE_DATA0) +		napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); + +	if (intr & MT_INT_RX_DONE_DATA1) +		napi_schedule(&dev->mt76.napi[MT_RXQ_EXT]);  	if (intr & MT_INT_RX_DONE_WM) -		napi_schedule(&dev->mt76.napi[1]); +		napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]);  	if (intr & MT_INT_RX_DONE_WA) -		napi_schedule(&dev->mt76.napi[2]); +		napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]);  	if (intr & MT_INT_MCU_CMD) {  		u32 val = mt76_rr(dev, MT_MCU_CMD); @@ -140,7 +149,7 @@ static int mt7915_pci_probe(struct pci_dev *pdev,  	dev = container_of(mdev, struct mt7915_dev, mt76);  	ret = mt7915_alloc_device(pdev, dev);  	if (ret) -		return ret; +		goto error;  	mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);  	mdev->rev = (mt7915_l1_rr(dev, MT_HW_CHIPID) << 16) | @@ -163,7 +172,8 @@ static int mt7915_pci_probe(struct pci_dev *pdev,  	return 0;  error: -	ieee80211_free_hw(mt76_hw(dev)); +	mt76_free_device(&dev->mt76); +  	return ret;  } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index 64327153b7fa..848703e6eb7c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -51,6 +51,9 @@  #define MT_WF_TMAC_BASE(_band)		((_band) ? 0xa1000 : 0x21000)  #define MT_WF_TMAC(_band, ofs)		(MT_WF_TMAC_BASE(_band) + (ofs)) +#define MT_TMAC_TCR0(_band)		MT_WF_TMAC(_band, 0) +#define MT_TMAC_TCR0_TBTT_STOP_CTRL	BIT(25) +  #define MT_TMAC_CDTR(_band)		MT_WF_TMAC(_band, 0x090)  #define MT_TMAC_ODTR(_band)		MT_WF_TMAC(_band, 0x094)  #define MT_TIMEOUT_VAL_PLCP		GENMASK(15, 0) @@ -67,11 +70,13 @@  #define MT_TMAC_CTCR0_INS_DDLMT_EN		BIT(17)  #define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN	BIT(18) -/* DMA Band 0 */ -#define MT_WF_DMA_BASE			0x21e00 -#define MT_WF_DMA(ofs)			(MT_WF_DMA_BASE + (ofs)) +#define MT_TMAC_TRCR0(_band)		MT_WF_TMAC(_band, 0x09c) +#define MT_TMAC_TFCR0(_band)		MT_WF_TMAC(_band, 0x1e0) + +#define MT_WF_DMA_BASE(_band)		((_band) ? 0xa1e00 : 0x21e00) +#define MT_WF_DMA(_band, ofs)		(MT_WF_DMA_BASE(_band) + (ofs)) -#define MT_DMA_DCR0			MT_WF_DMA(0x000) +#define MT_DMA_DCR0(_band)		MT_WF_DMA(_band, 0x000)  #define MT_DMA_DCR0_MAX_RX_LEN		GENMASK(15, 3)  #define MT_DMA_DCR0_RXD_G5_EN		BIT(23) @@ -166,10 +171,33 @@  #define MT_WF_AGG_BASE(_band)		((_band) ? 0xa0800 : 0x20800)  #define MT_WF_AGG(_band, ofs)		(MT_WF_AGG_BASE(_band) + (ofs)) +#define MT_AGG_AWSCR0(_band, _n)	MT_WF_AGG(_band, 0x05c + (_n) * 4) +#define MT_AGG_PCR0(_band, _n)		MT_WF_AGG(_band, 0x06c + (_n) * 4) +#define MT_AGG_PCR0_MM_PROT		BIT(0) +#define MT_AGG_PCR0_GF_PROT		BIT(1) +#define MT_AGG_PCR0_BW20_PROT		BIT(2) +#define MT_AGG_PCR0_BW40_PROT		BIT(4) +#define MT_AGG_PCR0_BW80_PROT		BIT(6) +#define MT_AGG_PCR0_ERP_PROT		GENMASK(12, 8) +#define MT_AGG_PCR0_VHT_PROT		BIT(13) +#define MT_AGG_PCR0_PTA_WIN_DIS		BIT(15) + +#define MT_AGG_PCR1_RTS0_NUM_THRES	GENMASK(31, 23) +#define MT_AGG_PCR1_RTS0_LEN_THRES	GENMASK(19, 0) +  #define MT_AGG_ACR0(_band)		MT_WF_AGG(_band, 0x084)  #define MT_AGG_ACR_CFEND_RATE		GENMASK(13, 0)  #define MT_AGG_ACR_BAR_RATE		GENMASK(29, 16) +#define MT_AGG_MRCR(_band)		MT_WF_AGG(_band, 0x098) +#define MT_AGG_MRCR_BAR_CNT_LIMIT	GENMASK(15, 12) +#define MT_AGG_MRCR_LAST_RTS_CTS_RN	BIT(6) +#define MT_AGG_MRCR_RTS_FAIL_LIMIT	GENMASK(11, 7) +#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT	GENMASK(28, 24) + +#define MT_AGG_ATCR1(_band)		MT_WF_AGG(_band, 0x0f0) +#define MT_AGG_ATCR3(_band)		MT_WF_AGG(_band, 0x0f4) +  /* ARB: band 0(0x20c00), band 1(0xa0c00) */  #define MT_WF_ARB_BASE(_band)		((_band) ? 0xa0c00 : 0x20c00)  #define MT_WF_ARB(_band, ofs)		(MT_WF_ARB_BASE(_band) + (ofs)) @@ -178,6 +206,8 @@  #define MT_ARB_SCR_TX_DISABLE		BIT(8)  #define MT_ARB_SCR_RX_DISABLE		BIT(9) +#define MT_ARB_DRNGR0(_band, _n)	MT_WF_ARB(_band, 0x194 + (_n) * 4) +  /* RMAC: band 0(0x21400), band 1(0xa1400) */  #define MT_WF_RMAC_BASE(_band)		((_band) ? 0xa1400 : 0x21400)  #define MT_WF_RMAC(_band, ofs)		(MT_WF_RMAC_BASE(_band) + (ofs)) @@ -308,11 +338,11 @@  #define MT_INT_SOURCE_CSR		MT_WFDMA_EXT_CSR(0x10)  #define MT_INT_MASK_CSR			MT_WFDMA_EXT_CSR(0x14) -#define MT_INT_RX_DONE_DATA		BIT(16) +#define MT_INT_RX_DONE_DATA0		BIT(16) +#define MT_INT_RX_DONE_DATA1		BIT(17)  #define MT_INT_RX_DONE_WM		BIT(0)  #define MT_INT_RX_DONE_WA		BIT(1) -#define MT_INT_RX_DONE(_n)		((_n) ? BIT((_n) - 1) : BIT(16)) -#define MT_INT_RX_DONE_ALL		(BIT(0) | BIT(1) | BIT(16)) +#define MT_INT_RX_DONE_ALL		(BIT(0) | BIT(1) | GENMASK(17, 16))  #define MT_INT_TX_DONE_MCU_WA		BIT(15)  #define MT_INT_TX_DONE_FWDL		BIT(26)  #define MT_INT_TX_DONE_MCU_WM		BIT(27) @@ -385,11 +415,19 @@  #define MT_PCIE_MAC(ofs)		(MT_PCIE_MAC_BASE + (ofs))  #define MT_PCIE_MAC_INT_ENABLE		MT_PCIE_MAC(0x188) +#define MT_WF_IRPI_BASE			0x83006000 +#define MT_WF_IRPI(ofs)			(MT_WF_IRPI_BASE + ((ofs) << 16)) +  /* PHY: band 0(0x83080000), band 1(0x83090000) */  #define MT_WF_PHY_BASE			0x83080000  #define MT_WF_PHY(ofs)			(MT_WF_PHY_BASE + (ofs))  #define MT_WF_PHY_RX_CTRL1(_phy)	MT_WF_PHY(0x2004 + ((_phy) << 16)) +#define MT_WF_PHY_RX_CTRL1_IPI_EN	GENMASK(2, 0)  #define MT_WF_PHY_RX_CTRL1_STSCNT_EN	GENMASK(11, 9) +#define MT_WF_PHY_RXTD12(_phy)		MT_WF_PHY(0x8230 + ((_phy) << 16)) +#define MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY	BIT(18) +#define MT_WF_PHY_RXTD12_IRPI_SW_CLR	BIT(29) +  #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c new file mode 100644 index 000000000000..9ee82e2d262c --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include "mt7915.h" +#include "mac.h" +#include "mcu.h" +#include "testmode.h" + +enum { +	TM_CHANGED_TXPOWER, +	TM_CHANGED_FREQ_OFFSET, + +	/* must be last */ +	NUM_TM_CHANGED +}; + +static const u8 tm_change_map[] = { +	[TM_CHANGED_TXPOWER] = MT76_TM_ATTR_TX_POWER, +	[TM_CHANGED_FREQ_OFFSET] = MT76_TM_ATTR_FREQ_OFFSET, +}; + +struct reg_band { +	u32 band[2]; +}; + +#define REG_BAND(_reg) \ +	{ .band[0] = MT_##_reg(0), .band[1] = MT_##_reg(1) } +#define REG_BAND_IDX(_reg, _idx) \ +	{ .band[0] = MT_##_reg(0, _idx), .band[1] = MT_##_reg(1, _idx) } + +static const struct reg_band reg_backup_list[] = { +	REG_BAND_IDX(AGG_PCR0, 0), +	REG_BAND_IDX(AGG_PCR0, 1), +	REG_BAND_IDX(AGG_AWSCR0, 0), +	REG_BAND_IDX(AGG_AWSCR0, 1), +	REG_BAND_IDX(AGG_AWSCR0, 2), +	REG_BAND_IDX(AGG_AWSCR0, 3), +	REG_BAND(AGG_MRCR), +	REG_BAND(TMAC_TFCR0), +	REG_BAND(TMAC_TCR0), +	REG_BAND(AGG_ATCR1), +	REG_BAND(AGG_ATCR3), +	REG_BAND(TMAC_TRCR0), +	REG_BAND(TMAC_ICR0), +	REG_BAND_IDX(ARB_DRNGR0, 0), +	REG_BAND_IDX(ARB_DRNGR0, 1), +	REG_BAND(WF_RFCR), +	REG_BAND(WF_RFCR1), +}; + +static int +mt7915_tm_set_tx_power(struct mt7915_phy *phy) +{ +	struct mt7915_dev *dev = phy->dev; +	struct mt76_phy *mphy = phy->mt76; +	struct cfg80211_chan_def *chandef = &mphy->chandef; +	int freq = chandef->center_freq1; +	int ret; +	struct { +		u8 format_id; +		u8 dbdc_idx; +		s8 tx_power; +		u8 ant_idx;	/* Only 0 is valid */ +		u8 center_chan; +		u8 rsv[3]; +	} __packed req = { +		.format_id = 0xf, +		.dbdc_idx = phy != &dev->phy, +		.center_chan = ieee80211_frequency_to_channel(freq), +	}; +	u8 *tx_power = NULL; + +	if (dev->mt76.test.state != MT76_TM_STATE_OFF) +		tx_power = dev->mt76.test.tx_power; + +	/* Tx power of the other antennas are the same as antenna 0 */ +	if (tx_power && tx_power[0]) +		req.tx_power = tx_power[0]; + +	ret = mt76_mcu_send_msg(&dev->mt76, +				MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, +				&req, sizeof(req), false); + +	return ret; +} + +static int +mt7915_tm_set_freq_offset(struct mt7915_dev *dev, bool en, u32 val) +{ +	struct mt7915_tm_cmd req = { +		.testmode_en = en, +		.param_idx = MCU_ATE_SET_FREQ_OFFSET, +		.param.freq.freq_offset = cpu_to_le32(val), +	}; + +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, +				 sizeof(req), false); +} + +static int +mt7915_tm_mode_ctrl(struct mt7915_dev *dev, bool enable) +{ +	struct { +		u8 format_id; +		bool enable; +		u8 rsv[2]; +	} __packed req = { +		.format_id = 0x6, +		.enable = enable, +	}; + +	return mt76_mcu_send_msg(&dev->mt76, +				 MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, +				 &req, sizeof(req), false); +} + +static int +mt7915_tm_set_trx(struct mt7915_dev *dev, struct mt7915_phy *phy, +		  int type, bool en) +{ +	struct mt7915_tm_cmd req = { +		.testmode_en = 1, +		.param_idx = MCU_ATE_SET_TRX, +		.param.trx.type = type, +		.param.trx.enable = en, +		.param.trx.band = phy != &dev->phy, +	}; + +	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req, +				 sizeof(req), false); +} + +static void +mt7915_tm_reg_backup_restore(struct mt7915_dev *dev, struct mt7915_phy *phy) +{ +	int n_regs = ARRAY_SIZE(reg_backup_list); +	bool ext_phy = phy != &dev->phy; +	u32 *b = dev->test.reg_backup; +	int i; + +	if (dev->mt76.test.state == MT76_TM_STATE_OFF) { +		for (i = 0; i < n_regs; i++) +			mt76_wr(dev, reg_backup_list[i].band[ext_phy], b[i]); +		return; +	} + +	if (b) +		return; + +	b = devm_kzalloc(dev->mt76.dev, 4 * n_regs, GFP_KERNEL); +	if (!b) +		return; + +	dev->test.reg_backup = b; +	for (i = 0; i < n_regs; i++) +		b[i] = mt76_rr(dev, reg_backup_list[i].band[ext_phy]); + +	mt76_clear(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_MM_PROT | +		   MT_AGG_PCR0_GF_PROT | MT_AGG_PCR0_ERP_PROT | +		   MT_AGG_PCR0_VHT_PROT | MT_AGG_PCR0_BW20_PROT | +		   MT_AGG_PCR0_BW40_PROT | MT_AGG_PCR0_BW80_PROT); +	mt76_set(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_PTA_WIN_DIS); + +	mt76_wr(dev, MT_AGG_PCR0(ext_phy, 1), MT_AGG_PCR1_RTS0_NUM_THRES | +		MT_AGG_PCR1_RTS0_LEN_THRES); + +	mt76_clear(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_BAR_CNT_LIMIT | +		   MT_AGG_MRCR_LAST_RTS_CTS_RN | MT_AGG_MRCR_RTS_FAIL_LIMIT | +		   MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT); + +	mt76_rmw(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_RTS_FAIL_LIMIT | +		 MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT, +		 FIELD_PREP(MT_AGG_MRCR_RTS_FAIL_LIMIT, 1) | +		 FIELD_PREP(MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT, 1)); + +	mt76_wr(dev, MT_TMAC_TFCR0(ext_phy), 0); +	mt76_clear(dev, MT_TMAC_TCR0(ext_phy), MT_TMAC_TCR0_TBTT_STOP_CTRL); + +	/* config rx filter for testmode rx */ +	mt76_wr(dev, MT_WF_RFCR(ext_phy), 0xcf70a); +	mt76_wr(dev, MT_WF_RFCR1(ext_phy), 0); +} + +static void +mt7915_tm_init(struct mt7915_dev *dev) +{ +	bool en = !(dev->mt76.test.state == MT76_TM_STATE_OFF); + +	if (!test_bit(MT76_STATE_RUNNING, &dev->phy.mt76->state)) +		return; + +	mt7915_tm_mode_ctrl(dev, en); +	mt7915_tm_reg_backup_restore(dev, &dev->phy); +	mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_TXRX, !en); +} + +static void +mt7915_tm_set_tx_frames(struct mt7915_dev *dev, bool en) +{ +	static const u8 spe_idx_map[] = {0, 0, 1, 0, 3, 2, 4, 0, +					 9, 8, 6, 10, 16, 12, 18, 0}; +	struct sk_buff *skb = dev->mt76.test.tx_skb; +	struct ieee80211_tx_info *info; + +	mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_RX_RXV, false); + +	if (en) { +		u8 tx_ant = dev->mt76.test.tx_antenna_mask; + +		mutex_unlock(&dev->mt76.mutex); +		mt7915_set_channel(&dev->phy); +		mutex_lock(&dev->mt76.mutex); + +		mt7915_mcu_set_chan_info(&dev->phy, MCU_EXT_CMD_SET_RX_PATH); +		dev->test.spe_idx = spe_idx_map[tx_ant]; +	} + +	mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_TX, en); + +	if (!en || !skb) +		return; + +	info = IEEE80211_SKB_CB(skb); +	info->control.vif = dev->phy.monitor_vif; +} + +static void +mt7915_tm_set_rx_frames(struct mt7915_dev *dev, bool en) +{ +	if (en) { +		mutex_unlock(&dev->mt76.mutex); +		mt7915_set_channel(&dev->phy); +		mutex_lock(&dev->mt76.mutex); + +		mt7915_mcu_set_chan_info(&dev->phy, MCU_EXT_CMD_SET_RX_PATH); +	} + +	mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_RX_RXV, en); +} + +static void +mt7915_tm_update_params(struct mt7915_dev *dev, u32 changed) +{ +	struct mt76_testmode_data *td = &dev->mt76.test; +	bool en = dev->mt76.test.state != MT76_TM_STATE_OFF; + +	if (changed & BIT(TM_CHANGED_FREQ_OFFSET)) +		mt7915_tm_set_freq_offset(dev, en, en ? td->freq_offset : 0); +	if (changed & BIT(TM_CHANGED_TXPOWER)) +		mt7915_tm_set_tx_power(&dev->phy); +} + +static int +mt7915_tm_set_state(struct mt76_dev *mdev, enum mt76_testmode_state state) +{ +	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); +	struct mt76_testmode_data *td = &mdev->test; +	enum mt76_testmode_state prev_state = td->state; + +	mdev->test.state = state; + +	if (prev_state == MT76_TM_STATE_TX_FRAMES) +		mt7915_tm_set_tx_frames(dev, false); +	else if (state == MT76_TM_STATE_TX_FRAMES) +		mt7915_tm_set_tx_frames(dev, true); +	else if (prev_state == MT76_TM_STATE_RX_FRAMES) +		mt7915_tm_set_rx_frames(dev, false); +	else if (state == MT76_TM_STATE_RX_FRAMES) +		mt7915_tm_set_rx_frames(dev, true); +	else if (prev_state == MT76_TM_STATE_OFF || state == MT76_TM_STATE_OFF) +		mt7915_tm_init(dev); + +	if ((state == MT76_TM_STATE_IDLE && +	     prev_state == MT76_TM_STATE_OFF) || +	    (state == MT76_TM_STATE_OFF && +	     prev_state == MT76_TM_STATE_IDLE)) { +		u32 changed = 0; +		int i; + +		for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) { +			u16 cur = tm_change_map[i]; + +			if (td->param_set[cur / 32] & BIT(cur % 32)) +				changed |= BIT(i); +		} + +		mt7915_tm_update_params(dev, changed); +	} + +	return 0; +} + +static int +mt7915_tm_set_params(struct mt76_dev *mdev, struct nlattr **tb, +		     enum mt76_testmode_state new_state) +{ +	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); +	struct mt76_testmode_data *td = &dev->mt76.test; +	u32 changed = 0; +	int i; + +	BUILD_BUG_ON(NUM_TM_CHANGED >= 32); + +	if (new_state == MT76_TM_STATE_OFF || +	    td->state == MT76_TM_STATE_OFF) +		return 0; + +	if (td->tx_antenna_mask & ~dev->phy.chainmask) +		return -EINVAL; + +	for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) { +		if (tb[tm_change_map[i]]) +			changed |= BIT(i); +	} + +	mt7915_tm_update_params(dev, changed); + +	return 0; +} + +static int +mt7915_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg) +{ +	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); +	void *rx, *rssi; +	int i; + +	rx = nla_nest_start(msg, MT76_TM_STATS_ATTR_LAST_RX); +	if (!rx) +		return -ENOMEM; + +	if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, dev->test.last_freq_offset)) +		return -ENOMEM; + +	rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RCPI); +	if (!rssi) +		return -ENOMEM; + +	for (i = 0; i < ARRAY_SIZE(dev->test.last_rcpi); i++) +		if (nla_put_u8(msg, i, dev->test.last_rcpi[i])) +			return -ENOMEM; + +	nla_nest_end(msg, rssi); + +	rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_IB_RSSI); +	if (!rssi) +		return -ENOMEM; + +	for (i = 0; i < ARRAY_SIZE(dev->test.last_ib_rssi); i++) +		if (nla_put_s8(msg, i, dev->test.last_ib_rssi[i])) +			return -ENOMEM; + +	nla_nest_end(msg, rssi); + +	rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_WB_RSSI); +	if (!rssi) +		return -ENOMEM; + +	for (i = 0; i < ARRAY_SIZE(dev->test.last_wb_rssi); i++) +		if (nla_put_s8(msg, i, dev->test.last_wb_rssi[i])) +			return -ENOMEM; + +	nla_nest_end(msg, rssi); + +	if (nla_put_u8(msg, MT76_TM_RX_ATTR_SNR, dev->test.last_snr)) +		return -ENOMEM; + +	nla_nest_end(msg, rx); + +	return 0; +} + +const struct mt76_testmode_ops mt7915_testmode_ops = { +	.set_state = mt7915_tm_set_state, +	.set_params = mt7915_tm_set_params, +	.dump_stats = mt7915_tm_dump_stats, +}; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h new file mode 100644 index 000000000000..964f2d7fde3a --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#ifndef __MT7915_TESTMODE_H +#define __MT7915_TESTMODE_H + +struct mt7915_tm_trx { +	u8 type; +	u8 enable; +	u8 band; +	u8 rsv; +}; + +struct mt7915_tm_freq_offset { +	u8 band; +	__le32 freq_offset; +}; + +struct mt7915_tm_cmd { +	u8 testmode_en; +	u8 param_idx; +	u8 _rsv[2]; +	union { +		__le32 data; +		struct mt7915_tm_trx trx; +		struct mt7915_tm_freq_offset freq; +		u8 test[72]; +	} param; +} __packed; + +enum { +	TM_MAC_TX = 1, +	TM_MAC_RX, +	TM_MAC_TXRX, +	TM_MAC_TXRX_RXV, +	TM_MAC_RXV, +	TM_MAC_RX_RXV, +}; + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c index 9a4d95a2a707..62b5b912818f 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/sdio.c @@ -36,46 +36,49 @@ mt76s_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid)  	return 0;  } -static int mt76s_alloc_tx(struct mt76_dev *dev) +static struct mt76_queue *mt76s_alloc_tx_queue(struct mt76_dev *dev)  {  	struct mt76_queue *q; -	int i; - -	for (i = 0; i < MT_TXQ_MCU_WA; i++) { -		q = devm_kzalloc(dev->dev, sizeof(*q), GFP_KERNEL); -		if (!q) -			return -ENOMEM; -		spin_lock_init(&q->lock); -		q->hw_idx = i; -		dev->q_tx[i] = q; +	q = devm_kzalloc(dev->dev, sizeof(*q), GFP_KERNEL); +	if (!q) +		return ERR_PTR(-ENOMEM); -		q->entry = devm_kcalloc(dev->dev, -					MT_NUM_TX_ENTRIES, sizeof(*q->entry), -					GFP_KERNEL); -		if (!q->entry) -			return -ENOMEM; +	spin_lock_init(&q->lock); +	q->entry = devm_kcalloc(dev->dev, +				MT_NUM_TX_ENTRIES, sizeof(*q->entry), +				GFP_KERNEL); +	if (!q->entry) +		return ERR_PTR(-ENOMEM); -		q->ndesc = MT_NUM_TX_ENTRIES; -	} +	q->ndesc = MT_NUM_TX_ENTRIES; -	return 0; +	return q;  } -void mt76s_stop_txrx(struct mt76_dev *dev) +static int mt76s_alloc_tx(struct mt76_dev *dev)  { -	struct mt76_sdio *sdio = &dev->sdio; +	struct mt76_queue *q; +	int i; -	cancel_work_sync(&sdio->tx.xmit_work); -	cancel_work_sync(&sdio->tx.status_work); -	cancel_work_sync(&sdio->rx.recv_work); -	cancel_work_sync(&sdio->rx.net_work); -	cancel_work_sync(&sdio->stat_work); -	clear_bit(MT76_READING_STATS, &dev->phy.state); +	for (i = 0; i <= MT_TXQ_PSD; i++) { +		q = mt76s_alloc_tx_queue(dev); +		if (IS_ERR(q)) +			return PTR_ERR(q); -	mt76_tx_status_check(dev, NULL, true); +		q->qid = i; +		dev->phy.q_tx[i] = q; +	} + +	q = mt76s_alloc_tx_queue(dev); +	if (IS_ERR(q)) +		return PTR_ERR(q); + +	q->qid = MT_MCUQ_WM; +	dev->q_mcu[MT_MCUQ_WM] = q; + +	return 0;  } -EXPORT_SYMBOL_GPL(mt76s_stop_txrx);  int mt76s_alloc_queues(struct mt76_dev *dev)  { @@ -131,11 +134,32 @@ mt76s_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)  	return nframes;  } -static void mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid) +static void mt76s_net_worker(struct mt76_worker *w) +{ +	struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, +					      net_worker); +	struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); +	int i, nframes; + +	do { +		nframes = 0; + +		local_bh_disable(); +		rcu_read_lock(); + +		mt76_for_each_q_rx(dev, i) +			nframes += mt76s_process_rx_queue(dev, &dev->q_rx[i]); + +		rcu_read_unlock(); +		local_bh_enable(); +	} while (nframes > 0); +} + +static int mt76s_process_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)  { -	struct mt76_queue *q = dev->q_tx[qid]; +	bool wake, mcu = q == dev->q_mcu[MT_MCUQ_WM];  	struct mt76_queue_entry entry; -	bool wake; +	int nframes = 0;  	while (q->queued > 0) {  		if (!q->entry[q->tail].done) @@ -144,12 +168,13 @@ static void mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid)  		entry = q->entry[q->tail];  		q->entry[q->tail].done = false; -		if (qid == MT_TXQ_MCU) { +		if (mcu) {  			dev_kfree_skb(entry.skb);  			entry.skb = NULL;  		}  		mt76_queue_tx_complete(dev, q, &entry); +		nframes++;  	}  	wake = q->stopped && q->queued < q->ndesc - 8; @@ -159,13 +184,35 @@ static void mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid)  	if (!q->queued)  		wake_up(&dev->tx_wait); -	if (qid == MT_TXQ_MCU) -		return; +	if (mcu) +		goto out; -	mt76_txq_schedule(&dev->phy, qid); +	mt76_txq_schedule(&dev->phy, q->qid);  	if (wake) -		ieee80211_wake_queue(dev->hw, qid); +		ieee80211_wake_queue(dev->hw, q->qid); +out: +	return nframes; +} + +static void mt76s_status_worker(struct mt76_worker *w) +{ +	struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, +					      status_worker); +	struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); +	int i, nframes; + +	do { +		nframes = mt76s_process_tx_queue(dev, dev->q_mcu[MT_MCUQ_WM]); + +		for (i = 0; i <= MT_TXQ_PSD; i++) +			nframes += mt76s_process_tx_queue(dev, +							  dev->phy.q_tx[i]); + +		if (dev->drv->tx_status_data && +		    !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) +			queue_work(dev->wq, &dev->sdio.stat_work); +	} while (nframes > 0);  }  static void mt76s_tx_status_data(struct work_struct *work) @@ -194,11 +241,10 @@ static void mt76s_tx_status_data(struct work_struct *work)  }  static int -mt76s_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,  		   struct sk_buff *skb, struct mt76_wcid *wcid,  		   struct ieee80211_sta *sta)  { -	struct mt76_queue *q = dev->q_tx[qid];  	struct mt76_tx_info tx_info = {  		.skb = skb,  	}; @@ -209,7 +255,7 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,  		return -ENOSPC;  	skb->prev = skb->next = NULL; -	err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info); +	err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info);  	if (err < 0)  		return err; @@ -222,10 +268,9 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,  }  static int -mt76s_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76s_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,  		       struct sk_buff *skb, u32 tx_info)  { -	struct mt76_queue *q = dev->q_tx[qid];  	int ret = -ENOSPC, len = skb->len, pad;  	if (q->queued == q->ndesc) @@ -257,7 +302,7 @@ static void mt76s_tx_kick(struct mt76_dev *dev, struct mt76_queue *q)  {  	struct mt76_sdio *sdio = &dev->sdio; -	queue_work(sdio->txrx_wq, &sdio->tx.xmit_work); +	mt76_worker_schedule(&sdio->txrx_worker);  }  static const struct mt76_queue_ops sdio_queue_ops = { @@ -266,49 +311,19 @@ static const struct mt76_queue_ops sdio_queue_ops = {  	.tx_queue_skb_raw = mt76s_tx_queue_skb_raw,  }; -static void mt76s_tx_work(struct work_struct *work) -{ -	struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, -					      tx.status_work); -	struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); -	int i; - -	for (i = 0; i < MT_TXQ_MCU_WA; i++) -		mt76s_process_tx_queue(dev, i); - -	if (dev->drv->tx_status_data && -	    !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) -		queue_work(dev->wq, &dev->sdio.stat_work); -} - -static void mt76s_rx_work(struct work_struct *work) -{ -	struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, -					      rx.net_work); -	struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); -	int i; - -	/* rx processing */ -	local_bh_disable(); -	rcu_read_lock(); - -	mt76_for_each_q_rx(dev, i) -		mt76s_process_rx_queue(dev, &dev->q_rx[i]); - -	rcu_read_unlock(); -	local_bh_enable(); -} -  void mt76s_deinit(struct mt76_dev *dev)  {  	struct mt76_sdio *sdio = &dev->sdio;  	int i; -	mt76s_stop_txrx(dev); -	if (sdio->txrx_wq) { -		destroy_workqueue(sdio->txrx_wq); -		sdio->txrx_wq = NULL; -	} +	mt76_worker_teardown(&sdio->txrx_worker); +	mt76_worker_teardown(&sdio->status_worker); +	mt76_worker_teardown(&sdio->net_worker); + +	cancel_work_sync(&sdio->stat_work); +	clear_bit(MT76_READING_STATS, &dev->phy.state); + +	mt76_tx_status_check(dev, NULL, true);  	sdio_claim_host(sdio->func);  	sdio_release_irq(sdio->func); @@ -335,18 +350,23 @@ int mt76s_init(struct mt76_dev *dev, struct sdio_func *func,  	       const struct mt76_bus_ops *bus_ops)  {  	struct mt76_sdio *sdio = &dev->sdio; +	int err; -	sdio->txrx_wq = alloc_workqueue("mt76s_txrx_wq", -					WQ_UNBOUND | WQ_HIGHPRI, -					WQ_UNBOUND_MAX_ACTIVE); -	if (!sdio->txrx_wq) -		return -ENOMEM; +	err = mt76_worker_setup(dev->hw, &sdio->status_worker, +				mt76s_status_worker, "sdio-status"); +	if (err) +		return err; + +	err = mt76_worker_setup(dev->hw, &sdio->net_worker, mt76s_net_worker, +				"sdio-net"); +	if (err) +		return err; + +	sched_set_fifo_low(sdio->status_worker.task); +	sched_set_fifo_low(sdio->net_worker.task);  	INIT_WORK(&sdio->stat_work, mt76s_tx_status_data); -	INIT_WORK(&sdio->tx.status_work, mt76s_tx_work); -	INIT_WORK(&sdio->rx.net_work, mt76s_rx_work); -	mutex_init(&sdio->sched.lock);  	dev->queue_ops = &sdio_queue_ops;  	dev->bus = bus_ops;  	dev->sdio.func = func; diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c index 883f59c7a7e4..581eb56dc4be 100644 --- a/drivers/net/wireless/mediatek/mt76/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/testmode.c @@ -11,6 +11,8 @@ static const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {  	[MT76_TM_ATTR_TX_RATE_IDX] = { .type = NLA_U8 },  	[MT76_TM_ATTR_TX_RATE_SGI] = { .type = NLA_U8 },  	[MT76_TM_ATTR_TX_RATE_LDPC] = { .type = NLA_U8 }, +	[MT76_TM_ATTR_TX_RATE_STBC] = { .type = NLA_U8 }, +	[MT76_TM_ATTR_TX_LTF] = { .type = NLA_U8 },  	[MT76_TM_ATTR_TX_ANTENNA] = { .type = NLA_U8 },  	[MT76_TM_ATTR_TX_POWER_CONTROL] = { .type = NLA_U8 },  	[MT76_TM_ATTR_TX_POWER] = { .type = NLA_NESTED }, @@ -21,6 +23,7 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev)  {  	struct mt76_testmode_data *td = &dev->test;  	struct mt76_wcid *wcid = &dev->global_wcid; +	struct mt76_phy *phy = &dev->phy;  	struct sk_buff *skb = td->tx_skb;  	struct mt76_queue *q;  	int qid; @@ -29,7 +32,7 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev)  		return;  	qid = skb_get_queue_mapping(skb); -	q = dev->q_tx[qid]; +	q = phy->q_tx[qid];  	spin_lock_bh(&q->lock); @@ -37,7 +40,8 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev)  	       q->queued < q->ndesc / 2) {  		int ret; -		ret = dev->queue_ops->tx_queue_skb(dev, qid, skb_get(skb), wcid, NULL); +		ret = dev->queue_ops->tx_queue_skb(dev, q, skb_get(skb), wcid, +						   NULL);  		if (ret < 0)  			break; @@ -55,13 +59,14 @@ static int  mt76_testmode_tx_init(struct mt76_dev *dev)  {  	struct mt76_testmode_data *td = &dev->test; +	struct mt76_phy *phy = &dev->phy;  	struct ieee80211_tx_info *info;  	struct ieee80211_hdr *hdr;  	struct sk_buff *skb;  	u16 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |  		 IEEE80211_FCTL_FROMDS;  	struct ieee80211_tx_rate *rate; -	u8 max_nss = hweight8(dev->phy.antenna_mask); +	u8 max_nss = hweight8(phy->antenna_mask);  	if (td->tx_antenna_mask)  		max_nss = min_t(u8, max_nss, hweight8(td->tx_antenna_mask)); @@ -74,28 +79,32 @@ mt76_testmode_tx_init(struct mt76_dev *dev)  	td->tx_skb = skb;  	hdr = __skb_put_zero(skb, td->tx_msdu_len);  	hdr->frame_control = cpu_to_le16(fc); -	memcpy(hdr->addr1, dev->macaddr, sizeof(dev->macaddr)); -	memcpy(hdr->addr2, dev->macaddr, sizeof(dev->macaddr)); -	memcpy(hdr->addr3, dev->macaddr, sizeof(dev->macaddr)); +	memcpy(hdr->addr1, phy->macaddr, sizeof(phy->macaddr)); +	memcpy(hdr->addr2, phy->macaddr, sizeof(phy->macaddr)); +	memcpy(hdr->addr3, phy->macaddr, sizeof(phy->macaddr));  	info = IEEE80211_SKB_CB(skb);  	info->flags = IEEE80211_TX_CTL_INJECTED |  		      IEEE80211_TX_CTL_NO_ACK |  		      IEEE80211_TX_CTL_NO_PS_BUFFER; + +	if (td->tx_rate_mode > MT76_TM_TX_MODE_VHT) +		goto out; +  	rate = &info->control.rates[0];  	rate->count = 1;  	rate->idx = td->tx_rate_idx;  	switch (td->tx_rate_mode) {  	case MT76_TM_TX_MODE_CCK: -		if (dev->phy.chandef.chan->band != NL80211_BAND_2GHZ) +		if (phy->chandef.chan->band != NL80211_BAND_2GHZ)  			return -EINVAL;  		if (rate->idx > 4)  			return -EINVAL;  		break;  	case MT76_TM_TX_MODE_OFDM: -		if (dev->phy.chandef.chan->band != NL80211_BAND_2GHZ) +		if (phy->chandef.chan->band != NL80211_BAND_2GHZ)  			break;  		if (rate->idx > 8) @@ -106,7 +115,7 @@ mt76_testmode_tx_init(struct mt76_dev *dev)  	case MT76_TM_TX_MODE_HT:  		if (rate->idx > 8 * max_nss &&  			!(rate->idx == 32 && -			  dev->phy.chandef.width >= NL80211_CHAN_WIDTH_40)) +			  phy->chandef.width >= NL80211_CHAN_WIDTH_40))  			return -EINVAL;  		rate->flags |= IEEE80211_TX_RC_MCS; @@ -131,8 +140,11 @@ mt76_testmode_tx_init(struct mt76_dev *dev)  	if (td->tx_rate_ldpc)  		info->flags |= IEEE80211_TX_CTL_LDPC; +	if (td->tx_rate_stbc) +		info->flags |= IEEE80211_TX_CTL_STBC; +  	if (td->tx_rate_mode >= MT76_TM_TX_MODE_HT) { -		switch (dev->phy.chandef.width) { +		switch (phy->chandef.width) {  		case NL80211_CHAN_WIDTH_40:  			rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;  			break; @@ -147,7 +159,7 @@ mt76_testmode_tx_init(struct mt76_dev *dev)  			break;  		}  	} - +out:  	skb_set_queue_mapping(skb, IEEE80211_AC_BE);  	return 0; @@ -334,8 +346,10 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  			   0, MT76_TM_TX_MODE_MAX) ||  	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_NSS], &td->tx_rate_nss,  			   1, hweight8(phy->antenna_mask)) || -	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_SGI], &td->tx_rate_sgi, 0, 1) || +	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_SGI], &td->tx_rate_sgi, 0, 2) ||  	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_LDPC], &td->tx_rate_ldpc, 0, 1) || +	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_STBC], &td->tx_rate_stbc, 0, 1) || +	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_LTF], &td->tx_ltf, 0, 2) ||  	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], &td->tx_antenna_mask, 1,  			   phy->antenna_mask) ||  	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL], @@ -472,6 +486,9 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,  	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, td->tx_rate_idx) ||  	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_SGI, td->tx_rate_sgi) ||  	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_LDPC, td->tx_rate_ldpc) || +	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) || +	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) && +	     nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||  	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&  	     nla_put_u8(msg, MT76_TM_ATTR_TX_ANTENNA, td->tx_antenna_mask)) ||  	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER_CONTROL) && diff --git a/drivers/net/wireless/mediatek/mt76/testmode.h b/drivers/net/wireless/mediatek/mt76/testmode.h index 691fe5773244..7efad685a17c 100644 --- a/drivers/net/wireless/mediatek/mt76/testmode.h +++ b/drivers/net/wireless/mediatek/mt76/testmode.h @@ -25,6 +25,8 @@   * @MT76_TM_ATTR_TX_RATE_IDX: packet tx rate/MCS index (u8)   * @MT76_TM_ATTR_TX_RATE_SGI: packet tx use short guard interval (u8)   * @MT76_TM_ATTR_TX_RATE_LDPC: packet tx enable LDPC (u8) + * @MT76_TM_ATTR_TX_RATE_STBC: packet tx enable STBC (u8) + * @MT76_TM_ATTR_TX_LTF: packet tx LTF, set 0 to 2 for 1x, 2x, and 4x LTF (u8)   *   * @MT76_TM_ATTR_TX_ANTENNA: tx antenna mask (u8)   * @MT76_TM_ATTR_TX_POWER_CONTROL: enable tx power control (u8) @@ -50,6 +52,8 @@ enum mt76_testmode_attr {  	MT76_TM_ATTR_TX_RATE_IDX,  	MT76_TM_ATTR_TX_RATE_SGI,  	MT76_TM_ATTR_TX_RATE_LDPC, +	MT76_TM_ATTR_TX_RATE_STBC, +	MT76_TM_ATTR_TX_LTF,  	MT76_TM_ATTR_TX_ANTENNA,  	MT76_TM_ATTR_TX_POWER_CONTROL, @@ -99,8 +103,9 @@ enum mt76_testmode_stats_attr {   *   * @MT76_TM_RX_ATTR_FREQ_OFFSET: frequency offset (s32)   * @MT76_TM_RX_ATTR_RCPI: received channel power indicator (array, u8) - * @MT76_TM_RX_ATTR_IB_RSSI: internal inband RSSI (s8) - * @MT76_TM_RX_ATTR_WB_RSSI: internal wideband RSSI (s8) + * @MT76_TM_RX_ATTR_IB_RSSI: internal inband RSSI (array, s8) + * @MT76_TM_RX_ATTR_WB_RSSI: internal wideband RSSI (array, s8) + * @MT76_TM_RX_ATTR_SNR: signal-to-noise ratio (u8)   */  enum mt76_testmode_rx_attr {  	MT76_TM_RX_ATTR_UNSPEC, @@ -109,6 +114,7 @@ enum mt76_testmode_rx_attr {  	MT76_TM_RX_ATTR_RCPI,  	MT76_TM_RX_ATTR_IB_RSSI,  	MT76_TM_RX_ATTR_WB_RSSI, +	MT76_TM_RX_ATTR_SNR,  	/* keep last */  	NUM_MT76_TM_RX_ATTRS, @@ -141,12 +147,20 @@ enum mt76_testmode_state {   * @MT76_TM_TX_MODE_OFDM: legacy OFDM mode   * @MT76_TM_TX_MODE_HT: 802.11n MCS   * @MT76_TM_TX_MODE_VHT: 802.11ac MCS + * @MT76_TM_TX_MODE_HE_SU: 802.11ax single-user MIMO + * @MT76_TM_TX_MODE_HE_EXT_SU: 802.11ax extended-range SU + * @MT76_TM_TX_MODE_HE_TB: 802.11ax trigger-based + * @MT76_TM_TX_MODE_HE_MU: 802.11ax multi-user MIMO   */  enum mt76_testmode_tx_mode {  	MT76_TM_TX_MODE_CCK,  	MT76_TM_TX_MODE_OFDM,  	MT76_TM_TX_MODE_HT,  	MT76_TM_TX_MODE_VHT, +	MT76_TM_TX_MODE_HE_SU, +	MT76_TM_TX_MODE_HE_EXT_SU, +	MT76_TM_TX_MODE_HE_TB, +	MT76_TM_TX_MODE_HE_MU,  	/* keep last */  	NUM_MT76_TM_TX_MODES, diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 44ef4bc7a46e..1e20afb70fc1 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -225,23 +225,23 @@ void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *sk  EXPORT_SYMBOL_GPL(mt76_tx_complete_skb);  static int -__mt76_tx_queue_skb(struct mt76_dev *dev, int qid, struct sk_buff *skb, +__mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,  		    struct mt76_wcid *wcid, struct ieee80211_sta *sta,  		    bool *stop)  {  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -	struct mt76_queue *q; +	struct mt76_queue *q = phy->q_tx[qid]; +	struct mt76_dev *dev = phy->dev;  	bool non_aql;  	int pending;  	int idx;  	non_aql = !info->tx_time_est; -	idx = dev->queue_ops->tx_queue_skb(dev, qid, skb, wcid, sta); +	idx = dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta);  	if (idx < 0 || !sta || !non_aql)  		return idx;  	wcid = (struct mt76_wcid *)sta->drv_priv; -	q = dev->q_tx[qid];  	q->entry[idx].wcid = wcid->idx;  	pending = atomic_inc_return(&wcid->non_aql_packets);  	if (stop && pending >= MT_MAX_NON_AQL_PKT) @@ -272,6 +272,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,  	}  	if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) && +	    !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&  	    !ieee80211_is_data(hdr->frame_control) &&  	    !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {  		qid = MT_TXQ_PSD; @@ -285,17 +286,11 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,  	if (ext_phy)  		info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; -	q = dev->q_tx[qid]; +	q = phy->q_tx[qid];  	spin_lock_bh(&q->lock); -	__mt76_tx_queue_skb(dev, qid, skb, wcid, sta, NULL); +	__mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL);  	dev->queue_ops->kick(dev, q); - -	if (q->queued > q->ndesc - 8 && !q->stopped) { -		ieee80211_stop_queue(phy->hw, skb_get_queue_mapping(skb)); -		q->stopped = true; -	} -  	spin_unlock_bh(&q->lock);  }  EXPORT_SYMBOL_GPL(mt76_tx); @@ -320,7 +315,7 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq)  }  static void -mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta, +mt76_queue_ps_skb(struct mt76_phy *phy, struct ieee80211_sta *sta,  		  struct sk_buff *skb, bool last)  {  	struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; @@ -332,7 +327,7 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,  			       IEEE80211_TX_CTL_REQ_TX_STATUS;  	mt76_skb_set_moredata(skb, !last); -	__mt76_tx_queue_skb(dev, MT_TXQ_PSD, skb, wcid, sta, NULL); +	__mt76_tx_queue_skb(phy, MT_TXQ_PSD, skb, wcid, sta, NULL);  }  void @@ -344,7 +339,7 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,  	struct mt76_phy *phy = hw->priv;  	struct mt76_dev *dev = phy->dev;  	struct sk_buff *last_skb = NULL; -	struct mt76_queue *hwq = dev->q_tx[MT_TXQ_PSD]; +	struct mt76_queue *hwq = phy->q_tx[MT_TXQ_PSD];  	int i;  	spin_lock_bh(&hwq->lock); @@ -363,14 +358,14 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,  			nframes--;  			if (last_skb) -				mt76_queue_ps_skb(dev, sta, last_skb, false); +				mt76_queue_ps_skb(phy, sta, last_skb, false);  			last_skb = skb;  		} while (nframes);  	}  	if (last_skb) { -		mt76_queue_ps_skb(dev, sta, last_skb, true); +		mt76_queue_ps_skb(phy, sta, last_skb, true);  		dev->queue_ops->kick(dev, hwq);  	} else {  		ieee80211_sta_eosp(sta); @@ -380,6 +375,13 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,  }  EXPORT_SYMBOL_GPL(mt76_release_buffered_frames); +static bool +mt76_txq_stopped(struct mt76_queue *q) +{ +	return q->stopped || q->blocked || +	       q->queued + MT_TXQ_FREE_THR >= q->ndesc; +} +  static int  mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,  		    struct mt76_txq *mtxq) @@ -409,7 +411,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,  		ieee80211_get_tx_rates(txq->vif, txq->sta, skb,  				       info->control.rates, 1); -	idx = __mt76_tx_queue_skb(dev, qid, skb, wcid, txq->sta, &stop); +	idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop);  	if (idx < 0)  		return idx; @@ -418,10 +420,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,  		    test_bit(MT76_RESET, &phy->state))  			return -EBUSY; -		if (stop) -			break; - -		if (q->queued + MT_TXQ_FREE_THR >= q->ndesc) +		if (stop || mt76_txq_stopped(q))  			break;  		skb = mt76_txq_dequeue(phy, mtxq); @@ -433,7 +432,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,  			ieee80211_get_tx_rates(txq->vif, txq->sta, skb,  					       info->control.rates, 1); -		idx = __mt76_tx_queue_skb(dev, qid, skb, wcid, txq->sta, &stop); +		idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop);  		if (idx < 0)  			break; @@ -448,8 +447,8 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,  static int  mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)  { +	struct mt76_queue *q = phy->q_tx[qid];  	struct mt76_dev *dev = phy->dev; -	struct mt76_queue *q = dev->q_tx[qid];  	struct ieee80211_txq *txq;  	struct mt76_txq *mtxq;  	struct mt76_wcid *wcid; @@ -463,7 +462,14 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)  			break;  		} -		if (q->queued + MT_TXQ_FREE_THR >= q->ndesc) +		if (dev->queue_ops->tx_cleanup && +		    q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) { +			spin_unlock_bh(&q->lock); +			dev->queue_ops->tx_cleanup(dev, q, false); +			spin_lock_bh(&q->lock); +		} + +		if (mt76_txq_stopped(q))  			break;  		txq = ieee80211_next_txq(phy->hw, qid); @@ -498,11 +504,14 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)  void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)  { +	struct mt76_queue *q;  	int len;  	if (qid >= 4)  		return; +	q = phy->q_tx[qid]; +  	rcu_read_lock();  	do { @@ -538,7 +547,7 @@ void mt76_tx_worker(struct mt76_worker *w)  #endif  } -void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, +void mt76_stop_tx_queues(struct mt76_phy *phy, struct ieee80211_sta *sta,  			 bool send_bar)  {  	int i; @@ -551,7 +560,7 @@ void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta,  		if (!txq)  			continue; -		hwq = dev->q_tx[mt76_txq_get_qid(txq)]; +		hwq = phy->q_tx[mt76_txq_get_qid(txq)];  		mtxq = (struct mt76_txq *)txq->drv_priv;  		spin_lock_bh(&hwq->lock); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index f1ae9ff835b2..dc850109de22 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -627,7 +627,7 @@ static void mt76u_complete_rx(struct urb *urb)  	q->head = (q->head + 1) % q->ndesc;  	q->queued++; -	tasklet_schedule(&dev->usb.rx_tasklet); +	mt76_worker_schedule(&dev->usb.rx_worker);  out:  	spin_unlock_irqrestore(&q->lock, flags);  } @@ -665,13 +665,17 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)  		}  		mt76u_submit_rx_buf(dev, qid, urb);  	} -	if (qid == MT_RXQ_MAIN) +	if (qid == MT_RXQ_MAIN) { +		local_bh_disable();  		mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL); +		local_bh_enable(); +	}  } -static void mt76u_rx_tasklet(unsigned long data) +static void mt76u_rx_worker(struct mt76_worker *w)  { -	struct mt76_dev *dev = (struct mt76_dev *)data; +	struct mt76_usb *usb = container_of(w, struct mt76_usb, rx_worker); +	struct mt76_dev *dev = container_of(usb, struct mt76_dev, usb);  	int i;  	rcu_read_lock(); @@ -737,8 +741,13 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)  	struct page *page;  	int i; -	for (i = 0; i < q->ndesc; i++) +	for (i = 0; i < q->ndesc; i++) { +		if (!q->entry[i].urb) +			continue; +  		mt76u_urb_free(q->entry[i].urb); +		q->entry[i].urb = NULL; +	}  	if (!q->rx_page.va)  		return; @@ -752,6 +761,8 @@ static void mt76u_free_rx(struct mt76_dev *dev)  {  	int i; +	mt76_worker_teardown(&dev->usb.rx_worker); +  	mt76_for_each_q_rx(dev, i)  		mt76u_free_rx_queue(dev, &dev->q_rx[i]);  } @@ -760,6 +771,8 @@ void mt76u_stop_rx(struct mt76_dev *dev)  {  	int i; +	mt76_worker_disable(&dev->usb.rx_worker); +  	mt76_for_each_q_rx(dev, i) {  		struct mt76_queue *q = &dev->q_rx[i];  		int j; @@ -767,8 +780,6 @@ void mt76u_stop_rx(struct mt76_dev *dev)  		for (j = 0; j < q->ndesc; j++)  			usb_poison_urb(q->entry[j].urb);  	} - -	tasklet_kill(&dev->usb.rx_tasklet);  }  EXPORT_SYMBOL_GPL(mt76u_stop_rx); @@ -788,20 +799,23 @@ int mt76u_resume_rx(struct mt76_dev *dev)  			return err;  	} +	mt76_worker_enable(&dev->usb.rx_worker); +  	return 0;  }  EXPORT_SYMBOL_GPL(mt76u_resume_rx); -static void mt76u_tx_worker(struct mt76_worker *w) +static void mt76u_status_worker(struct mt76_worker *w)  { -	struct mt76_dev *dev = container_of(w, struct mt76_dev, tx_worker); +	struct mt76_usb *usb = container_of(w, struct mt76_usb, status_worker); +	struct mt76_dev *dev = container_of(usb, struct mt76_dev, usb);  	struct mt76_queue_entry entry;  	struct mt76_queue *q;  	bool wake;  	int i;  	for (i = 0; i < IEEE80211_NUM_ACS; i++) { -		q = dev->q_tx[i]; +		q = dev->phy.q_tx[i];  		while (q->queued > 0) {  			if (!q->entry[q->tail].done) @@ -820,7 +834,7 @@ static void mt76u_tx_worker(struct mt76_worker *w)  		if (!q->queued)  			wake_up(&dev->tx_wait); -		mt76_txq_schedule(&dev->phy, i); +		mt76_worker_schedule(&dev->tx_worker);  		if (dev->drv->tx_status_data &&  		    !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) @@ -864,7 +878,7 @@ static void mt76u_complete_tx(struct urb *urb)  		dev_err(dev->dev, "tx urb failed: %d\n", urb->status);  	e->done = true; -	mt76_worker_schedule(&dev->tx_worker); +	mt76_worker_schedule(&dev->usb.status_worker);  }  static int @@ -887,11 +901,10 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb,  }  static int -mt76u_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,  		   struct sk_buff *skb, struct mt76_wcid *wcid,  		   struct ieee80211_sta *sta)  { -	struct mt76_queue *q = dev->q_tx[qid];  	struct mt76_tx_info tx_info = {  		.skb = skb,  	}; @@ -902,7 +915,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,  		return -ENOSPC;  	skb->prev = skb->next = NULL; -	err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info); +	err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info);  	if (err < 0)  		return err; @@ -970,7 +983,7 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)  	for (i = 0; i <= MT_TXQ_PSD; i++) {  		if (i >= IEEE80211_NUM_ACS) { -			dev->q_tx[i] = dev->q_tx[0]; +			dev->phy.q_tx[i] = dev->phy.q_tx[0];  			continue;  		} @@ -980,7 +993,9 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)  		spin_lock_init(&q->lock);  		q->hw_idx = mt76u_ac_to_hwq(dev, i); -		dev->q_tx[i] = q; +		q->qid = i; + +		dev->phy.q_tx[i] = q;  		q->entry = devm_kcalloc(dev->dev,  					MT_NUM_TX_ENTRIES, sizeof(*q->entry), @@ -1003,16 +1018,20 @@ static void mt76u_free_tx(struct mt76_dev *dev)  {  	int i; +	mt76_worker_teardown(&dev->usb.status_worker); +  	for (i = 0; i < IEEE80211_NUM_ACS; i++) {  		struct mt76_queue *q;  		int j; -		q = dev->q_tx[i]; +		q = dev->phy.q_tx[i];  		if (!q)  			continue; -		for (j = 0; j < q->ndesc; j++) +		for (j = 0; j < q->ndesc; j++) {  			usb_free_urb(q->entry[j].urb); +			q->entry[j].urb = NULL; +		}  	}  } @@ -1020,6 +1039,8 @@ void mt76u_stop_tx(struct mt76_dev *dev)  {  	int ret; +	mt76_worker_disable(&dev->usb.status_worker); +  	ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(&dev->phy),  				 HZ / 5);  	if (!ret) { @@ -1030,7 +1051,7 @@ void mt76u_stop_tx(struct mt76_dev *dev)  		dev_err(dev->dev, "timed out waiting for pending tx\n");  		for (i = 0; i < IEEE80211_NUM_ACS; i++) { -			q = dev->q_tx[i]; +			q = dev->phy.q_tx[i];  			if (!q)  				continue; @@ -1044,7 +1065,7 @@ void mt76u_stop_tx(struct mt76_dev *dev)  		 * will fail to submit urb, cleanup those skb's manually.  		 */  		for (i = 0; i < IEEE80211_NUM_ACS; i++) { -			q = dev->q_tx[i]; +			q = dev->phy.q_tx[i];  			if (!q)  				continue; @@ -1061,6 +1082,8 @@ void mt76u_stop_tx(struct mt76_dev *dev)  	cancel_work_sync(&dev->usb.stat_work);  	clear_bit(MT76_READING_STATS, &dev->phy.state); +	mt76_worker_enable(&dev->usb.status_worker); +  	mt76_tx_status_check(dev, NULL, true);  }  EXPORT_SYMBOL_GPL(mt76u_stop_tx); @@ -1103,15 +1126,13 @@ int mt76u_init(struct mt76_dev *dev,  	};  	struct usb_device *udev = interface_to_usbdev(intf);  	struct mt76_usb *usb = &dev->usb; -	int err = -ENOMEM; +	int err;  	mt76u_ops.rr = ext ? mt76u_rr_ext : mt76u_rr;  	mt76u_ops.wr = ext ? mt76u_wr_ext : mt76u_wr;  	mt76u_ops.rmw = ext ? mt76u_rmw_ext : mt76u_rmw;  	mt76u_ops.write_copy = ext ? mt76u_copy_ext : mt76u_copy; -	dev->tx_worker.fn = mt76u_tx_worker; -	tasklet_init(&usb->rx_tasklet, mt76u_rx_tasklet, (unsigned long)dev);  	INIT_WORK(&usb->stat_work, mt76u_tx_status_data);  	usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1); @@ -1120,7 +1141,7 @@ int mt76u_init(struct mt76_dev *dev,  	usb->data = devm_kmalloc(dev->dev, usb->data_len, GFP_KERNEL);  	if (!usb->data) -		goto error; +		return -ENOMEM;  	mutex_init(&usb->usb_ctrl_mtx);  	dev->bus = &mt76u_ops; @@ -1132,14 +1153,22 @@ int mt76u_init(struct mt76_dev *dev,  	err = mt76u_set_endpoints(intf, usb);  	if (err < 0) -		goto error; +		return err; -	return 0; +	err = mt76_worker_setup(dev->hw, &usb->rx_worker, mt76u_rx_worker, +				"usb-rx"); +	if (err) +		return err; + +	err = mt76_worker_setup(dev->hw, &usb->status_worker, +				mt76u_status_worker, "usb-status"); +	if (err) +		return err; -error: -	destroy_workqueue(dev->wq); +	sched_set_fifo_low(usb->rx_worker.task); +	sched_set_fifo_low(usb->status_worker.task); -	return err; +	return 0;  }  EXPORT_SYMBOL_GPL(mt76u_init);  | 
