[rdkb][common][bsp][Refactor and sync wifi from openwrt]

[Description]
1dacd97b [MAC80211][WiFi6][Misc][Fix patch fail]
7c02334a [MAC80211][WiFi7][Misc][Fix build fail because of mt76 version upgradation]
7a073097 [MAC80211][WiFi7][misc][ensure the first MLD bss is bss[0]]
27e2304c [MAC80211][WiFi6][mt76][Refactor due to atenl change]
1e1eb98e [MAC80211][WiFi6/7][app][Add single wiphy support for atenl & iwpriv wrapper]
d4101c33 [MAC80211][WiFi7][mt76][enable lftp for wifi7 r1 cert]
55f5732f [MAC80211][WiFi7][hostapd][set ctrl_interface for all bss]

[Release-log]

Change-Id: I9cad01561c310576a9e5bdc9f1b8eec3025e51d9
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0082-wifi-mt76-mt7996-implement-and-switch-to-hw-scan-cal.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0082-wifi-mt76-mt7996-implement-and-switch-to-hw-scan-cal.patch
new file mode 100644
index 0000000..c76593a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0082-wifi-mt76-mt7996-implement-and-switch-to-hw-scan-cal.patch
@@ -0,0 +1,451 @@
+From 8a1c29f6a9b99d2f3d699fe6100704349406fc4b Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Fri, 3 Nov 2023 21:44:45 +0800
+Subject: [PATCH 082/116] wifi: mt76: mt7996: implement and switch to hw scan
+ callbacks
+
+To support MLO, hw_scan callbacks are mandatory. However, the
+firmware of AP-segment doesn't support hw_scan commands, so we need
+to implement it in the driver.
+This is a preliminary patch to add MLO support for mt7996 chipsets.
+
+If the cfg80211_scan_request contains an unicast BSSID, the probe
+request should be unicast.
+This works for ML probe request, which should be unicast.
+
+Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Co-developed-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mac80211.c      |   3 +-
+ mt76.h          |   2 +
+ mt7996/init.c   |   5 ++
+ mt7996/mac.c    | 141 ++++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/main.c   |  95 ++++++++++++++++++++++++++++----
+ mt7996/mcu.c    |   3 +-
+ mt7996/mt7996.h |  11 +++-
+ 7 files changed, 248 insertions(+), 12 deletions(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index 3c2c2af..0ad3f25 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -821,7 +821,7 @@ bool mt76_has_tx_pending(struct mt76_phy *phy)
+ }
+ EXPORT_SYMBOL_GPL(mt76_has_tx_pending);
+ 
+-static struct mt76_channel_state *
++struct mt76_channel_state *
+ mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c)
+ {
+ 	struct mt76_sband *msband;
+@@ -837,6 +837,7 @@ mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c)
+ 	idx = c - &msband->sband.channels[0];
+ 	return &msband->chan[idx];
+ }
++EXPORT_SYMBOL_GPL(mt76_channel_state);
+ 
+ void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time)
+ {
+diff --git a/mt76.h b/mt76.h
+index 28defd4..8ca7907 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -1477,6 +1477,8 @@ void mt76_release_buffered_frames(struct ieee80211_hw *hw,
+ 				  enum ieee80211_frame_release_type reason,
+ 				  bool more_data);
+ bool mt76_has_tx_pending(struct mt76_phy *phy);
++struct mt76_channel_state *
++mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c);
+ void mt76_set_channel(struct mt76_phy *phy);
+ void mt76_update_survey(struct mt76_phy *phy);
+ void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time);
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 768979e..9523568 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -457,6 +457,9 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
+ 
+ 	wiphy->available_antennas_rx = phy->mt76->antenna_mask;
+ 	wiphy->available_antennas_tx = phy->mt76->antenna_mask;
++
++	wiphy->max_scan_ssids = 4;
++	wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+ }
+ 
+ static void
+@@ -677,6 +680,7 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ 	mphy->dev->phys[band] = mphy;
+ 
+ 	INIT_DELAYED_WORK(&mphy->mac_work, mt7996_mac_work);
++	INIT_DELAYED_WORK(&phy->scan_work, mt7996_scan_work);
+ 
+ 	ret = mt7996_eeprom_parse_hw_cap(dev, phy);
+ 	if (ret)
+@@ -1574,6 +1578,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ 	dev->mt76.phy.priv = &dev->phy;
+ 	INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work);
+ 	INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work);
++	INIT_DELAYED_WORK(&dev->phy.scan_work, mt7996_scan_work);
+ 	INIT_DELAYED_WORK(&dev->scs_work, mt7996_mcu_scs_sta_poll);
+ 	INIT_LIST_HEAD(&dev->sta_rc_list);
+ 	INIT_LIST_HEAD(&dev->twt_list);
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 8c44442..4e9dd2c 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -2693,3 +2693,144 @@ void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
+ 	dev->twt.table_mask &= ~BIT(flow->table_id);
+ 	dev->twt.n_agrt--;
+ }
++
++static void
++mt7996_scan_send_probe(struct mt7996_phy *phy, struct cfg80211_ssid *ssid,
++		       const u8 *dst)
++{
++	struct ieee80211_hw *hw = phy->mt76->hw;
++	struct cfg80211_scan_request *req = phy->scan_req;
++	struct ieee80211_vif *vif = phy->scan_vif;
++	struct mt7996_vif *mvif;
++	struct mt76_wcid *wcid;
++	struct ieee80211_tx_info *info;
++	struct sk_buff *skb;
++
++	if (!req || !vif)
++		return;
++
++	mvif = (struct mt7996_vif *)vif->drv_priv;
++	wcid = &mvif->sta.wcid;
++
++	skb = ieee80211_probereq_get(hw, vif->addr,
++				     ssid->ssid, ssid->ssid_len, req->ie_len);
++	if (!skb)
++		return;
++
++	if (is_unicast_ether_addr(dst)) {
++		struct ieee80211_hdr_3addr *hdr =
++			(struct ieee80211_hdr_3addr *)skb->data;
++		memcpy(hdr->addr1, dst, ETH_ALEN);
++		memcpy(hdr->addr3, dst, ETH_ALEN);
++	}
++
++	info = IEEE80211_SKB_CB(skb);
++	if (req->no_cck)
++		info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
++
++	if (req->ie_len)
++		skb_put_data(skb, req->ie, req->ie_len);
++
++	skb_set_queue_mapping(skb, IEEE80211_AC_VO);
++
++	rcu_read_lock();
++	if (!ieee80211_tx_prepare_skb(hw, vif, skb,
++				      phy->scan_chan->band,
++				      NULL)) {
++		rcu_read_unlock();
++		ieee80211_free_txskb(hw, skb);
++		return;
++	}
++
++	local_bh_disable();
++	mt76_tx(phy->mt76, NULL, wcid, skb);
++	local_bh_enable();
++
++	rcu_read_unlock();
++}
++
++void mt7996_scan_complete(struct mt7996_phy *phy, bool aborted)
++{
++	struct cfg80211_scan_info info = {
++		.aborted = aborted,
++	};
++
++	ieee80211_scan_completed(phy->mt76->hw, &info);
++	phy->scan_chan = NULL;
++	phy->scan_req = NULL;
++	phy->scan_vif = NULL;
++	clear_bit(MT76_SCANNING, &phy->mt76->state);
++}
++
++static void mt7996_scan_check_sta(void *data, struct ieee80211_sta *sta)
++{
++	bool *has_sta = data;
++
++	if (*has_sta)
++		return;
++	*has_sta = true;
++}
++
++void mt7996_scan_work(struct work_struct *work)
++{
++	struct mt7996_phy *phy = container_of(work, struct mt7996_phy, scan_work.work);
++	struct ieee80211_hw *hw = phy->mt76->hw;
++	struct cfg80211_scan_request *req = phy->scan_req;
++	struct cfg80211_chan_def chandef = {};
++	int duration;
++	bool has_sta = false, active_scan = false;
++
++	mutex_lock(&phy->dev->mt76.mutex);
++	if (phy->scan_chan_idx >= req->n_channels) {
++		mt7996_scan_complete(phy, false);
++		mutex_unlock(&phy->dev->mt76.mutex);
++
++		mt7996_set_channel(phy, &hw->conf.chandef);
++
++		return;
++	}
++
++	ieee80211_iterate_stations_atomic(hw, mt7996_scan_check_sta, &has_sta);
++
++	/* go back to operating channel */
++	if (has_sta && phy->scan_chan) {
++		phy->scan_chan = NULL;
++		mutex_unlock(&phy->dev->mt76.mutex);
++
++		mt7996_set_channel(phy, &phy->mt76->chandef);
++
++		ieee80211_queue_delayed_work(hw, &phy->scan_work, HZ / 10);
++
++		return;
++	}
++
++	wiphy_info(hw->wiphy, "hw scan %d MHz\n",
++		   req->channels[phy->scan_chan_idx]->center_freq);
++
++	phy->scan_chan = req->channels[phy->scan_chan_idx++];
++
++	if (!req->n_ssids ||
++	    (phy->scan_chan->flags & (IEEE80211_CHAN_NO_IR |
++				      IEEE80211_CHAN_RADAR))) {
++		duration = HZ / 9; /* ~110 ms */
++	} else {
++		duration = HZ / 16; /* ~60 ms */
++		active_scan = true;
++	}
++
++	cfg80211_chandef_create(&chandef, phy->scan_chan, NL80211_CHAN_HT20);
++	mutex_unlock(&phy->dev->mt76.mutex);
++
++	mt7996_set_channel(phy, &chandef);
++
++	if (active_scan) {
++		int i;
++
++		mutex_lock(&phy->dev->mt76.mutex);
++		for (i = 0; i < req->n_ssids; i++)
++			mt7996_scan_send_probe(phy, &req->ssids[i], req->bssid);
++		mutex_unlock(&phy->dev->mt76.mutex);
++	}
++
++	ieee80211_queue_delayed_work(hw, &phy->scan_work, duration);
++}
+diff --git a/mt7996/main.c b/mt7996/main.c
+index c9e8108..5c1735e 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -312,6 +312,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
+ 	struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ 	int idx = msta->wcid.idx;
+ 
++	cancel_delayed_work_sync(&phy->scan_work);
++
+ 	mt7996_mcu_add_sta(dev, vif, NULL, false, false);
+ 	mt7996_mcu_add_bss_info(phy, vif, false);
+ 
+@@ -323,6 +325,10 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
+ 	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
+ 
+ 	mutex_lock(&dev->mt76.mutex);
++
++	if (test_bit(MT76_SCANNING, &phy->mt76->state))
++		mt7996_scan_complete(phy, true);
++
+ 	dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
+ 	phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
+ 	mutex_unlock(&dev->mt76.mutex);
+@@ -335,7 +341,33 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
+ 	mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
+ }
+ 
+-int mt7996_set_channel(struct mt7996_phy *phy)
++static void ___mt7996_set_channel(struct mt7996_phy *phy,
++				 struct cfg80211_chan_def *chandef)
++{
++	struct mt76_dev *mdev = phy->mt76->dev;
++	struct mt76_phy *mphy = phy->mt76;
++	bool offchannel = phy->scan_chan != NULL;
++	int timeout = HZ / 5;
++
++	wait_event_timeout(mdev->tx_wait, !mt76_has_tx_pending(mphy), timeout);
++	mt76_update_survey(mphy);
++
++	if (mphy->chandef.chan->center_freq != chandef->chan->center_freq ||
++	    mphy->chandef.width != chandef->width)
++		mphy->dfs_state = MT_DFS_STATE_UNKNOWN;
++
++	mphy->chandef = *chandef;
++	mphy->chan_state = mt76_channel_state(mphy, chandef->chan);
++
++	if (!offchannel)
++		mphy->main_chan = chandef->chan;
++
++	if (chandef->chan != mphy->main_chan)
++		memset(mphy->chan_state, 0, sizeof(*mphy->chan_state));
++}
++
++static int __mt7996_set_channel(struct mt7996_phy *phy,
++				struct cfg80211_chan_def *chandef)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+ 	int ret;
+@@ -345,7 +377,7 @@ int mt7996_set_channel(struct mt7996_phy *phy)
+ 	mutex_lock(&dev->mt76.mutex);
+ 	set_bit(MT76_RESET, &phy->mt76->state);
+ 
+-	mt76_set_channel(phy->mt76);
++	___mt7996_set_channel(phy, chandef);
+ 
+ 	if (dev->cal) {
+ 		ret = mt7996_mcu_apply_tx_dpd(phy);
+@@ -381,6 +413,19 @@ out:
+ 	return ret;
+ }
+ 
++int mt7996_set_channel(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef)
++{
++	int ret;
++
++	ieee80211_stop_queues(phy->mt76->hw);
++	ret = __mt7996_set_channel(phy, chandef);
++	if (ret)
++		return ret;
++	ieee80211_wake_queues(phy->mt76->hw);
++
++	return 0;
++}
++
+ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ 			  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ 			  struct ieee80211_key_conf *key)
+@@ -477,11 +522,7 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
+ 		if (ret)
+ 			return ret;
+ 
+-		ieee80211_stop_queues(hw);
+-		ret = mt7996_set_channel(phy);
+-		if (ret)
+-			return ret;
+-		ieee80211_wake_queues(hw);
++		mt7996_set_channel(phy, &hw->conf.chandef);
+ 	}
+ 
+ 	if (changed & (IEEE80211_CONF_CHANGE_POWER |
+@@ -1648,6 +1689,42 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
+ 
+ #endif
+ 
++static int
++mt7996_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
++	       struct ieee80211_scan_request *hw_req)
++{
++	struct cfg80211_scan_request *req = &hw_req->req;
++	struct mt7996_phy *phy = mt7996_hw_phy(hw);
++
++	mutex_lock(&phy->dev->mt76.mutex);
++	if (WARN_ON(phy->scan_req || phy->scan_chan)) {
++		mutex_unlock(&phy->dev->mt76.mutex);
++		return -EBUSY;
++	}
++
++	set_bit(MT76_SCANNING, &phy->mt76->state);
++	phy->scan_req = req;
++	phy->scan_vif = vif;
++	phy->scan_chan_idx = 0;
++	mutex_unlock(&phy->dev->mt76.mutex);
++
++	ieee80211_queue_delayed_work(hw, &phy->scan_work, 0);
++
++	return 0;
++}
++
++static void
++mt7996_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
++{
++	struct mt7996_phy *phy = mt7996_hw_phy(hw);
++
++	cancel_delayed_work_sync(&phy->scan_work);
++
++	mutex_lock(&phy->dev->mt76.mutex);
++	mt7996_scan_complete(phy, true);
++	mutex_unlock(&phy->dev->mt76.mutex);
++}
++
+ const struct ieee80211_ops mt7996_ops = {
+ 	.tx = mt7996_tx,
+ 	.start = mt7996_start,
+@@ -1666,8 +1743,8 @@ const struct ieee80211_ops mt7996_ops = {
+ 	.ampdu_action = mt7996_ampdu_action,
+ 	.set_rts_threshold = mt7996_set_rts_threshold,
+ 	.wake_tx_queue = mt76_wake_tx_queue,
+-	.sw_scan_start = mt76_sw_scan,
+-	.sw_scan_complete = mt76_sw_scan_complete,
++	.hw_scan = mt7996_hw_scan,
++	.cancel_hw_scan = mt7996_cancel_hw_scan,
+ 	.release_buffered_frames = mt76_release_buffered_frames,
+ 	.get_txpower = mt76_get_txpower,
+ 	.channel_switch_beacon = mt7996_channel_switch_beacon,
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index e38a507..9f2d125 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3775,7 +3775,8 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
+ 	if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
+ 		req.switch_reason = CH_SWITCH_NORMAL;
+ 	else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL ||
+-		 phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
++		 phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE ||
++		 phy->scan_chan)
+ 		req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
+ 	else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
+ 					  NL80211_IFTYPE_AP))
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index d03d3d9..fbf1e83 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -458,6 +458,13 @@ struct mt7996_phy {
+ 	u8 pp_mode;
+ 	u16 punct_bitmap;
+ 
++	/* for hw_scan */
++	struct delayed_work scan_work;
++	struct ieee80211_channel *scan_chan;
++	struct cfg80211_scan_request *scan_req;
++	struct ieee80211_vif *scan_vif;
++	int scan_chan_idx;
++
+ 	struct mt7996_scs_ctrl scs_ctrl;
+ 	u32 red_drop;
+ 
+@@ -806,7 +813,7 @@ int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+ 			    struct ieee80211_he_obss_pd *he_obss_pd);
+ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ 			     struct ieee80211_sta *sta, bool changed);
+-int mt7996_set_channel(struct mt7996_phy *phy);
++int mt7996_set_channel(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef);
+ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
+ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif);
+ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
+@@ -964,6 +971,8 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 			 struct sk_buff *skb, u32 *info);
+ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
+ void mt7996_stats_work(struct work_struct *work);
++void mt7996_scan_work(struct work_struct *work);
++void mt7996_scan_complete(struct mt7996_phy *phy, bool aborted);
+ int mt76_dfs_start_rdd(struct mt7996_dev *dev, bool force);
+ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy);
+ void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy);
+-- 
+2.18.0
+