Archive-only list for patches
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	patches@lists.linux.dev, Zong-Zhe Yang <kevin_yang@realtek.com>,
	Ping-Ke Shih <pkshih@realtek.com>,
	Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.12 273/826] wifi: rtw89: tweak driver architecture for impending MLO support
Date: Tue,  3 Dec 2024 15:40:00 +0100	[thread overview]
Message-ID: <20241203144754.424173605@linuxfoundation.org> (raw)
In-Reply-To: <20241203144743.428732212@linuxfoundation.org>

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Zong-Zhe Yang <kevin_yang@realtek.com>

[ Upstream commit aad0394e7a02fe933159be79d9d4595d2ad089dd ]

The drv_priv hooked to mac80211 become as below.

                           (drv_priv)             (instance-0)
 +---------------+       +-----------+          +----------------+
 | ieee80211_vif | <---> | rtw89_vif | -------> | rtw89_vif_link |
 +---------------+       +-----------+    |     +----------------+
                                          |
                                          |       (instance-1)
                                          |     +----------------+
                                          +---> | rtw89_vif_link |
                                                +----------------+

                           (drv_priv)             (instance-0)
 +---------------+       +-----------+          +----------------+
 | ieee80211_sta | <---> | rtw89_sta | -------> | rtw89_sta_link |
 +---------------+       +-----------+    |     +----------------+
                                          |
                                          |       (instance-1)
                                          |     +----------------+
                                          +---> | rtw89_sta_link |
                                                +----------------+

The relation bewteen mac80211 link_id and our link instance is like below.

                 |\
 (link_id)       | \
     0  -------- |  |
     1  -------- |  | ------ instance-0 (link_id: X) -> work on HW band 0
     2  -------- |  |
     ...         |  | ------ instance-1 (link_id: Y) -> work on HW band 1
     14 -------- |  |
                 | /
                 |/

	N.B. For cases of non-MLD connection, we set our link instance-0
	active with link_id 0. So, our code flow can be compatible between
	non-MLD connection and MLD connection.

Based on above, we tweak entire driver architecture first. But, we don't
dynamically enable multiple links here. That will be handled separately.
Most of the things changed here are changing flows to iterate all active
links and read bss_conf/link_sta data according to target link. And, for
cases of scan, ROC, WOW, we use instance-0 to deal with the request.

There are some things listed below, which work for now but need to extend
before multiple active links.
	1. tx path
		select suitable link instance among multiple active links
	2. rx path
		determine rx link by PPDU instead of always link instance-0
	3. CAM
		apply MLD pairwise key to any active links dynamically

Besides, PS code cannot easily work along with tweaking architecture. With
supporting MLO flag (currently false), we disable PS first and will fix it
by another commit in the following.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20240916053158.47350-8-pkshih@realtek.com
Stable-dep-of: f16c40acd319 ("wifi: rtw89: Fix TX fail with A2DP after scanning")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/net/wireless/realtek/rtw89/cam.c      | 126 ++++-
 drivers/net/wireless/realtek/rtw89/chan.c     |  77 ++-
 drivers/net/wireless/realtek/rtw89/coex.c     |  54 +-
 drivers/net/wireless/realtek/rtw89/core.c     | 504 +++++++++++++-----
 drivers/net/wireless/realtek/rtw89/core.h     | 240 +++++++--
 drivers/net/wireless/realtek/rtw89/debug.c    |  85 ++-
 drivers/net/wireless/realtek/rtw89/fw.c       | 147 ++---
 drivers/net/wireless/realtek/rtw89/fw.h       |  72 ++-
 drivers/net/wireless/realtek/rtw89/mac.c      | 137 +++--
 drivers/net/wireless/realtek/rtw89/mac.h      |   2 +-
 drivers/net/wireless/realtek/rtw89/mac80211.c | 423 +++++++++++----
 drivers/net/wireless/realtek/rtw89/phy.c      | 134 +++--
 drivers/net/wireless/realtek/rtw89/ps.c       |  33 +-
 drivers/net/wireless/realtek/rtw89/regd.c     |  40 +-
 drivers/net/wireless/realtek/rtw89/ser.c      |  63 ++-
 drivers/net/wireless/realtek/rtw89/util.h     |   8 +-
 drivers/net/wireless/realtek/rtw89/wow.c      |  99 ++--
 drivers/net/wireless/realtek/rtw89/wow.h      |   6 +-
 18 files changed, 1615 insertions(+), 635 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c
index 7efc6280feaf8..8d140b94cb440 100644
--- a/drivers/net/wireless/realtek/rtw89/cam.c
+++ b/drivers/net/wireless/realtek/rtw89/cam.c
@@ -211,24 +211,16 @@ static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam,
 	return 0;
 }
 
-static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_sta *sta,
-				    const struct rtw89_sec_cam_entry *sec_cam,
-				    bool inform_fw)
+static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
+				      struct rtw89_vif_link *rtwvif_link,
+				      struct rtw89_sta_link *rtwsta_link,
+				      const struct rtw89_sec_cam_entry *sec_cam,
+				      bool inform_fw)
 {
-	struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta);
-	struct rtw89_vif_link *rtwvif_link;
 	struct rtw89_addr_cam_entry *addr_cam;
 	unsigned int i;
 	int ret = 0;
 
-	if (!vif) {
-		rtw89_err(rtwdev, "No iface for deleting sec cam\n");
-		return -EINVAL;
-	}
-
-	rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
 	addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link);
 
 	for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) {
@@ -251,24 +243,16 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
 	return ret;
 }
 
-static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_sta *sta,
-				    struct ieee80211_key_conf *key,
-				    struct rtw89_sec_cam_entry *sec_cam)
+static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
+				      struct rtw89_vif_link *rtwvif_link,
+				      struct rtw89_sta_link *rtwsta_link,
+				      struct ieee80211_key_conf *key,
+				      struct rtw89_sec_cam_entry *sec_cam)
 {
-	struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta);
-	struct rtw89_vif_link *rtwvif_link;
 	struct rtw89_addr_cam_entry *addr_cam;
 	u8 key_idx = 0;
 	int ret;
 
-	if (!vif) {
-		rtw89_err(rtwdev, "No iface for adding sec cam\n");
-		return -EINVAL;
-	}
-
-	rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
 	addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link);
 
 	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
@@ -302,6 +286,92 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
 	return 0;
 }
 
+static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_sta *sta,
+				    const struct rtw89_sec_cam_entry *sec_cam,
+				    bool inform_fw)
+{
+	struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
+	struct rtw89_sta_link *rtwsta_link;
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
+	int ret;
+
+	if (!vif) {
+		rtw89_err(rtwdev, "No iface for deleting sec cam\n");
+		return -EINVAL;
+	}
+
+	rtwvif = vif_to_rtwvif(vif);
+
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+		rtwsta_link = rtwsta ? rtwsta->links[link_id] : NULL;
+		if (rtwsta && !rtwsta_link)
+			continue;
+
+		ret = __rtw89_cam_detach_sec_cam(rtwdev, rtwvif_link, rtwsta_link,
+						 sec_cam, inform_fw);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_sta *sta,
+				    struct ieee80211_key_conf *key,
+				    struct rtw89_sec_cam_entry *sec_cam)
+{
+	struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
+	struct rtw89_sta_link *rtwsta_link;
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
+	int key_link_id;
+	int ret;
+
+	if (!vif) {
+		rtw89_err(rtwdev, "No iface for adding sec cam\n");
+		return -EINVAL;
+	}
+
+	rtwvif = vif_to_rtwvif(vif);
+
+	key_link_id = ieee80211_vif_is_mld(vif) ? key->link_id : 0;
+	if (key_link_id >= 0) {
+		rtwvif_link = rtwvif->links[key_link_id];
+		rtwsta_link = rtwsta ? rtwsta->links[key_link_id] : NULL;
+
+		if (!rtwvif_link || (rtwsta && !rtwsta_link)) {
+			rtw89_err(rtwdev, "No drv link for adding sec cam\n");
+			return -ENOLINK;
+		}
+
+		return __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link,
+						  rtwsta_link, key, sec_cam);
+	}
+
+	/* key_link_id < 0: MLD pairwise key */
+	if (!rtwsta) {
+		rtw89_err(rtwdev, "No sta for adding MLD pairwise sec cam\n");
+		return -EINVAL;
+	}
+
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		ret = __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link,
+						 rtwsta_link, key, sec_cam);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_sta *sta,
@@ -708,10 +778,10 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
 				  const u8 *scan_mac_addr,
 				  u8 *cmd)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_addr_cam_entry *addr_cam =
 		rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link);
-	struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta_link);
+	struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link);
 	struct ieee80211_link_sta *link_sta;
 	const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif_link->mac_addr;
 	u8 sma_hash, tma_hash, addr_msk_start;
diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 2968c299203b8..ba6332da8019c 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -234,12 +234,24 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev)
 	rtw89_config_default_chandef(rtwdev);
 }
 
+static bool rtw89_vif_is_active_role(struct rtw89_vif *rtwvif)
+{
+	struct rtw89_vif_link *rtwvif_link;
+	unsigned int link_id;
+
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+		if (rtwvif_link->chanctx_assigned)
+			return true;
+
+	return false;
+}
+
 static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev,
 					  struct rtw89_entity_weight *w)
 {
 	struct rtw89_hal *hal = &rtwdev->hal;
 	const struct rtw89_chanctx_cfg *cfg;
-	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
 	int idx;
 
 	for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) {
@@ -254,8 +266,8 @@ static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev,
 			w->active_chanctxs++;
 	}
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link) {
-		if (rtwvif_link->chanctx_assigned)
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+		if (rtw89_vif_is_active_role(rtwvif))
 			w->active_roles++;
 	}
 }
@@ -522,14 +534,22 @@ u32 rtw89_mcc_role_fw_macid_bitmap_to_u32(struct rtw89_mcc_role *mcc_role)
 
 static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
 	struct rtw89_mcc_role *mcc_role = data;
-	struct rtw89_vif_link *target = mcc_role->rtwvif_link;
+	struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+	struct rtw89_sta_link *rtwsta_link;
 
-	if (rtwvif_link != target)
+	if (rtwvif != target)
 		return;
 
+	rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+	if (unlikely(!rtwsta_link)) {
+		rtw89_err(rtwdev, "mcc sta macid: find no link on HW-0\n");
+		return;
+	}
+
 	rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta_link->mac_id);
 }
 
@@ -605,7 +625,7 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev,
 		return;
 	}
 
-	ret = rtw89_mac_port_get_tsf(rtwdev, mcc_role->rtwvif_link, &tsf);
+	ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
 	if (ret) {
 		rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
 		return;
@@ -727,12 +747,19 @@ static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_mcc_fill_role_selector sel = {};
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
 	int ret;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link) {
-		if (!rtwvif_link->chanctx_assigned)
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+		if (!rtw89_vif_is_active_role(rtwvif))
 			continue;
 
+		rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+		if (unlikely(!rtwvif_link)) {
+			rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n");
+			continue;
+		}
+
 		if (sel.bind_vif[rtwvif_link->chanctx_idx]) {
 			rtw89_warn(rtwdev,
 				   "MCC skip extra vif <macid %d> on chanctx[%d]\n",
@@ -2384,12 +2411,30 @@ void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev)
 	rtw89_queue_chanctx_work(rtwdev);
 }
 
+static void __rtw89_swap_chanctx(struct rtw89_vif *rtwvif,
+				 enum rtw89_chanctx_idx idx1,
+				 enum rtw89_chanctx_idx idx2)
+{
+	struct rtw89_vif_link *rtwvif_link;
+	unsigned int link_id;
+
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+		if (!rtwvif_link->chanctx_assigned)
+			continue;
+
+		if (rtwvif_link->chanctx_idx == idx1)
+			rtwvif_link->chanctx_idx = idx2;
+		else if (rtwvif_link->chanctx_idx == idx2)
+			rtwvif_link->chanctx_idx = idx1;
+	}
+}
+
 static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
 			       enum rtw89_chanctx_idx idx1,
 			       enum rtw89_chanctx_idx idx2)
 {
 	struct rtw89_hal *hal = &rtwdev->hal;
-	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
 	u8 cur;
 
 	if (idx1 == idx2)
@@ -2400,14 +2445,8 @@ static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
 
 	swap(hal->chanctx[idx1], hal->chanctx[idx2]);
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link) {
-		if (!rtwvif_link->chanctx_assigned)
-			continue;
-		if (rtwvif_link->chanctx_idx == idx1)
-			rtwvif_link->chanctx_idx = idx2;
-		else if (rtwvif_link->chanctx_idx == idx2)
-			rtwvif_link->chanctx_idx = idx1;
-	}
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		__rtw89_swap_chanctx(rtwvif, idx1, idx2);
 
 	cur = atomic_read(&hal->roc_chanctx_idx);
 	if (cur == idx1)
diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index 3d33e40544d0f..8c2db2a493c8b 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -4989,13 +4989,11 @@ struct rtw89_txtime_data {
 	bool reenable;
 };
 
-static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
+static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link,
+				 struct rtw89_sta_link *rtwsta_link,
+				 struct rtw89_txtime_data *iter_data)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_txtime_data *iter_data =
-				(struct rtw89_txtime_data *)data;
 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
 	struct rtw89_btc *btc = &rtwdev->btc;
 	struct rtw89_btc_cx *cx = &btc->cx;
 	struct rtw89_btc_wl_info *wl = &cx->wl;
@@ -5048,6 +5046,21 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
 	}
 }
 
+static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_txtime_data *iter_data =
+				(struct rtw89_txtime_data *)data;
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
+
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		__rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data);
+	}
+}
+
 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_btc *btc = &rtwdev->btc;
@@ -7488,7 +7501,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
 {
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
 						       rtwvif_link->chanctx_idx);
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct ieee80211_bss_conf *bss_conf;
 	struct ieee80211_link_sta *link_sta;
 	struct rtw89_btc *btc = &rtwdev->btc;
@@ -7794,20 +7807,20 @@ struct rtw89_btc_wl_sta_iter_data {
 	bool is_traffic_change;
 };
 
-static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
+static
+void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link,
+				  struct rtw89_sta_link *rtwsta_link,
+				  struct rtw89_btc_wl_sta_iter_data *iter_data)
 {
-	struct rtw89_btc_wl_sta_iter_data *iter_data =
-				(struct rtw89_btc_wl_sta_iter_data *)data;
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
 	struct rtw89_btc *btc = &rtwdev->btc;
 	struct rtw89_btc_dm *dm = &btc->dm;
 	const struct rtw89_btc_ver *ver = btc->ver;
 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 	struct rtw89_btc_wl_link_info *link_info = NULL;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
 	struct rtw89_traffic_stats *link_info_t = NULL;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
-	struct rtw89_traffic_stats *stats = &rtwvif_link->stats;
+	struct rtw89_traffic_stats *stats = &rtwvif->stats;
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 	struct rtw89_btc_wl_role_info *r;
 	struct rtw89_btc_wl_role_info_v1 *r1;
@@ -7825,7 +7838,7 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
 
 	link_info = &wl->link_info[port];
-	link_info->stat.traffic = rtwvif_link->stats;
+	link_info->stat.traffic = *stats;
 	link_info_t = &link_info->stat.traffic;
 
 	if (link_info->connected == MLME_NO_LINK) {
@@ -7929,6 +7942,21 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
 		iter_data->is_traffic_change = true;
 }
 
+static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_btc_wl_sta_iter_data *iter_data =
+				(struct rtw89_btc_wl_sta_iter_data *)data;
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
+
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		__rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data);
+	}
+}
+
 #define BTC_NHM_CHK_INTVL 20
 
 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 8d2cca0b0a18d..5b8e65f6de6a4 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -436,15 +436,6 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev)
 	return 0;
 }
 
-void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
-		       struct rtw89_chan *chan)
-{
-	const struct cfg80211_chan_def *chandef;
-
-	chandef = rtw89_chandef_get(rtwdev, rtwvif_link->chanctx_idx);
-	rtw89_get_channel_params(chandef, chan);
-}
-
 static enum rtw89_core_tx_type
 rtw89_core_get_tx_type(struct rtw89_dev *rtwdev,
 		       struct sk_buff *skb)
@@ -463,11 +454,11 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev,
 				struct rtw89_core_tx_request *tx_req,
 				enum btc_pkt_type pkt_type)
 {
-	struct ieee80211_sta *sta = tx_req->sta;
+	struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
 	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
 	struct ieee80211_link_sta *link_sta;
 	struct sk_buff *skb = tx_req->skb;
-	struct rtw89_sta_link *rtwsta_link;
+	struct rtw89_sta *rtwsta;
 	u8 ampdu_num;
 	u8 tid;
 
@@ -479,19 +470,19 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev,
 	if (!(IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU))
 		return;
 
-	if (!sta) {
+	if (!rtwsta_link) {
 		rtw89_warn(rtwdev, "cannot set ampdu info without sta\n");
 		return;
 	}
 
 	tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-	rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	rtwsta = rtwsta_link->rtwsta;
 
 	rcu_read_lock();
 
 	link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
-	ampdu_num = (u8)((rtwsta_link->ampdu_params[tid].agg_num ?
-			  rtwsta_link->ampdu_params[tid].agg_num :
+	ampdu_num = (u8)((rtwsta->ampdu_params[tid].agg_num ?
+			  rtwsta->ampdu_params[tid].agg_num :
 			  4 << link_sta->ht_cap.ampdu_factor) - 1);
 
 	desc_info->agg_en = true;
@@ -575,9 +566,10 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
 				    const struct rtw89_chan *chan)
 {
 	struct sk_buff *skb = tx_req->skb;
+	struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_vif *vif = tx_info->control.vif;
-	struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif);
 	struct ieee80211_bss_conf *bss_conf;
 	u16 lowest_rate;
 	u16 rate;
@@ -596,7 +588,7 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
 	rcu_read_lock();
 
 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
-	if (!bss_conf->basic_rates || !tx_req->sta) {
+	if (!bss_conf->basic_rates || !rtwsta_link) {
 		rate = lowest_rate;
 		goto out;
 	}
@@ -612,15 +604,12 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
 static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev,
 				   struct rtw89_core_tx_request *tx_req)
 {
-	struct ieee80211_vif *vif = tx_req->vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct ieee80211_sta *sta = tx_req->sta;
-	struct rtw89_sta_link *rtwsta_link;
+	struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
 
-	if (!sta)
+	if (!rtwsta_link)
 		return rtwvif_link->mac_id;
 
-	rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
 	return rtwsta_link->mac_id;
 }
 
@@ -640,8 +629,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
 			       struct rtw89_core_tx_request *tx_req)
 {
 	const struct rtw89_chip_info *chip = rtwdev->chip;
-	struct ieee80211_vif *vif = tx_req->vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
 	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
 						       rtwvif_link->chanctx_idx);
@@ -723,8 +711,7 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev,
 				 struct rtw89_core_tx_request *tx_req,
 				 enum btc_pkt_type pkt_type)
 {
-	struct ieee80211_sta *sta = tx_req->sta;
-	struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta);
+	struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
 	struct sk_buff *skb = tx_req->skb;
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	struct ieee80211_link_sta *link_sta;
@@ -763,8 +750,7 @@ static void
 __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev,
 				  struct rtw89_core_tx_request *tx_req)
 {
-	struct ieee80211_sta *sta = tx_req->sta;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
 	struct sk_buff *skb = tx_req->skb;
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	__le16 fc = hdr->frame_control;
@@ -794,8 +780,7 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev,
 				enum btc_pkt_type pkt_type)
 {
 	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
-	struct ieee80211_vif *vif = tx_req->vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
 
 	if (!__rtw89_core_tx_check_he_qos_htc(rtwdev, tx_req, pkt_type))
 		goto desc_bk;
@@ -816,10 +801,9 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev,
 static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev,
 				    struct rtw89_core_tx_request *tx_req)
 {
-	struct ieee80211_vif *vif = tx_req->vif;
-	struct ieee80211_sta *sta = tx_req->sta;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta);
+	struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern;
 	enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx;
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, idx);
@@ -860,10 +844,8 @@ static void
 rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
 			       struct rtw89_core_tx_request *tx_req)
 {
-	struct ieee80211_vif *vif = tx_req->vif;
-	struct ieee80211_sta *sta = tx_req->sta;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta);
+	struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
 	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
 	struct sk_buff *skb = tx_req->skb;
 	u8 tid, tid_indicate;
@@ -1076,16 +1058,37 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
 int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
 			struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel)
 {
+	struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
 	struct rtw89_core_tx_request tx_req = {0};
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_sta_link *rtwsta_link = NULL;
+	struct rtw89_vif_link *rtwvif_link;
 	int ret;
 
+	/* By default, driver writes tx via the link on HW-0. And then,
+	 * according to links' status, HW can change tx to another link.
+	 */
+
+	if (rtwsta) {
+		rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+		if (unlikely(!rtwsta_link)) {
+			rtw89_err(rtwdev, "tx: find no sta link on HW-0\n");
+			return -ENOLINK;
+		}
+	}
+
+	rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev, "tx: find no vif link on HW-0\n");
+		return -ENOLINK;
+	}
+
 	tx_req.skb = skb;
-	tx_req.sta = sta;
-	tx_req.vif = vif;
+	tx_req.rtwvif_link = rtwvif_link;
+	tx_req.rtwsta_link = rtwsta_link;
 
 	rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true);
-	rtw89_traffic_stats_accu(rtwdev, &rtwvif_link->stats, skb, true);
+	rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true);
 	rtw89_core_tx_update_desc_info(rtwdev, &tx_req);
 	rtw89_core_tx_wake(rtwdev, &tx_req);
 
@@ -1563,15 +1566,23 @@ static u8 rtw89_get_data_rate_nss(struct rtw89_dev *rtwdev, u16 data_rate)
 static void rtw89_core_rx_process_phy_ppdu_iter(void *data,
 						struct ieee80211_sta *sta)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
 	struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data;
-	struct rtw89_dev *rtwdev = rtwsta_link->rtwdev;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
 	struct rtw89_hal *hal = &rtwdev->hal;
+	struct rtw89_sta_link *rtwsta_link;
 	u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
 	u8 ant_pos = U8_MAX;
 	u8 evm_pos = 0;
 	int i;
 
+	/* FIXME: For single link, taking link on HW-0 here is okay. But, when
+	 * enabling multiple active links, we should determine the right link.
+	 */
+	rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+	if (unlikely(!rtwsta_link))
+		return;
+
 	if (rtwsta_link->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self)
 		return;
 
@@ -1927,12 +1938,13 @@ struct rtw89_vif_rx_stats_iter_data {
 };
 
 static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
-				      struct ieee80211_vif *vif,
+				      struct rtw89_vif_link *rtwvif_link,
 				      struct ieee80211_bss_conf *bss_conf,
 				      struct sk_buff *skb)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
 	struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data;
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
 	u8 *pos, *end, type, tf_bw;
 	u16 aid, tf_rua;
 
@@ -1963,7 +1975,7 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
 		if (aid == vif->cfg.aid) {
 			enum nl80211_he_ru_alloc rua = rtw89_he_rua_to_ru_alloc(tf_rua >> 1);
 
-			rtwvif_link->stats.rx_tf_acc++;
+			rtwvif->stats.rx_tf_acc++;
 			rtwdev->stats.rx_tf_acc++;
 			if (tf_bw == IEEE80211_TRIGGER_ULBW_160_80P80MHZ &&
 			    rua <= NL80211_RATE_INFO_HE_RU_ALLOC_106)
@@ -2052,15 +2064,16 @@ static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif_link *rtwvif_link,
 static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
 				    struct ieee80211_vif *vif)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
 	struct rtw89_vif_rx_stats_iter_data *iter_data = data;
 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
 	struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat;
 	struct rtw89_rx_desc_info *desc_info = iter_data->desc_info;
 	struct sk_buff *skb = iter_data->skb;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct rtw89_rx_phy_ppdu *phy_ppdu = iter_data->phy_ppdu;
 	struct ieee80211_bss_conf *bss_conf;
+	struct rtw89_vif_link *rtwvif_link;
 	const u8 *bssid = iter_data->bssid;
 
 	if (rtwdev->scanning &&
@@ -2070,12 +2083,19 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
 
 	rcu_read_lock();
 
+	/* FIXME: For single link, taking link on HW-0 here is okay. But, when
+	 * enabling multiple active links, we should determine the right link.
+	 */
+	rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+	if (unlikely(!rtwvif_link))
+		goto out;
+
 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
 	if (!bss_conf->bssid)
 		goto out;
 
 	if (ieee80211_is_trigger(hdr->frame_control)) {
-		rtw89_stats_trigger_frame(rtwdev, vif, bss_conf, skb);
+		rtw89_stats_trigger_frame(rtwdev, rtwvif_link, bss_conf, skb);
 		goto out;
 	}
 
@@ -2097,7 +2117,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
 	if (desc_info->data_rate < RTW89_HW_RATE_NR)
 		pkt_stat->rx_rate_cnt[desc_info->data_rate]++;
 
-	rtw89_traffic_stats_accu(rtwdev, &rtwvif_link->stats, skb, false);
+	rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, false);
 
 out:
 	rcu_read_unlock();
@@ -2491,10 +2511,18 @@ void rtw89_core_stats_sta_rx_status_iter(void *data, struct ieee80211_sta *sta)
 	struct rtw89_core_iter_rx_status *iter_data =
 				(struct rtw89_core_iter_rx_status *)data;
 	struct ieee80211_rx_status *rx_status = iter_data->rx_status;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
 	struct rtw89_rx_desc_info *desc_info = iter_data->desc_info;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_sta_link *rtwsta_link;
 	u8 mac_id = iter_data->mac_id;
 
+	/* FIXME: For single link, taking link on HW-0 here is okay. But, when
+	 * enabling multiple active links, we should determine the right link.
+	 */
+	rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+	if (unlikely(!rtwsta_link))
+		return;
+
 	if (mac_id != rtwsta_link->mac_id)
 		return;
 
@@ -2605,6 +2633,10 @@ static enum rtw89_ps_mode rtw89_update_ps_mode(struct rtw89_dev *rtwdev)
 {
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 
+	/* FIXME: Fix __rtw89_enter_ps_mode() to consider MLO cases. */
+	if (rtwdev->support_mlo)
+		return RTW89_PS_MODE_NONE;
+
 	if (rtw89_disable_ps_mode || !chip->ps_mode_supported ||
 	    RTW89_CHK_FW_FEATURE(NO_DEEP_PS, &rtwdev->fw))
 		return RTW89_PS_MODE_NONE;
@@ -2717,8 +2749,7 @@ static void rtw89_core_ba_work(struct work_struct *work)
 	list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) {
 		struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq);
 		struct ieee80211_sta *sta = txq->sta;
-		struct rtw89_sta_link *rtwsta_link =
-			sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL;
+		struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
 		u8 tid = txq->tid;
 
 		if (!sta) {
@@ -2726,7 +2757,7 @@ static void rtw89_core_ba_work(struct work_struct *work)
 			goto skip_ba_work;
 		}
 
-		if (rtwsta_link->disassoc) {
+		if (rtwsta->disassoc) {
 			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
 				    "cannot start BA with disassoc sta\n");
 			goto skip_ba_work;
@@ -2781,11 +2812,11 @@ void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev,
 void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev,
 					struct ieee80211_sta *sta)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
 	struct sk_buff *skb, *tmp;
 
-	skb_queue_walk_safe(&rtwsta_link->roc_queue, skb, tmp) {
-		skb_unlink(skb, &rtwsta_link->roc_queue);
+	skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) {
+		skb_unlink(skb, &rtwsta->roc_queue);
 		dev_kfree_skb_any(skb);
 	}
 }
@@ -2795,9 +2826,9 @@ static void rtw89_core_stop_tx_ba_session(struct rtw89_dev *rtwdev,
 {
 	struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq);
 	struct ieee80211_sta *sta = txq->sta;
-	struct rtw89_sta_link *rtwsta_link = sta_to_rtwsta_safe(sta);
+	struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
 
-	if (unlikely(!rtwsta_link) || unlikely(rtwsta_link->disassoc))
+	if (unlikely(!rtwsta) || unlikely(rtwsta->disassoc))
 		return;
 
 	if (!test_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags) ||
@@ -2822,8 +2853,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev,
 	struct ieee80211_hw *hw = rtwdev->hw;
 	struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq);
 	struct ieee80211_sta *sta = txq->sta;
-	struct rtw89_sta_link *rtwsta_link =
-		sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
 
 	if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags))
 		return;
@@ -2845,7 +2875,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev,
 	}
 
 	spin_lock_bh(&rtwdev->ba_lock);
-	if (!rtwsta_link->disassoc && list_empty(&rtwtxq->list)) {
+	if (!rtwsta->disassoc && list_empty(&rtwtxq->list)) {
 		list_add_tail(&rtwtxq->list, &rtwdev->ba_list);
 		ieee80211_queue_work(hw, &rtwdev->ba_work);
 	}
@@ -2899,11 +2929,19 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev,
 				    bool *sched_txq, bool *reinvoke)
 {
 	struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv;
-	struct ieee80211_sta *sta = txq->sta;
-	struct rtw89_sta_link *rtwsta_link =
-		sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(txq->sta);
+	struct rtw89_sta_link *rtwsta_link;
 
-	if (!sta || rtwsta_link->max_agg_wait <= 0)
+	if (!rtwsta)
+		return false;
+
+	rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+	if (unlikely(!rtwsta_link)) {
+		rtw89_err(rtwdev, "agg wait: find no link on HW-0\n");
+		return false;
+	}
+
+	if (rtwsta_link->max_agg_wait <= 0)
 		return false;
 
 	if (rtwdev->stats.tx_tfc_lv <= RTW89_TFC_MID)
@@ -2931,7 +2969,7 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv
 {
 	struct ieee80211_hw *hw = rtwdev->hw;
 	struct ieee80211_txq *txq;
-	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
 	struct rtw89_txq *rtwtxq;
 	unsigned long frame_cnt;
 	unsigned long byte_cnt;
@@ -2941,9 +2979,9 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv
 	ieee80211_txq_schedule_start(hw, ac);
 	while ((txq = ieee80211_next_txq(hw, ac))) {
 		rtwtxq = (struct rtw89_txq *)txq->drv_priv;
-		rtwvif_link = (struct rtw89_vif_link *)txq->vif->drv_priv;
+		rtwvif = vif_to_rtwvif(txq->vif);
 
-		if (rtwvif_link->offchan) {
+		if (rtwvif->offchan) {
 			ieee80211_return_txq(hw, txq, true);
 			continue;
 		}
@@ -3017,22 +3055,28 @@ static void rtw89_forbid_ba_work(struct work_struct *w)
 static void rtw89_core_sta_pending_tx_iter(void *data,
 					   struct ieee80211_sta *sta)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_vif_link *rtwvif_target = data;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
-	struct rtw89_dev *rtwdev = rtwvif_link->rtwdev;
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+	struct rtw89_vif_link *target = data;
+	struct rtw89_vif_link *rtwvif_link;
 	struct sk_buff *skb, *tmp;
+	unsigned int link_id;
 	int qsel, ret;
 
-	if (rtwvif_link->chanctx_idx != rtwvif_target->chanctx_idx)
-		return;
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+		if (rtwvif_link->chanctx_idx == target->chanctx_idx)
+			goto bottom;
 
-	if (skb_queue_len(&rtwsta_link->roc_queue) == 0)
+	return;
+
+bottom:
+	if (skb_queue_len(&rtwsta->roc_queue) == 0)
 		return;
 
-	skb_queue_walk_safe(&rtwsta_link->roc_queue, skb, tmp) {
-		skb_unlink(skb, &rtwsta_link->roc_queue);
+	skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) {
+		skb_unlink(skb, &rtwsta->roc_queue);
 
 		ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel);
 		if (ret) {
@@ -3055,7 +3099,7 @@ static void rtw89_core_handle_sta_pending_tx(struct rtw89_dev *rtwdev,
 static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
 				    struct rtw89_vif_link *rtwvif_link, bool qos, bool ps)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct ieee80211_sta *sta;
 	struct ieee80211_hdr *hdr;
 	struct sk_buff *skb;
@@ -3098,19 +3142,27 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
 	return ret;
 }
 
-void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
+void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 	struct ieee80211_hw *hw = rtwdev->hw;
-	struct rtw89_roc *roc = &rtwvif_link->roc;
+	struct rtw89_roc *roc = &rtwvif->roc;
+	struct rtw89_vif_link *rtwvif_link;
 	struct cfg80211_chan_def roc_chan;
-	struct rtw89_vif_link *tmp;
+	struct rtw89_vif *tmp_vif;
 	int ret;
 
 	lockdep_assert_held(&rtwdev->mutex);
 
 	rtw89_leave_ips_by_hwflags(rtwdev);
 	rtw89_leave_lps(rtwdev);
+
+	rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev, "roc start: find no link on HW-0\n");
+		return;
+	}
+
 	rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_ROC);
 
 	ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true);
@@ -3118,9 +3170,17 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_lin
 		rtw89_debug(rtwdev, RTW89_DBG_TXRX,
 			    "roc send null-1 failed: %d\n", ret);
 
-	rtw89_for_each_rtwvif(rtwdev, tmp)
-		if (tmp->chanctx_idx == rtwvif_link->chanctx_idx)
-			tmp->offchan = true;
+	rtw89_for_each_rtwvif(rtwdev, tmp_vif) {
+		struct rtw89_vif_link *tmp_link;
+		unsigned int link_id;
+
+		rtw89_vif_for_each_link(tmp_vif, tmp_link, link_id) {
+			if (tmp_link->chanctx_idx == rtwvif_link->chanctx_idx) {
+				tmp_vif->offchan = true;
+				break;
+			}
+		}
+	}
 
 	cfg80211_chandef_create(&roc_chan, &roc->chan, NL80211_CHAN_NO_HT);
 	rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, &roc_chan);
@@ -3130,17 +3190,18 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_lin
 			  B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH);
 
 	ieee80211_ready_on_channel(hw);
-	cancel_delayed_work(&rtwvif_link->roc.roc_work);
-	ieee80211_queue_delayed_work(hw, &rtwvif_link->roc.roc_work,
-				     msecs_to_jiffies(rtwvif_link->roc.duration));
+	cancel_delayed_work(&rtwvif->roc.roc_work);
+	ieee80211_queue_delayed_work(hw, &rtwvif->roc.roc_work,
+				     msecs_to_jiffies(rtwvif->roc.duration));
 }
 
-void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
+void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 	struct ieee80211_hw *hw = rtwdev->hw;
-	struct rtw89_roc *roc = &rtwvif_link->roc;
-	struct rtw89_vif_link *tmp;
+	struct rtw89_roc *roc = &rtwvif->roc;
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *tmp_vif;
 	int ret;
 
 	lockdep_assert_held(&rtwdev->mutex);
@@ -3150,6 +3211,12 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
 	rtw89_leave_ips_by_hwflags(rtwdev);
 	rtw89_leave_lps(rtwdev);
 
+	rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev, "roc end: find no link on HW-0\n");
+		return;
+	}
+
 	rtw89_write32_mask(rtwdev,
 			   rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
 			   B_AX_RX_FLTR_CFG_MASK,
@@ -3163,9 +3230,8 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
 		rtw89_debug(rtwdev, RTW89_DBG_TXRX,
 			    "roc send null-0 failed: %d\n", ret);
 
-	rtw89_for_each_rtwvif(rtwdev, tmp)
-		if (tmp->chanctx_idx == rtwvif_link->chanctx_idx)
-			tmp->offchan = false;
+	rtw89_for_each_rtwvif(rtwdev, tmp_vif)
+		tmp_vif->offchan = false;
 
 	rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif_link);
 	queue_work(rtwdev->txq_wq, &rtwdev->txq_work);
@@ -3177,10 +3243,10 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
 
 void rtw89_roc_work(struct work_struct *work)
 {
-	struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link,
-							  roc.roc_work.work);
-	struct rtw89_dev *rtwdev = rtwvif_link->rtwdev;
-	struct rtw89_roc *roc = &rtwvif_link->roc;
+	struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif,
+						roc.roc_work.work);
+	struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+	struct rtw89_roc *roc = &rtwvif->roc;
 
 	mutex_lock(&rtwdev->mutex);
 
@@ -3190,7 +3256,7 @@ void rtw89_roc_work(struct work_struct *work)
 		break;
 	case RTW89_ROC_MGMT:
 	case RTW89_ROC_NORMAL:
-		rtw89_roc_end(rtwdev, rtwvif_link);
+		rtw89_roc_end(rtwdev, rtwvif);
 		break;
 	default:
 		break;
@@ -3252,12 +3318,17 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev,
 static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 	bool tfc_changed;
 
 	tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats);
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link) {
-		rtw89_traffic_stats_calc(rtwdev, &rtwvif_link->stats);
-		rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link);
+
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+		rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats);
+
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link);
 	}
 
 	return tfc_changed;
@@ -3266,25 +3337,32 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev)
 static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev,
 				struct rtw89_vif_link *rtwvif_link)
 {
-	if ((rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION &&
-	     rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) ||
-	    rtwvif_link->tdls_peer)
-		return;
-
-	if (rtwvif_link->offchan)
+	if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION &&
+	    rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT)
 		return;
 
-	if (rtwvif_link->stats.tx_tfc_lv == RTW89_TFC_IDLE &&
-	    rtwvif_link->stats.rx_tfc_lv == RTW89_TFC_IDLE)
-		rtw89_enter_lps(rtwdev, rtwvif_link, true);
+	rtw89_enter_lps(rtwdev, rtwvif_link, true);
 }
 
 static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
+
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+		if (rtwvif->tdls_peer)
+			continue;
+		if (rtwvif->offchan)
+			continue;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		rtw89_vif_enter_lps(rtwdev, rtwvif_link);
+		if (rtwvif->stats.tx_tfc_lv != RTW89_TFC_IDLE ||
+		    rtwvif->stats.rx_tfc_lv != RTW89_TFC_IDLE)
+			continue;
+
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			rtw89_vif_enter_lps(rtwdev, rtwvif_link);
+	}
 }
 
 static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev)
@@ -3468,7 +3546,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
 		break
 void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc)
 {
-	const struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	const struct ieee80211_bss_conf *bss_conf;
 
 	switch (vif->type) {
@@ -3529,8 +3607,8 @@ int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev,
 			    struct rtw89_vif_link *rtwvif_link,
 			    struct rtw89_sta_link *rtwsta_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
-	struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link);
+	const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+	const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
 	struct rtw89_hal *hal = &rtwdev->hal;
 	u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
 	int i;
@@ -3586,7 +3664,7 @@ int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev,
 				 struct rtw89_vif_link *rtwvif_link,
 				 struct rtw89_sta_link *rtwsta_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 
 	if (vif->type == NL80211_IFTYPE_STATION)
 		rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false);
@@ -3598,8 +3676,8 @@ int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev,
 				   struct rtw89_vif_link *rtwvif_link,
 				   struct rtw89_sta_link *rtwsta_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
-	struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link);
+	const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+	const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
 	int ret;
 
 	rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, true);
@@ -3641,8 +3719,8 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
 			      struct rtw89_vif_link *rtwvif_link,
 			      struct rtw89_sta_link *rtwsta_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
-	struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link);
+	const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+	const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
 	struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link,
 									 rtwsta_link);
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
@@ -3730,8 +3808,8 @@ int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev,
 			       struct rtw89_vif_link *rtwvif_link,
 			       struct rtw89_sta_link *rtwsta_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
-	struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link);
+	const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+	const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
 	int ret;
 
 	if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
@@ -4212,7 +4290,8 @@ void rtw89_core_update_beacon_work(struct work_struct *work)
 	if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE)
 		return;
 
-	rtwdev = rtwvif_link->rtwdev;
+	rtwdev = rtwvif_link->rtwvif->rtwdev;
+
 	mutex_lock(&rtwdev->mutex);
 	rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link);
 	mutex_unlock(&rtwdev->mutex);
@@ -4409,6 +4488,168 @@ void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id)
 	clear_bit(mac_id, rtwdev->mac_id_map);
 }
 
+void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+		    u8 mac_id, u8 port)
+{
+	const struct rtw89_chip_info *chip = rtwdev->chip;
+	u8 support_link_num = chip->support_link_num;
+	u8 support_mld_num = 0;
+	unsigned int link_id;
+	u8 index;
+
+	bitmap_zero(rtwvif->links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
+	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
+		rtwvif->links[link_id] = NULL;
+
+	rtwvif->rtwdev = rtwdev;
+
+	if (rtwdev->support_mlo) {
+		rtwvif->links_inst_valid_num = support_link_num;
+		support_mld_num = chip->support_macid_num / support_link_num;
+	} else {
+		rtwvif->links_inst_valid_num = 1;
+	}
+
+	for (index = 0; index < rtwvif->links_inst_valid_num; index++) {
+		struct rtw89_vif_link *inst = &rtwvif->links_inst[index];
+
+		inst->rtwvif = rtwvif;
+		inst->mac_id = mac_id + index * support_mld_num;
+		inst->mac_idx = RTW89_MAC_0 + index;
+		inst->phy_idx = RTW89_PHY_0 + index;
+
+		/* multi-link use the same port id on different HW bands */
+		inst->port = port;
+	}
+}
+
+void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+		    struct rtw89_sta *rtwsta, u8 mac_id)
+{
+	const struct rtw89_chip_info *chip = rtwdev->chip;
+	u8 support_link_num = chip->support_link_num;
+	u8 support_mld_num = 0;
+	unsigned int link_id;
+	u8 index;
+
+	bitmap_zero(rtwsta->links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
+	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
+		rtwsta->links[link_id] = NULL;
+
+	rtwsta->rtwdev = rtwdev;
+	rtwsta->rtwvif = rtwvif;
+
+	if (rtwdev->support_mlo) {
+		rtwsta->links_inst_valid_num = support_link_num;
+		support_mld_num = chip->support_macid_num / support_link_num;
+	} else {
+		rtwsta->links_inst_valid_num = 1;
+	}
+
+	for (index = 0; index < rtwsta->links_inst_valid_num; index++) {
+		struct rtw89_sta_link *inst = &rtwsta->links_inst[index];
+
+		inst->rtwvif_link = &rtwvif->links_inst[index];
+
+		inst->rtwsta = rtwsta;
+		inst->mac_id = mac_id + index * support_mld_num;
+	}
+}
+
+struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif,
+					  unsigned int link_id)
+{
+	struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id];
+	u8 index;
+	int ret;
+
+	if (rtwvif_link)
+		return rtwvif_link;
+
+	index = find_first_zero_bit(rtwvif->links_inst_map,
+				    rtwvif->links_inst_valid_num);
+	if (index == rtwvif->links_inst_valid_num) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	rtwvif_link = &rtwvif->links_inst[index];
+	rtwvif_link->link_id = link_id;
+
+	set_bit(index, rtwvif->links_inst_map);
+	rtwvif->links[link_id] = rtwvif_link;
+	return rtwvif_link;
+
+err:
+	rtw89_err(rtwvif->rtwdev, "vif (link_id %u) failed to set link: %d\n",
+		  link_id, ret);
+	return NULL;
+}
+
+void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id)
+{
+	struct rtw89_vif_link **container = &rtwvif->links[link_id];
+	struct rtw89_vif_link *link = *container;
+	u8 index;
+
+	if (!link)
+		return;
+
+	index = rtw89_vif_link_inst_get_index(link);
+	clear_bit(index, rtwvif->links_inst_map);
+	*container = NULL;
+}
+
+struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta,
+					  unsigned int link_id)
+{
+	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+	struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id];
+	struct rtw89_sta_link *rtwsta_link = rtwsta->links[link_id];
+	u8 index;
+	int ret;
+
+	if (rtwsta_link)
+		return rtwsta_link;
+
+	if (!rtwvif_link) {
+		ret = -ENOLINK;
+		goto err;
+	}
+
+	index = rtw89_vif_link_inst_get_index(rtwvif_link);
+	if (test_bit(index, rtwsta->links_inst_map)) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	rtwsta_link = &rtwsta->links_inst[index];
+	rtwsta_link->link_id = link_id;
+
+	set_bit(index, rtwsta->links_inst_map);
+	rtwsta->links[link_id] = rtwsta_link;
+	return rtwsta_link;
+
+err:
+	rtw89_err(rtwsta->rtwdev, "sta (link_id %u) failed to set link: %d\n",
+		  link_id, ret);
+	return NULL;
+}
+
+void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id)
+{
+	struct rtw89_sta_link **container = &rtwsta->links[link_id];
+	struct rtw89_sta_link *link = *container;
+	u8 index;
+
+	if (!link)
+		return;
+
+	index = rtw89_sta_link_inst_get_index(link);
+	clear_bit(index, rtwsta->links_inst_map);
+	*container = NULL;
+}
+
 int rtw89_core_init(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_btc *btc = &rtwdev->btc;
@@ -4519,10 +4760,8 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv
 }
 
 void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
-			      struct ieee80211_vif *vif, bool hw_scan)
+			      struct rtw89_vif_link *rtwvif_link, bool hw_scan)
 {
-	struct rtw89_vif_link *rtwvif_link =
-		vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL;
 	struct ieee80211_bss_conf *bss_conf;
 
 	if (!rtwvif_link)
@@ -4753,7 +4992,7 @@ EXPORT_SYMBOL(rtw89_chip_info_setup);
 void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
 				       struct rtw89_vif_link *rtwvif_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 	struct ieee80211_bss_conf *bss_conf;
 
@@ -4774,14 +5013,15 @@ void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
 static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
 {
 	const struct rtw89_chip_info *chip = rtwdev->chip;
+	u8 n = rtwdev->support_mlo ? chip->support_link_num : 1;
 	struct ieee80211_hw *hw = rtwdev->hw;
 	struct rtw89_efuse *efuse = &rtwdev->efuse;
 	struct rtw89_hal *hal = &rtwdev->hal;
 	int ret;
 	int tx_headroom = IEEE80211_HT_CTL_LEN;
 
-	hw->vif_data_size = sizeof(struct rtw89_vif_link);
-	hw->sta_data_size = sizeof(struct rtw89_sta_link);
+	hw->vif_data_size = struct_size_t(struct rtw89_vif, links_inst, n);
+	hw->sta_data_size = struct_size_t(struct rtw89_sta, links_inst, n);
 	hw->txq_data_size = sizeof(struct rtw89_txq);
 	hw->chanctx_data_size = sizeof(struct rtw89_chanctx_cfg);
 
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index bfa3dba07fe1e..de33320b1354c 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -829,6 +829,8 @@ enum rtw89_phy_idx {
 	RTW89_PHY_MAX
 };
 
+#define __RTW89_MLD_MAX_LINK_NUM 2
+
 enum rtw89_chanctx_idx {
 	RTW89_CHANCTX_0 = 0,
 	RTW89_CHANCTX_1 = 1,
@@ -1166,8 +1168,8 @@ struct rtw89_core_tx_request {
 	enum rtw89_core_tx_type tx_type;
 
 	struct sk_buff *skb;
-	struct ieee80211_vif *vif;
-	struct ieee80211_sta *sta;
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
 	struct rtw89_tx_desc_info desc_info;
 };
 
@@ -3355,12 +3357,11 @@ struct rtw89_sec_cam_entry {
 };
 
 struct rtw89_sta_link {
+	struct rtw89_sta *rtwsta;
 	unsigned int link_id;
 
 	u8 mac_id;
-	bool disassoc;
 	bool er_cap;
-	struct rtw89_dev *rtwdev;
 	struct rtw89_vif_link *rtwvif_link;
 	struct rtw89_ra_info ra;
 	struct rtw89_ra_report ra_report;
@@ -3372,15 +3373,12 @@ struct rtw89_sta_link {
 	struct ewma_evm evm_1ss;
 	struct ewma_evm evm_min[RF_PATH_MAX];
 	struct ewma_evm evm_max[RF_PATH_MAX];
-	struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS];
-	DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS);
 	struct ieee80211_rx_status rx_status;
 	u16 rx_hw_rate;
 	__le32 htc_template;
 	struct rtw89_addr_cam_entry addr_cam; /* AP mode or TDLS peer only */
 	struct rtw89_bssid_cam_entry bssid_cam; /* TDLS peer only */
 	struct list_head ba_cam_list;
-	struct sk_buff_head roc_queue;
 
 	bool use_cfg_mask;
 	struct cfg80211_bitrate_mask mask;
@@ -3463,11 +3461,9 @@ struct rtw89_p2p_noa_setter {
 };
 
 struct rtw89_vif_link {
+	struct rtw89_vif *rtwvif;
 	unsigned int link_id;
 
-	struct list_head list;
-	struct rtw89_dev *rtwdev;
-	struct rtw89_roc roc;
 	bool chanctx_assigned; /* only valid when running with chanctx_ops */
 	enum rtw89_chanctx_idx chanctx_idx;
 	enum rtw89_reg_6ghz_power reg_6ghz_power;
@@ -3477,7 +3473,6 @@ struct rtw89_vif_link {
 	u8 port;
 	u8 mac_addr[ETH_ALEN];
 	u8 bssid[ETH_ALEN];
-	__be32 ip_addr;
 	u8 phy_idx;
 	u8 mac_idx;
 	u8 net_type;
@@ -3488,7 +3483,6 @@ struct rtw89_vif_link {
 	u8 hit_rule;
 	u8 last_noa_nr;
 	u64 sync_bcn_tsf;
-	bool offchan;
 	bool trigger;
 	bool lsig_txop;
 	u8 tgt_ind;
@@ -3502,15 +3496,11 @@ struct rtw89_vif_link {
 	bool pre_pwr_diff_en;
 	bool pwr_diff_en;
 	u8 def_tri_idx;
-	u32 tdls_peer;
 	struct work_struct update_beacon_work;
 	struct rtw89_addr_cam_entry addr_cam;
 	struct rtw89_bssid_cam_entry bssid_cam;
 	struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS];
-	struct rtw89_traffic_stats stats;
 	struct rtw89_phy_rate_pattern rate_pattern;
-	struct cfg80211_scan_request *scan_req;
-	struct ieee80211_scan_ies *scan_ies;
 	struct list_head general_pkt_list;
 	struct rtw89_p2p_noa_setter p2p_noa;
 };
@@ -3659,14 +3649,16 @@ struct rtw89_chip_ops {
 				  struct rtw89_vif_link *rtwvif_link,
 				  struct rtw89_sta_link *rtwsta_link);
 	int (*h2c_ampdu_cmac_tbl)(struct rtw89_dev *rtwdev,
-				  struct ieee80211_vif *vif,
-				  struct ieee80211_sta *sta);
+				  struct rtw89_vif_link *rtwvif_link,
+				  struct rtw89_sta_link *rtwsta_link);
 	int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev,
 				    struct rtw89_vif_link *rtwvif_link,
 				    struct rtw89_sta_link *rtwsta_link);
 	int (*h2c_update_beacon)(struct rtw89_dev *rtwdev,
 				 struct rtw89_vif_link *rtwvif_link);
-	int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
+	int (*h2c_ba_cam)(struct rtw89_dev *rtwdev,
+			  struct rtw89_vif_link *rtwvif_link,
+			  struct rtw89_sta_link *rtwsta_link,
 			  bool valid, struct ieee80211_ampdu_params *params);
 
 	void (*btc_set_rfe)(struct rtw89_dev *rtwdev);
@@ -5200,7 +5192,7 @@ struct rtw89_early_h2c {
 };
 
 struct rtw89_hw_scan_info {
-	struct ieee80211_vif *scanning_vif;
+	struct rtw89_vif_link *scanning_vif;
 	struct list_head pkt_list[NUM_NL80211_BANDS];
 	struct rtw89_chan op_chan;
 	bool abort;
@@ -5375,7 +5367,7 @@ struct rtw89_wow_aoac_report {
 };
 
 struct rtw89_wow_param {
-	struct ieee80211_vif *wow_vif;
+	struct rtw89_vif_link *rtwvif_link;
 	DECLARE_BITMAP(flags, RTW89_WOW_FLAG_NUM);
 	struct rtw89_wow_cam_info patterns[RTW89_MAX_PATTERN_NUM];
 	struct rtw89_wow_key_info key_info;
@@ -5612,6 +5604,121 @@ struct rtw89_dev {
 	u8 priv[] __aligned(sizeof(void *));
 };
 
+struct rtw89_vif {
+	struct rtw89_dev *rtwdev;
+	struct list_head list;
+
+	u8 mac_addr[ETH_ALEN];
+	__be32 ip_addr;
+
+	struct rtw89_traffic_stats stats;
+	u32 tdls_peer;
+
+	struct ieee80211_scan_ies *scan_ies;
+	struct cfg80211_scan_request *scan_req;
+
+	struct rtw89_roc roc;
+	bool offchan;
+
+	u8 links_inst_valid_num;
+	DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
+	struct rtw89_vif_link *links[IEEE80211_MLD_MAX_NUM_LINKS];
+	struct rtw89_vif_link links_inst[] __counted_by(links_inst_valid_num);
+};
+
+static inline bool rtw89_vif_assign_link_is_valid(struct rtw89_vif_link **rtwvif_link,
+						  const struct rtw89_vif *rtwvif,
+						  unsigned int link_id)
+{
+	*rtwvif_link = rtwvif->links[link_id];
+	return !!*rtwvif_link;
+}
+
+#define rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) \
+	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \
+		if (rtw89_vif_assign_link_is_valid(&(rtwvif_link), rtwvif, link_id))
+
+struct rtw89_sta {
+	struct rtw89_dev *rtwdev;
+	struct rtw89_vif *rtwvif;
+
+	bool disassoc;
+
+	struct sk_buff_head roc_queue;
+
+	struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS];
+	DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS);
+
+	u8 links_inst_valid_num;
+	DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
+	struct rtw89_sta_link *links[IEEE80211_MLD_MAX_NUM_LINKS];
+	struct rtw89_sta_link links_inst[] __counted_by(links_inst_valid_num);
+};
+
+static inline bool rtw89_sta_assign_link_is_valid(struct rtw89_sta_link **rtwsta_link,
+						  const struct rtw89_sta *rtwsta,
+						  unsigned int link_id)
+{
+	*rtwsta_link = rtwsta->links[link_id];
+	return !!*rtwsta_link;
+}
+
+#define rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) \
+	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \
+		if (rtw89_sta_assign_link_is_valid(&(rtwsta_link), rtwsta, link_id))
+
+static inline u8 rtw89_vif_get_main_macid(struct rtw89_vif *rtwvif)
+{
+	/* const after init, so no need to check if active first */
+	return rtwvif->links_inst[0].mac_id;
+}
+
+static inline u8 rtw89_vif_get_main_port(struct rtw89_vif *rtwvif)
+{
+	/* const after init, so no need to check if active first */
+	return rtwvif->links_inst[0].port;
+}
+
+static inline struct rtw89_vif_link *
+rtw89_vif_get_link_inst(struct rtw89_vif *rtwvif, u8 index)
+{
+	if (index >= rtwvif->links_inst_valid_num ||
+	    !test_bit(index, rtwvif->links_inst_map))
+		return NULL;
+	return &rtwvif->links_inst[index];
+}
+
+static inline
+u8 rtw89_vif_link_inst_get_index(struct rtw89_vif_link *rtwvif_link)
+{
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+
+	return rtwvif_link - rtwvif->links_inst;
+}
+
+static inline u8 rtw89_sta_get_main_macid(struct rtw89_sta *rtwsta)
+{
+	/* const after init, so no need to check if active first */
+	return rtwsta->links_inst[0].mac_id;
+}
+
+static inline struct rtw89_sta_link *
+rtw89_sta_get_link_inst(struct rtw89_sta *rtwsta, u8 index)
+{
+	if (index >= rtwsta->links_inst_valid_num ||
+	    !test_bit(index, rtwsta->links_inst_map))
+		return NULL;
+	return &rtwsta->links_inst[index];
+}
+
+static inline
+u8 rtw89_sta_link_inst_get_index(struct rtw89_sta_link *rtwsta_link)
+{
+	struct rtw89_sta *rtwsta = rtwsta_link->rtwsta;
+
+	return rtwsta_link - rtwsta->links_inst;
+}
+
 static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev,
 				     struct rtw89_core_tx_request *tx_req)
 {
@@ -5964,44 +6071,78 @@ static inline void rtw89_core_txq_init(struct rtw89_dev *rtwdev,
 	INIT_LIST_HEAD(&rtwtxq->list);
 }
 
-static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw89_vif_link *rtwvif_link)
+static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw89_vif *rtwvif)
 {
-	void *p = rtwvif_link;
+	void *p = rtwvif;
 
 	return container_of(p, struct ieee80211_vif, drv_priv);
 }
 
-static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif_link *rtwvif_link)
+static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif *rtwvif)
 {
-	return rtwvif_link ? rtwvif_to_vif(rtwvif_link) : NULL;
+	return rtwvif ? rtwvif_to_vif(rtwvif) : NULL;
 }
 
-static inline struct rtw89_vif_link *vif_to_rtwvif_safe(struct ieee80211_vif *vif)
+static inline
+struct ieee80211_vif *rtwvif_link_to_vif(struct rtw89_vif_link *rtwvif_link)
 {
-	return vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL;
+	return rtwvif_to_vif(rtwvif_link->rtwvif);
 }
 
-static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta_link *rtwsta_link)
+static inline
+struct ieee80211_vif *rtwvif_link_to_vif_safe(struct rtw89_vif_link *rtwvif_link)
 {
-	void *p = rtwsta_link;
+	return rtwvif_link ? rtwvif_link_to_vif(rtwvif_link) : NULL;
+}
+
+static inline struct rtw89_vif *vif_to_rtwvif(struct ieee80211_vif *vif)
+{
+	return (struct rtw89_vif *)vif->drv_priv;
+}
+
+static inline struct rtw89_vif *vif_to_rtwvif_safe(struct ieee80211_vif *vif)
+{
+	return vif ? vif_to_rtwvif(vif) : NULL;
+}
+
+static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta *rtwsta)
+{
+	void *p = rtwsta;
 
 	return container_of(p, struct ieee80211_sta, drv_priv);
 }
 
-static inline struct ieee80211_sta *rtwsta_to_sta_safe(struct rtw89_sta_link *rtwsta_link)
+static inline struct ieee80211_sta *rtwsta_to_sta_safe(struct rtw89_sta *rtwsta)
+{
+	return rtwsta ? rtwsta_to_sta(rtwsta) : NULL;
+}
+
+static inline
+struct ieee80211_sta *rtwsta_link_to_sta(struct rtw89_sta_link *rtwsta_link)
+{
+	return rtwsta_to_sta(rtwsta_link->rtwsta);
+}
+
+static inline
+struct ieee80211_sta *rtwsta_link_to_sta_safe(struct rtw89_sta_link *rtwsta_link)
+{
+	return rtwsta_link ? rtwsta_link_to_sta(rtwsta_link) : NULL;
+}
+
+static inline struct rtw89_sta *sta_to_rtwsta(struct ieee80211_sta *sta)
 {
-	return rtwsta_link ? rtwsta_to_sta(rtwsta_link) : NULL;
+	return (struct rtw89_sta *)sta->drv_priv;
 }
 
-static inline struct rtw89_sta_link *sta_to_rtwsta_safe(struct ieee80211_sta *sta)
+static inline struct rtw89_sta *sta_to_rtwsta_safe(struct ieee80211_sta *sta)
 {
-	return sta ? (struct rtw89_sta_link *)sta->drv_priv : NULL;
+	return sta ? sta_to_rtwsta(sta) : NULL;
 }
 
 static inline struct ieee80211_bss_conf *
 __rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolink)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct ieee80211_bss_conf *bss_conf;
 
 	bss_conf = rcu_dereference(vif->link_conf[rtwvif_link->link_id]);
@@ -6022,7 +6163,7 @@ __rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolin
 									\
 	bss_conf = __rtw89_vif_rcu_dereference_link(p, &nolink);	\
 	if (unlikely(nolink) && (assert))				\
-		rtw89_err(p->rtwdev,					\
+		rtw89_err(p->rtwvif->rtwdev,				\
 			  "%s: cannot find exact bss_conf for link_id %u\n",\
 			  __func__, p->link_id);			\
 	bss_conf;							\
@@ -6031,7 +6172,7 @@ __rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolin
 static inline struct ieee80211_link_sta *
 __rtw89_sta_rcu_dereference_link(struct rtw89_sta_link *rtwsta_link, bool *nolink)
 {
-	struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link);
+	struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
 	struct ieee80211_link_sta *link_sta;
 
 	link_sta = rcu_dereference(sta->link[rtwsta_link->link_id]);
@@ -6052,7 +6193,7 @@ __rtw89_sta_rcu_dereference_link(struct rtw89_sta_link *rtwsta_link, bool *nolin
 									\
 	link_sta = __rtw89_sta_rcu_dereference_link(p, &nolink);	\
 	if (unlikely(nolink) && (assert))				\
-		rtw89_err(p->rtwdev,					\
+		rtw89_err(p->rtwsta->rtwdev,				\
 			  "%s: cannot find exact link_sta for link_id %u\n",\
 			  __func__, p->link_id);			\
 	link_sta;							\
@@ -6146,7 +6287,7 @@ struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif_link *rtwvif
 						   struct rtw89_sta_link *rtwsta_link)
 {
 	if (rtwsta_link) {
-		struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link);
+		struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
 
 		if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls)
 			return &rtwsta_link->addr_cam;
@@ -6159,7 +6300,7 @@ struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif_link *rtwv
 						     struct rtw89_sta_link *rtwsta_link)
 {
 	if (rtwsta_link) {
-		struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta_link);
+		struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
 
 		if (sta->tdls)
 			return &rtwsta_link->bssid_cam;
@@ -6223,8 +6364,7 @@ const struct rtw89_chan_rcd *rtw89_chan_rcd_get(struct rtw89_dev *rtwdev,
 static inline
 const struct rtw89_chan *rtw89_scan_chan_get(struct rtw89_dev *rtwdev)
 {
-	struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
-	struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif);
+	struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
 
 	if (rtwvif_link)
 		return rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
@@ -6686,13 +6826,21 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
 void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev);
 u8 rtw89_acquire_mac_id(struct rtw89_dev *rtwdev);
 void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id);
+void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+		    u8 mac_id, u8 port);
+void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+		    struct rtw89_sta *rtwsta, u8 mac_id);
+struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif,
+					  unsigned int link_id);
+void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id);
+struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta,
+					  unsigned int link_id);
+void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id);
 void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev);
 void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef);
 void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
 			      struct rtw89_chan *chan);
 int rtw89_set_channel(struct rtw89_dev *rtwdev);
-void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
-		       struct rtw89_chan *chan);
 u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size);
 void rtw89_core_release_bit_map(unsigned long *addr, u8 bit);
 void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits);
@@ -6726,12 +6874,12 @@ int rtw89_core_start(struct rtw89_dev *rtwdev);
 void rtw89_core_stop(struct rtw89_dev *rtwdev);
 void rtw89_core_update_beacon_work(struct work_struct *work);
 void rtw89_roc_work(struct work_struct *work);
-void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
-void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
+void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
 void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
 			   const u8 *mac_addr, bool hw_scan);
 void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
-			      struct ieee80211_vif *vif, bool hw_scan);
+			      struct rtw89_vif_link *rtwvif_link, bool hw_scan);
 int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
 			  bool active);
 void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index cc7aaf6fa31fc..7391f131229a5 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -3506,7 +3506,9 @@ static ssize_t rtw89_debug_priv_fw_log_manual_set(struct file *filp,
 	return count;
 }
 
-static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
+static void rtw89_sta_link_info_get_iter(struct seq_file *m,
+					 struct rtw89_dev *rtwdev,
+					 struct rtw89_sta_link *rtwsta_link)
 {
 	static const char * const he_gi_str[] = {
 		[NL80211_RATE_INFO_HE_GI_0_8] = "0.8",
@@ -3518,11 +3520,8 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
 		[NL80211_RATE_INFO_EHT_GI_1_6] = "1.6",
 		[NL80211_RATE_INFO_EHT_GI_3_2] = "3.2",
 	};
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
 	struct rate_info *rate = &rtwsta_link->ra_report.txrate;
 	struct ieee80211_rx_status *status = &rtwsta_link->rx_status;
-	struct seq_file *m = (struct seq_file *)data;
-	struct rtw89_dev *rtwdev = rtwsta_link->rtwdev;
 	struct rtw89_hal *hal = &rtwdev->hal;
 	u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
 	bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity;
@@ -3540,7 +3539,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
 
 	rcu_read_unlock();
 
-	seq_printf(m, "TX rate [%d]: ", rtwsta_link->mac_id);
+	seq_printf(m, "TX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id);
 
 	if (rate->flags & RATE_INFO_FLAGS_MCS)
 		seq_printf(m, "HT MCS-%d%s", rate->mcs,
@@ -3560,11 +3559,11 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
 		seq_printf(m, "Legacy %d", rate->legacy);
 	seq_printf(m, "%s", rtwsta_link->ra_report.might_fallback_legacy ? " FB_G" : "");
 	seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(rate->bw));
-	seq_printf(m, "\t(hw_rate=0x%x)", rtwsta_link->ra_report.hw_rate);
-	seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta_link->max_agg_wait,
+	seq_printf(m, " (hw_rate=0x%x)", rtwsta_link->ra_report.hw_rate);
+	seq_printf(m, " ==> agg_wait=%d (%d)\n", rtwsta_link->max_agg_wait,
 		   max_rc_amsdu_len);
 
-	seq_printf(m, "RX rate [%d]: ", rtwsta_link->mac_id);
+	seq_printf(m, "RX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id);
 
 	switch (status->encoding) {
 	case RX_ENC_LEGACY:
@@ -3591,7 +3590,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
 		break;
 	}
 	seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(status->bw));
-	seq_printf(m, "\t(hw_rate=0x%x)\n", rtwsta_link->rx_hw_rate);
+	seq_printf(m, " (hw_rate=0x%x)\n", rtwsta_link->rx_hw_rate);
 
 	rssi = ewma_rssi_read(&rtwsta_link->avg_rssi);
 	seq_printf(m, "RSSI: %d dBm (raw=%d, prev=%d) [",
@@ -3620,6 +3619,18 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
 	seq_printf(m, "SNR: %u\n", snr);
 }
 
+static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct seq_file *m = (struct seq_file *)data;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
+
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
+		rtw89_sta_link_info_get_iter(m, rtwdev, rtwsta_link);
+}
+
 static void
 rtw89_debug_append_rx_rate(struct seq_file *m, struct rtw89_pkt_stat *pkt_stat,
 			   enum rtw89_hw_rate first_rate, int len)
@@ -3746,25 +3757,37 @@ static void rtw89_dump_pkt_offload(struct seq_file *m, struct list_head *pkt_lis
 	seq_puts(m, "\n");
 }
 
-static
-void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+static void rtw89_vif_link_ids_get(struct seq_file *m, u8 *mac,
+				   struct rtw89_dev *rtwdev,
+				   struct rtw89_vif_link *rtwvif_link)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct rtw89_dev *rtwdev = rtwvif_link->rtwdev;
-	struct seq_file *m = (struct seq_file *)data;
 	struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam;
 
-	seq_printf(m, "VIF [%d] %pM\n", rtwvif_link->mac_id, rtwvif_link->mac_addr);
+	seq_printf(m, "    [%u] %pM\n", rtwvif_link->mac_id, rtwvif_link->mac_addr);
+	seq_printf(m, "\tlink_id=%u\n", rtwvif_link->link_id);
 	seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx);
 	rtw89_dump_addr_cam(m, rtwdev, &rtwvif_link->addr_cam);
 	rtw89_dump_pkt_offload(m, &rtwvif_link->general_pkt_list,
 			       "\tpkt_ofld[GENERAL]: ");
 }
 
-static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta_link *rtwsta_link)
+static
+void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct seq_file *m = (struct seq_file *)data;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+	struct rtw89_vif_link *rtwvif_link;
+	unsigned int link_id;
+
+	seq_printf(m, "VIF %pM\n", rtwvif->mac_addr);
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+		rtw89_vif_link_ids_get(m, mac, rtwdev, rtwvif_link);
+}
+
+static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_dev *rtwdev,
+			      struct rtw89_sta_link *rtwsta_link)
 {
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
-	struct rtw89_dev *rtwdev = rtwvif_link->rtwdev;
 	struct rtw89_ba_cam_entry *entry;
 	bool first = true;
 
@@ -3781,24 +3804,36 @@ static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta_link *rtwsta_
 	seq_puts(m, "\n");
 }
 
-static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
+static void rtw89_sta_link_ids_get(struct seq_file *m,
+				   struct rtw89_dev *rtwdev,
+				   struct rtw89_sta_link *rtwsta_link)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_dev *rtwdev = rtwsta_link->rtwdev;
-	struct seq_file *m = (struct seq_file *)data;
 	struct ieee80211_link_sta *link_sta;
 
 	rcu_read_lock();
 
 	link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
 
-	seq_printf(m, "STA [%d] %pM %s\n", rtwsta_link->mac_id, link_sta->addr,
-		   sta->tdls ? "(TDLS)" : "");
+	seq_printf(m, "    [%u] %pM\n", rtwsta_link->mac_id, link_sta->addr);
 
 	rcu_read_unlock();
 
+	seq_printf(m, "\tlink_id=%u\n", rtwsta_link->link_id);
 	rtw89_dump_addr_cam(m, rtwdev, &rtwsta_link->addr_cam);
-	rtw89_dump_ba_cam(m, rtwsta_link);
+	rtw89_dump_ba_cam(m, rtwdev, rtwsta_link);
+}
+
+static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct seq_file *m = (struct seq_file *)data;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
+
+	seq_printf(m, "STA %pM %s\n", sta->addr, sta->tdls ? "(TDLS)" : "");
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
+		rtw89_sta_link_ids_get(m, rtwdev, rtwsta_link);
 }
 
 static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 8e890ebae6134..37f931e887917 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -1909,11 +1909,12 @@ int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev,
 }
 EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2);
 
-int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
+int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev,
+			struct rtw89_vif_link *rtwvif_link,
+			struct rtw89_sta_link *rtwsta_link,
 			bool valid, struct ieee80211_ampdu_params *params)
 {
 	const struct rtw89_chip_info *chip = rtwdev->chip;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
 	struct rtw89_h2c_ba_cam *h2c;
 	u8 macid = rtwsta_link->mac_id;
 	u32 len = sizeof(*h2c);
@@ -2043,11 +2044,12 @@ void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev)
 	}
 }
 
-int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
+int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev,
+			   struct rtw89_vif_link *rtwvif_link,
+			   struct rtw89_sta_link *rtwsta_link,
 			   bool valid, struct ieee80211_ampdu_params *params)
 {
 	const struct rtw89_chip_info *chip = rtwdev->chip;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
 	struct rtw89_h2c_ba_cam_v1 *h2c;
 	u8 macid = rtwsta_link->mac_id;
 	u32 len = sizeof(*h2c);
@@ -2293,6 +2295,7 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev,
 static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev,
 					      struct rtw89_vif_link *rtwvif_link)
 {
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
 	u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev);
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
 	struct ieee80211_hdr_3addr *hdr;
@@ -2332,7 +2335,7 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev,
 	arp_hdr->ar_op = htons(ARPOP_REPLY);
 
 	ether_addr_copy(arp_skb->sender_hw, rtwvif_link->mac_addr);
-	arp_skb->sender_ip = rtwvif_link->ip_addr;
+	arp_skb->sender_ip = rtwvif->ip_addr;
 
 	return skb;
 }
@@ -2342,7 +2345,7 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
 					enum rtw89_fw_pkt_ofld_type type,
 					u8 *id)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_pktofld_info *info;
 	struct sk_buff *skb;
 	int ret;
@@ -2415,9 +2418,13 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
 void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw)
 {
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, notify_fw);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link,
+							      notify_fw);
 }
 
 #define H2C_GENERAL_PKT_LEN 6
@@ -2834,7 +2841,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
 				struct rtw89_vif_link *rtwvif_link,
 				struct rtw89_sta_link *rtwsta_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
 						       rtwvif_link->chanctx_idx);
@@ -2981,7 +2988,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
 				   struct rtw89_vif_link *rtwvif_link,
 				   struct rtw89_sta_link *rtwsta_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
 	u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
 	struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
@@ -3105,10 +3112,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
 EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_g7);
 
 int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
-				   struct ieee80211_vif *vif,
-				   struct ieee80211_sta *sta)
+				   struct rtw89_vif_link *rtwvif_link,
+				   struct rtw89_sta_link *rtwsta_link)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_sta *rtwsta = rtwsta_link->rtwsta;
 	struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
 	u32 len = sizeof(*h2c);
 	struct sk_buff *skb;
@@ -3125,11 +3132,11 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
 	skb_put(skb, len);
 	h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data;
 
-	for_each_set_bit(tid, rtwsta_link->ampdu_map, IEEE80211_NUM_TIDS) {
+	for_each_set_bit(tid, rtwsta->ampdu_map, IEEE80211_NUM_TIDS) {
 		if (agg_num == 0)
-			agg_num = rtwsta_link->ampdu_params[tid].agg_num;
+			agg_num = rtwsta->ampdu_params[tid].agg_num;
 		else
-			agg_num = min(agg_num, rtwsta_link->ampdu_params[tid].agg_num);
+			agg_num = min(agg_num, rtwsta->ampdu_params[tid].agg_num);
 	}
 
 	if (agg_num <= 0x20)
@@ -3256,7 +3263,7 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
 {
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
 						       rtwvif_link->chanctx_idx);
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_h2c_bcn_upd *h2c;
 	struct sk_buff *skb_beacon;
 	struct ieee80211_hdr *hdr;
@@ -3335,7 +3342,7 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev,
 				  struct rtw89_vif_link *rtwvif_link)
 {
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_h2c_bcn_upd_be *h2c;
 	struct sk_buff *skb_beacon;
 	struct ieee80211_hdr *hdr;
@@ -3899,7 +3906,8 @@ int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev,
 
 int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
 {
-	struct rtw89_traffic_stats *stats = &rtwvif_link->stats;
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+	struct rtw89_traffic_stats *stats = &rtwvif->stats;
 	struct rtw89_h2c_ofld *h2c;
 	u32 len = sizeof(*h2c);
 	struct sk_buff *skb;
@@ -5030,9 +5038,10 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
 				 struct rtw89_vif_link *rtwvif_link,
 				 bool wowlan)
 {
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
 	struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
 	struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
-	struct cfg80211_scan_request *req = rtwvif_link->scan_req;
+	struct cfg80211_scan_request *req = rtwvif->scan_req;
 	struct rtw89_h2c_scanofld_be_macc_role *macc_role;
 	struct rtw89_chan *op = &scan_info->op_chan;
 	struct rtw89_h2c_scanofld_be_opch *opch;
@@ -5935,12 +5944,10 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
 }
 
 static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev,
-					     struct rtw89_vif_link *rtwvif_link,
+					     struct cfg80211_scan_request *req,
 					     struct rtw89_pktofld_info *info,
 					     enum nl80211_band band, u8 ssid_idx)
 {
-	struct cfg80211_scan_request *req = rtwvif_link->scan_req;
-
 	if (band != NL80211_BAND_6GHZ)
 		return false;
 
@@ -5960,7 +5967,9 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
 				     struct sk_buff *skb, u8 ssid_idx)
 {
 	struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
-	struct ieee80211_scan_ies *ies = rtwvif_link->scan_ies;
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+	struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
+	struct cfg80211_scan_request *req = rtwvif->scan_req;
 	struct rtw89_pktofld_info *info;
 	struct sk_buff *new;
 	int ret = 0;
@@ -5985,8 +5994,7 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
 			goto out;
 		}
 
-		rtw89_is_6ghz_wildcard_probe_req(rtwdev, rtwvif_link, info, band,
-						 ssid_idx);
+		rtw89_is_6ghz_wildcard_probe_req(rtwdev, req, info, band, ssid_idx);
 
 		ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, new);
 		if (ret) {
@@ -6005,7 +6013,8 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
 static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
 					  struct rtw89_vif_link *rtwvif_link)
 {
-	struct cfg80211_scan_request *req = rtwvif_link->scan_req;
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+	struct cfg80211_scan_request *req = rtwvif->scan_req;
 	struct sk_buff *skb;
 	u8 num = req->n_ssids, i;
 	int ret;
@@ -6029,13 +6038,12 @@ static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
 }
 
 static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev,
+				      struct ieee80211_scan_ies *ies,
 				      struct cfg80211_scan_request *req,
 				      struct rtw89_mac_chinfo *ch_info)
 {
-	struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
 	struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
-	struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif);
-	struct ieee80211_scan_ies *ies = rtwvif_link->scan_ies;
 	struct cfg80211_scan_6ghz_params *params;
 	struct rtw89_pktofld_info *info, *tmp;
 	struct ieee80211_hdr *hdr;
@@ -6154,9 +6162,10 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
 				   struct rtw89_mac_chinfo *ch_info)
 {
 	struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
-	struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct cfg80211_scan_request *req = rtwvif_link->scan_req;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+	struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
+	struct cfg80211_scan_request *req = rtwvif->scan_req;
 	struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
 	struct rtw89_pktofld_info *info;
 	u8 band, probe_count = 0;
@@ -6181,7 +6190,7 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
 		}
 	}
 
-	ret = rtw89_update_6ghz_rnr_chan(rtwdev, req, ch_info);
+	ret = rtw89_update_6ghz_rnr_chan(rtwdev, ies, req, ch_info);
 	if (ret)
 		rtw89_warn(rtwdev, "RNR fails: %d\n", ret);
 
@@ -6271,9 +6280,9 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type,
 				      struct rtw89_mac_chinfo_be *ch_info)
 {
 	struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
-	struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct cfg80211_scan_request *req = rtwvif_link->scan_req;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+	struct cfg80211_scan_request *req = rtwvif->scan_req;
 	struct rtw89_pktofld_info *info;
 	u8 band, probe_count = 0, i;
 
@@ -6381,7 +6390,8 @@ int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
 int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
 				   struct rtw89_vif_link *rtwvif_link, bool connected)
 {
-	struct cfg80211_scan_request *req = rtwvif_link->scan_req;
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+	struct cfg80211_scan_request *req = rtwvif->scan_req;
 	struct rtw89_mac_chinfo	*ch_info, *tmp;
 	struct ieee80211_channel *channel;
 	struct list_head chan_list;
@@ -6510,7 +6520,8 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
 int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
 				   struct rtw89_vif_link *rtwvif_link, bool connected)
 {
-	struct cfg80211_scan_request *req = rtwvif_link->scan_req;
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+	struct cfg80211_scan_request *req = rtwvif->scan_req;
 	struct rtw89_mac_chinfo_be *ch_info, *tmp;
 	struct ieee80211_channel *channel;
 	struct list_head chan_list;
@@ -6582,21 +6593,26 @@ static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev,
 	return ret;
 }
 
-void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+void rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
+			 struct rtw89_vif_link *rtwvif_link,
 			 struct ieee80211_scan_request *scan_req)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 	struct cfg80211_scan_request *req = &scan_req->req;
+	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
+						       rtwvif_link->chanctx_idx);
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
 	u32 rx_fltr = rtwdev->hal.rx_fltr;
 	u8 mac_addr[ETH_ALEN];
 
-	rtw89_get_channel(rtwdev, rtwvif_link, &rtwdev->scan_info.op_chan);
-	rtwdev->scan_info.scanning_vif = vif;
+	/* clone op and keep it during scan */
+	rtwdev->scan_info.op_chan = *chan;
+
+	rtwdev->scan_info.scanning_vif = rtwvif_link;
 	rtwdev->scan_info.last_chan_idx = 0;
 	rtwdev->scan_info.abort = false;
-	rtwvif_link->scan_ies = &scan_req->ies;
-	rtwvif_link->scan_req = req;
+	rtwvif->scan_ies = &scan_req->ies;
+	rtwvif->scan_req = req;
 	ieee80211_stop_queues(rtwdev->hw);
 	rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, false);
 
@@ -6618,33 +6634,36 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
 	rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_HW_SCAN);
 }
 
-void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev,
+			    struct rtw89_vif_link *rtwvif_link,
 			    bool aborted)
 {
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 	struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
-	struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif);
 	struct cfg80211_scan_info info = {
 		.aborted = aborted,
 	};
+	struct rtw89_vif *rtwvif;
 
-	if (!vif)
+	if (!rtwvif_link)
 		return;
 
+	rtwvif = rtwvif_link->rtwvif;
+
 	rtw89_write32_mask(rtwdev,
 			   rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
 			   B_AX_RX_FLTR_CFG_MASK,
 			   rtwdev->hal.rx_fltr);
 
-	rtw89_core_scan_complete(rtwdev, vif, true);
+	rtw89_core_scan_complete(rtwdev, rtwvif_link, true);
 	ieee80211_scan_completed(rtwdev->hw, &info);
 	ieee80211_wake_queues(rtwdev->hw);
 	rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, true);
 	rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true);
 
 	rtw89_release_pkt_list(rtwdev);
-	rtwvif_link->scan_req = NULL;
-	rtwvif_link->scan_ies = NULL;
+	rtwvif->scan_req = NULL;
+	rtwvif->scan_ies = NULL;
 	scan_info->last_chan_idx = 0;
 	scan_info->scanning_vif = NULL;
 	scan_info->abort = false;
@@ -6652,14 +6671,15 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
 	rtw89_chanctx_proceed(rtwdev);
 }
 
-void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
+void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev,
+			 struct rtw89_vif_link *rtwvif_link)
 {
 	struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
 	int ret;
 
 	scan_info->abort = true;
 
-	ret = rtw89_hw_scan_offload(rtwdev, vif, false);
+	ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, false);
 	if (ret)
 		rtw89_warn(rtwdev, "rtw89_hw_scan_offload failed ret %d\n", ret);
 
@@ -6668,32 +6688,35 @@ void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
 	 * RTW89_SCAN_END_SCAN_NOTIFY, so that ieee80211_stop() can flush scan
 	 * work properly.
 	 */
-	rtw89_hw_scan_complete(rtwdev, vif, true);
+	rtw89_hw_scan_complete(rtwdev, rtwvif_link, true);
 }
 
 static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_vif_link *rtwvif_link;
-
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link) {
-		/* This variable implies connected or during attempt to connect */
-		if (!is_zero_ether_addr(rtwvif_link->bssid))
-			return true;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
+
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+			/* This variable implies connected or during attempt to connect */
+			if (!is_zero_ether_addr(rtwvif_link->bssid))
+				return true;
+		}
 	}
 
 	return false;
 }
 
-int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev,
+			  struct rtw89_vif_link *rtwvif_link,
 			  bool enable)
 {
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 	struct rtw89_scan_option opt = {0};
-	struct rtw89_vif_link *rtwvif_link;
 	bool connected;
 	int ret = 0;
 
-	rtwvif_link = vif ? (struct rtw89_vif_link *)vif->drv_priv : NULL;
 	if (!rtwvif_link)
 		return -EINVAL;
 
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 17e952bd70e36..ccbbc43f33fee 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -4419,8 +4419,8 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
 				   struct rtw89_vif_link *rtwvif_link,
 				   struct rtw89_sta_link *rtwsta_link);
 int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
-				   struct ieee80211_vif *vif,
-				   struct ieee80211_sta *sta);
+				   struct rtw89_vif_link *rtwvif_link,
+				   struct rtw89_sta_link *rtwsta_link);
 int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
 				 struct rtw89_sta_link *rtwsta_link);
 int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
@@ -4514,9 +4514,13 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
 					   struct rtw89_vif_link *rtwvif_link,
 					   bool notify_fw);
 void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw);
-int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
+int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev,
+			struct rtw89_vif_link *rtwvif_link,
+			struct rtw89_sta_link *rtwsta_link,
 			bool valid, struct ieee80211_ampdu_params *params);
-int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
+int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev,
+			   struct rtw89_vif_link *rtwvif_link,
+			   struct rtw89_sta_link *rtwsta_link,
 			   bool valid, struct ieee80211_ampdu_params *params);
 void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev);
 int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users,
@@ -4535,13 +4539,17 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev,
 		     struct rtw89_mac_c2h_info *c2h_info);
 int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable);
 void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev);
-void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
-			 struct ieee80211_scan_request *req);
-void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+void rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
+			 struct rtw89_vif_link *rtwvif_link,
+			 struct ieee80211_scan_request *scan_req);
+void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev,
+			    struct rtw89_vif_link *rtwvif_link,
 			    bool aborted);
-int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev,
+			  struct rtw89_vif_link *rtwvif_link,
 			  bool enable);
-void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
+void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev,
+			 struct rtw89_vif_link *rtwvif_link);
 int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
 				   struct rtw89_vif_link *rtwvif_link, bool connected);
 int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
@@ -4662,25 +4670,59 @@ static inline int rtw89_chip_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
 	return chip->ops->h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link);
 }
 
-static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev,
-						struct ieee80211_vif *vif,
-						struct ieee80211_sta *sta)
+static inline
+int rtw89_chip_h2c_ampdu_link_cmac_tbl(struct rtw89_dev *rtwdev,
+				       struct rtw89_vif_link *rtwvif_link,
+				       struct rtw89_sta_link *rtwsta_link)
 {
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 
 	if (chip->ops->h2c_ampdu_cmac_tbl)
-		return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, vif, sta);
+		return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, rtwvif_link,
+						     rtwsta_link);
+
+	return 0;
+}
+
+static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev,
+						struct rtw89_vif *rtwvif,
+						struct rtw89_sta *rtwsta)
+{
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
+	int ret;
+
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		ret = rtw89_chip_h2c_ampdu_link_cmac_tbl(rtwdev, rtwvif_link,
+							 rtwsta_link);
+		if (ret)
+			return ret;
+	}
 
 	return 0;
 }
 
 static inline
-int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
+int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
 			  bool valid, struct ieee80211_ampdu_params *params)
 {
 	const struct rtw89_chip_info *chip = rtwdev->chip;
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
+	int ret;
+
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		ret = chip->ops->h2c_ba_cam(rtwdev, rtwvif_link, rtwsta_link,
+					    valid, params);
+		if (ret)
+			return ret;
+	}
 
-	return chip->ops->h2c_ba_cam(rtwdev, rtwsta_link, valid, params);
+	return 0;
 }
 
 /* must consider compatibility; don't insert new in the mid */
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 28cc4885105a5..4e15d539e3d1c 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -4298,10 +4298,13 @@ static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev,
 void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en)
 {
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE)
-			rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE)
+				rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en);
 }
 
 static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev,
@@ -4547,13 +4550,17 @@ static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_vif_link *src = NULL, *tmp;
 	u8 offset = 100, vif_aps = 0;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 	int n_offset = 1;
 
-	rtw89_for_each_rtwvif(rtwdev, tmp) {
-		if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA)
-			src = tmp;
-		if (tmp->net_type == RTW89_NET_TYPE_AP_MODE)
-			vif_aps++;
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+		rtw89_vif_for_each_link(rtwvif, tmp, link_id) {
+			if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA)
+				src = tmp;
+			if (tmp->net_type == RTW89_NET_TYPE_AP_MODE)
+				vif_aps++;
+		}
 	}
 
 	if (vif_aps == 0)
@@ -4561,8 +4568,10 @@ static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev)
 
 	offset /= (vif_aps + 1);
 
-	rtw89_for_each_rtwvif(rtwdev, tmp)
-		rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, &n_offset);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		rtw89_vif_for_each_link(rtwvif, tmp, link_id)
+			rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset,
+						     &n_offset);
 }
 
 int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
@@ -4699,7 +4708,7 @@ static void rtw89_mac_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
 void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
 					struct rtw89_vif_link *rtwvif_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 	struct ieee80211_hw *hw = rtwdev->hw;
 	struct ieee80211_bss_conf *bss_conf;
@@ -4768,8 +4777,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
 {
 	const struct rtw89_c2h_scanofld *c2h =
 		(const struct rtw89_c2h_scanofld *)skb->data;
-	struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
-	struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif);
+	struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
+	struct rtw89_vif *rtwvif;
 	struct rtw89_chan new;
 	u8 reason, status, tx_fail, band, actual_period, expect_period;
 	u32 last_chan = rtwdev->scan_info.last_chan_idx, report_tsf;
@@ -4780,6 +4789,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
 	if (!rtwvif_link)
 		return;
 
+	rtwvif = rtwvif_link->rtwvif;
+
 	tx_fail = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_TX_FAIL);
 	status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS);
 	chan = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_PRI_CH);
@@ -4819,15 +4830,15 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
 		if (rtwdev->scan_info.abort)
 			return;
 
-		if (rtwvif_link && rtwvif_link->scan_req &&
-		    last_chan < rtwvif_link->scan_req->n_channels) {
-			ret = rtw89_hw_scan_offload(rtwdev, vif, true);
+		if (rtwvif_link && rtwvif->scan_req &&
+		    last_chan < rtwvif->scan_req->n_channels) {
+			ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true);
 			if (ret) {
-				rtw89_hw_scan_abort(rtwdev, vif);
+				rtw89_hw_scan_abort(rtwdev, rtwvif_link);
 				rtw89_warn(rtwdev, "HW scan failed: %d\n", ret);
 			}
 		} else {
-			rtw89_hw_scan_complete(rtwdev, vif, false);
+			rtw89_hw_scan_complete(rtwdev, rtwvif_link, false);
 		}
 		break;
 	case RTW89_SCAN_ENTER_OP_NOTIFY:
@@ -4853,7 +4864,8 @@ static void
 rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
 		       struct sk_buff *skb)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
 	enum nl80211_cqm_rssi_threshold_event nl_event;
 	const struct rtw89_c2h_mac_bcnfltr_rpt *c2h =
 		(const struct rtw89_c2h_mac_bcnfltr_rpt *)skb->data;
@@ -4874,7 +4886,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l
 
 	switch (type) {
 	case RTW89_BCN_FLTR_BEACON_LOSS:
-		if (!rtwdev->scanning && !rtwvif_link->offchan)
+		if (!rtwdev->scanning && !rtwvif->offchan)
 			ieee80211_connection_loss(vif);
 		else
 			rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
@@ -4902,9 +4914,12 @@ rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
 			   u32 len)
 {
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif_link, c2h);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif_link, c2h);
 }
 
 static void
@@ -6112,10 +6127,21 @@ void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev,
 void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
 				struct ieee80211_bss_conf *conf)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	u8 mac_idx = rtwvif_link->mac_idx;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
+	u8 mac_idx;
 	__le32 *p;
 
+	rtwvif_link = rtwvif->links[conf->link_id];
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev,
+			  "%s: rtwvif link (link_id %u) is not active\n",
+			  __func__, conf->link_id);
+		return;
+	}
+
+	mac_idx = rtwvif_link->mac_idx;
+
 	rtw89_debug(rtwdev, RTW89_DBG_BF, "update bf GID table\n");
 
 	p = (__le32 *)conf->mu_group.membership;
@@ -6146,20 +6172,30 @@ struct rtw89_mac_bf_monitor_iter_data {
 static
 void rtw89_mac_bf_monitor_calc_iter(void *data, struct ieee80211_sta *sta)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
 	struct rtw89_mac_bf_monitor_iter_data *iter_data =
 				(struct rtw89_mac_bf_monitor_iter_data *)data;
 	struct rtw89_sta_link *down_rtwsta_link = iter_data->down_rtwsta_link;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
 	struct ieee80211_link_sta *link_sta;
+	struct rtw89_sta_link *rtwsta_link;
+	bool has_beamformer_cap = false;
 	int *count = &iter_data->count;
-
-	if (down_rtwsta_link == rtwsta_link)
-		return;
+	unsigned int link_id;
 
 	rcu_read_lock();
 
-	link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
-	if (rtw89_sta_has_beamformer_cap(link_sta))
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		if (rtwsta_link == down_rtwsta_link)
+			continue;
+
+		link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
+		if (rtw89_sta_has_beamformer_cap(link_sta)) {
+			has_beamformer_cap = true;
+			break;
+		}
+	}
+
+	if (has_beamformer_cap)
 		(*count)++;
 
 	rcu_read_unlock();
@@ -6191,7 +6227,9 @@ void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev)
 	struct rtw89_vif_link *rtwvif_link;
 	bool en = stats->tx_tfc_lv <= stats->rx_tfc_lv;
 	bool old = test_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags);
+	struct rtw89_vif *rtwvif;
 	bool keep_timer = true;
+	unsigned int link_id;
 	bool old_keep_timer;
 
 	old_keep_timer = test_bit(RTW89_FLAG_BFEE_TIMER_KEEP, rtwdev->flags);
@@ -6200,16 +6238,18 @@ void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev)
 		keep_timer = false;
 
 	if (keep_timer != old_keep_timer) {
-		rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-			rtw89_mac_bfee_standby_timer(rtwdev, rtwvif_link->mac_idx,
-						     keep_timer);
+		rtw89_for_each_rtwvif(rtwdev, rtwvif)
+			rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+				rtw89_mac_bfee_standby_timer(rtwdev, rtwvif_link->mac_idx,
+							     keep_timer);
 	}
 
 	if (en == old)
 		return;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, en);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, en);
 }
 
 static int
@@ -6393,7 +6433,9 @@ int rtw89_mac_read_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 *val)
 }
 
 static
-void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link)
+void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev,
+			    struct rtw89_vif_link *rtwvif_link,
+			    struct rtw89_sta_link *rtwsta_link)
 {
 	static const enum rtw89_pkt_drop_sel sels[] = {
 		RTW89_PKT_DROP_SEL_MACID_BE_ONCE,
@@ -6401,7 +6443,6 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtw
 		RTW89_PKT_DROP_SEL_MACID_VI_ONCE,
 		RTW89_PKT_DROP_SEL_MACID_VO_ONCE,
 	};
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
 	struct rtw89_pkt_drop_params params = {0};
 	int i;
 
@@ -6419,22 +6460,28 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtw
 
 static void rtw89_mac_pkt_drop_vif_iter(void *data, struct ieee80211_sta *sta)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
-	struct rtw89_dev *rtwdev = rtwvif_link->rtwdev;
-	struct rtw89_vif_link *target = data;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	struct rtw89_vif *target = data;
+	unsigned int link_id;
 
-	if (rtwvif_link != target)
+	if (rtwvif != target)
 		return;
 
-	rtw89_mac_pkt_drop_sta(rtwdev, rtwsta_link);
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		rtw89_mac_pkt_drop_sta(rtwdev, rtwvif_link, rtwsta_link);
+	}
 }
 
-void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
+void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
 	ieee80211_iterate_stations_atomic(rtwdev->hw,
 					  rtw89_mac_pkt_drop_vif_iter,
-					  rtwvif_link);
+					  rtwvif);
 }
 
 int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index b781b823496f6..0c269961a5731 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -1466,7 +1466,7 @@ int rtw89_mac_read_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 *val)
 	return mac->read_xtal_si(rtwdev, offset, val);
 }
 
-void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
+void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
 int rtw89_mac_resize_ple_rx_quota(struct rtw89_dev *rtwdev, bool wow);
 int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev,
 					enum rtw89_mac_idx band);
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index fc05ad1b799bf..44ba4dc181b5b 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -23,17 +23,16 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw,
 	struct rtw89_dev *rtwdev = hw->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_vif *vif = info->control.vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
 	struct ieee80211_sta *sta = control->sta;
 	u32 flags = IEEE80211_SKB_CB(skb)->flags;
 	int ret, qsel;
 
-	if (rtwvif_link->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) {
-		struct rtw89_sta_link *rtwsta_link =
-			(struct rtw89_sta_link *)sta->drv_priv;
+	if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) {
+		struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
 
 		rtw89_debug(rtwdev, RTW89_DBG_TXRX, "ops_tx during offchan\n");
-		skb_queue_tail(&rtwsta_link->roc_queue, skb);
+		skb_queue_tail(&rtwsta->roc_queue, skb);
 		return;
 	}
 
@@ -158,7 +157,8 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
 	u8 mac_id, port;
 	int ret = 0;
 
@@ -173,13 +173,6 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
 		vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
 				     IEEE80211_VIF_SUPPORTS_CQM_RSSI;
 
-	rtwvif_link->rtwdev = rtwdev;
-	rtwvif_link->roc.state = RTW89_ROC_IDLE;
-	rtwvif_link->offchan = false;
-	INIT_DELAYED_WORK(&rtwvif_link->roc.roc_work, rtw89_roc_work);
-
-	rtw89_traffic_stats_init(rtwdev, &rtwvif_link->stats);
-
 	mac_id = rtw89_acquire_mac_id(rtwdev);
 	if (mac_id == RTW89_MAX_MAC_ID_NUM) {
 		ret = -ENOSPC;
@@ -192,27 +185,40 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
 		goto release_macid;
 	}
 
-	rtwvif_link->mac_idx = RTW89_MAC_0;
-	rtwvif_link->phy_idx = RTW89_PHY_0;
-	rtwvif_link->mac_id = mac_id;
-	rtwvif_link->port = port;
+	rtw89_init_vif(rtwdev, rtwvif, mac_id, port);
 
 	rtw89_core_txq_init(rtwdev, vif->txq);
 
-	if (!rtw89_rtwvif_in_list(rtwdev, rtwvif_link))
-		list_add_tail(&rtwvif_link->list, &rtwdev->rtwvifs_list);
+	if (!rtw89_rtwvif_in_list(rtwdev, rtwvif))
+		list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
+
+	ether_addr_copy(rtwvif->mac_addr, vif->addr);
+
+	rtwvif->offchan = false;
+	rtwvif->roc.state = RTW89_ROC_IDLE;
+	INIT_DELAYED_WORK(&rtwvif->roc.roc_work, rtw89_roc_work);
+
+	rtw89_traffic_stats_init(rtwdev, &rtwvif->stats);
+
+	rtwvif_link = rtw89_vif_set_link(rtwvif, 0);
+	if (!rtwvif_link) {
+		ret = -EINVAL;
+		goto release_port;
+	}
 
 	ret = __rtw89_ops_add_iface_link(rtwdev, rtwvif_link);
 	if (ret)
-		goto release_port;
+		goto unset_link;
 
 	rtw89_recalc_lps(rtwdev);
 
 	mutex_unlock(&rtwdev->mutex);
 	return 0;
 
+unset_link:
+	rtw89_vif_unset_link(rtwvif, 0);
 release_port:
-	list_del_init(&rtwvif_link->list);
+	list_del_init(&rtwvif->list);
 	rtw89_core_release_bit_map(rtwdev->hw_port, port);
 release_macid:
 	rtw89_release_mac_id(rtwdev, mac_id);
@@ -226,20 +232,35 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	u8 macid = rtw89_vif_get_main_macid(rtwvif);
+	u8 port = rtw89_vif_get_main_port(rtwvif);
+	struct rtw89_vif_link *rtwvif_link;
 
 	rtw89_debug(rtwdev, RTW89_DBG_STATE, "remove vif %pM type %d p2p %d\n",
 		    vif->addr, vif->type, vif->p2p);
 
-	cancel_delayed_work_sync(&rtwvif_link->roc.roc_work);
+	cancel_delayed_work_sync(&rtwvif->roc.roc_work);
 
 	mutex_lock(&rtwdev->mutex);
 
+	rtwvif_link = rtwvif->links[0];
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev,
+			  "%s: rtwvif link (link_id %u) is not active\n",
+			  __func__, 0);
+		goto bottom;
+	}
+
 	__rtw89_ops_remove_iface_link(rtwdev, rtwvif_link);
 
-	rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port);
-	rtw89_release_mac_id(rtwdev, rtwvif_link->mac_id);
-	list_del_init(&rtwvif_link->list);
+	rtw89_vif_unset_link(rtwvif, 0);
+
+bottom:
+	list_del_init(&rtwvif->list);
+	rtw89_core_release_bit_map(rtwdev->hw_port, port);
+	rtw89_release_mac_id(rtwdev, macid);
+
 	rtw89_recalc_lps(rtwdev);
 	rtw89_enter_ips_by_hwflags(rtwdev);
 
@@ -460,8 +481,10 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev,
 			       struct ieee80211_vif *vif,
 			       struct ieee80211_sta *sta)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
 	bool acquire_macid = false;
 	u8 macid;
 	int ret;
@@ -469,7 +492,7 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev,
 
 	if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
 		/* for station mode, assign the mac_id from itself */
-		macid = rtwvif_link->mac_id;
+		macid = rtw89_vif_get_main_macid(rtwvif);
 	} else {
 		macid = rtw89_acquire_mac_id(rtwdev);
 		if (macid == RTW89_MAX_MAC_ID_NUM)
@@ -478,24 +501,32 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev,
 		acquire_macid = true;
 	}
 
-	rtwsta_link->rtwdev = rtwdev;
-	rtwsta_link->rtwvif_link = rtwvif_link;
-	rtwsta_link->mac_id = macid;
+	rtw89_init_sta(rtwdev, rtwvif, rtwsta, macid);
 
 	for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
 		rtw89_core_txq_init(rtwdev, sta->txq[i]);
 
-	skb_queue_head_init(&rtwsta_link->roc_queue);
+	skb_queue_head_init(&rtwsta->roc_queue);
+
+	rtwsta_link = rtw89_sta_set_link(rtwsta, sta->deflink.link_id);
+	if (!rtwsta_link) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	rtwvif_link = rtwsta_link->rtwvif_link;
 
 	ret = rtw89_core_sta_link_add(rtwdev, rtwvif_link, rtwsta_link);
 	if (ret)
-		goto err;
+		goto unset_link;
 
 	if (vif->type == NL80211_IFTYPE_AP || sta->tdls)
 		rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE);
 
 	return 0;
 
+unset_link:
+	rtw89_sta_unset_link(rtwsta, sta->deflink.link_id);
 err:
 	if (acquire_macid)
 		rtw89_release_mac_id(rtwdev, macid);
@@ -508,20 +539,27 @@ static int __rtw89_ops_sta_assoc(struct rtw89_dev *rtwdev,
 				 struct ieee80211_sta *sta,
 				 bool station_mode)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
 	int ret;
 
-	if (station_mode)
-		rtw89_vif_type_mapping(rtwvif_link, true);
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
 
-	ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link);
-	if (ret)
-		return ret;
+		if (station_mode)
+			rtw89_vif_type_mapping(rtwvif_link, true);
+
+		ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link);
+		if (ret)
+			return ret;
+	}
 
 	rtwdev->total_sta_assoc++;
 	if (sta->tdls)
-		rtwvif_link->tdls_peer++;
+		rtwvif->tdls_peer++;
 
 	return 0;
 }
@@ -530,19 +568,25 @@ static int __rtw89_ops_sta_disassoc(struct rtw89_dev *rtwdev,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_sta *sta)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
 	int ret;
 
-	ret = rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link);
-	if (ret)
-		return ret;
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		ret = rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link);
+		if (ret)
+			return ret;
+	}
 
-	rtwsta_link->disassoc = true;
+	rtwsta->disassoc = true;
 
 	rtwdev->total_sta_assoc--;
 	if (sta->tdls)
-		rtwvif_link->tdls_peer--;
+		rtwvif->tdls_peer--;
 
 	return 0;
 }
@@ -551,17 +595,22 @@ static int __rtw89_ops_sta_disconnect(struct rtw89_dev *rtwdev,
 				      struct ieee80211_vif *vif,
 				      struct ieee80211_sta *sta)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
 	int ret;
 
 	rtw89_core_free_sta_pending_ba(rtwdev, sta);
 	rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta);
 	rtw89_core_free_sta_pending_roc_tx(rtwdev, sta);
 
-	ret = rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link);
-	if (ret)
-		return ret;
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		ret = rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link);
+		if (ret)
+			return ret;
+	}
 
 	return 0;
 }
@@ -570,14 +619,21 @@ static int __rtw89_ops_sta_remove(struct rtw89_dev *rtwdev,
 				  struct ieee80211_vif *vif,
 				  struct ieee80211_sta *sta)
 {
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	u8 macid = rtwsta_link->mac_id;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	u8 macid = rtw89_sta_get_main_macid(rtwsta);
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
 	int ret;
 
-	ret = rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link);
-	if (ret)
-		return ret;
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		ret = rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link);
+		if (ret)
+			return ret;
+
+		rtw89_sta_unset_link(rtwsta, link_id);
+	}
 
 	if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
 		rtw89_release_mac_id(rtwdev, macid);
@@ -613,11 +669,22 @@ static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev,
 	rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link);
 }
 
+static void __rtw89_ops_bss_assoc(struct rtw89_dev *rtwdev,
+				  struct ieee80211_vif *vif)
+{
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
+	unsigned int link_id;
+
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+		__rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link);
+}
+
 static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw,
 				      struct ieee80211_vif *vif, u64 changed)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
 
 	mutex_lock(&rtwdev->mutex);
 	rtw89_leave_ps_mode(rtwdev);
@@ -625,7 +692,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw,
 	if (changed & BSS_CHANGED_ASSOC) {
 		if (vif->cfg.assoc) {
 			rtw89_station_mode_sta_assoc(rtwdev, vif);
-			__rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link);
+			__rtw89_ops_bss_assoc(rtwdev, vif);
 
 			rtw89_queue_chanctx_work(rtwdev);
 		} else {
@@ -641,7 +708,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw,
 		rtw89_recalc_lps(rtwdev);
 
 	if (changed & BSS_CHANGED_ARP_FILTER)
-		rtwvif_link->ip_addr = vif->cfg.arp_addr_list[0];
+		rtwvif->ip_addr = vif->cfg.arp_addr_list[0];
 
 	mutex_unlock(&rtwdev->mutex);
 }
@@ -652,11 +719,20 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw,
 					u64 changed)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
 
 	mutex_lock(&rtwdev->mutex);
 	rtw89_leave_ps_mode(rtwdev);
 
+	rtwvif_link = rtwvif->links[conf->link_id];
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev,
+			  "%s: rtwvif link (link_id %u) is not active\n",
+			  __func__, conf->link_id);
+		goto out;
+	}
+
 	if (changed & BSS_CHANGED_BSSID) {
 		ether_addr_copy(rtwvif_link->bssid, conf->bssid);
 		rtw89_cam_bssid_changed(rtwdev, rtwvif_link);
@@ -685,6 +761,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw,
 	if (changed & BSS_CHANGED_TPE)
 		rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true);
 
+out:
 	mutex_unlock(&rtwdev->mutex);
 }
 
@@ -693,11 +770,20 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
 			      struct ieee80211_bss_conf *link_conf)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
 	const struct rtw89_chan *chan;
 
 	mutex_lock(&rtwdev->mutex);
 
+	rtwvif_link = rtwvif->links[link_conf->link_id];
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev,
+			  "%s: rtwvif link (link_id %u) is not active\n",
+			  __func__, link_conf->link_id);
+		goto out;
+	}
+
 	chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
 	if (chan->band_type == RTW89_BAND_6G) {
 		mutex_unlock(&rtwdev->mutex);
@@ -717,6 +803,8 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
 	rtw89_chip_rfk_channel(rtwdev, rtwvif_link);
 
 	rtw89_queue_chanctx_work(rtwdev);
+
+out:
 	mutex_unlock(&rtwdev->mutex);
 
 	return 0;
@@ -727,12 +815,24 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct ieee80211_bss_conf *link_conf)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
 
 	mutex_lock(&rtwdev->mutex);
+
+	rtwvif_link = rtwvif->links[link_conf->link_id];
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev,
+			  "%s: rtwvif link (link_id %u) is not active\n",
+			  __func__, link_conf->link_id);
+		goto out;
+	}
+
 	rtw89_mac_stop_ap(rtwdev, rtwvif_link);
 	rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL);
 	rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true);
+
+out:
 	mutex_unlock(&rtwdev->mutex);
 }
 
@@ -740,10 +840,13 @@ static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 			     bool set)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+	struct rtw89_vif_link *rtwvif_link;
+	unsigned int link_id;
 
-	ieee80211_queue_work(rtwdev->hw, &rtwvif_link->update_beacon_work);
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+		ieee80211_queue_work(rtwdev->hw, &rtwvif_link->update_beacon_work);
 
 	return 0;
 }
@@ -754,15 +857,29 @@ static int rtw89_ops_conf_tx(struct ieee80211_hw *hw,
 			     const struct ieee80211_tx_queue_params *params)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
+	int ret = 0;
 
 	mutex_lock(&rtwdev->mutex);
 	rtw89_leave_ps_mode(rtwdev);
+
+	rtwvif_link = rtwvif->links[link_id];
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev,
+			  "%s: rtwvif link (link_id %u) is not active\n",
+			  __func__, link_id);
+		ret = -ENOLINK;
+		goto out;
+	}
+
 	rtwvif_link->tx_params[ac] = *params;
 	__rtw89_conf_tx(rtwdev, rtwvif_link, ac);
+
+out:
 	mutex_unlock(&rtwdev->mutex);
 
-	return 0;
+	return ret;
 }
 
 static int __rtw89_ops_sta_state(struct ieee80211_hw *hw,
@@ -860,7 +977,8 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
 {
 	struct rtw89_dev *rtwdev = hw->priv;
 	struct ieee80211_sta *sta = params->sta;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
 	u16 tid = params->tid;
 	struct ieee80211_txq *txq = sta->txq[tid];
 	struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv;
@@ -873,29 +991,29 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
 		mutex_lock(&rtwdev->mutex);
 		clear_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags);
-		clear_bit(tid, rtwsta_link->ampdu_map);
-		rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta);
+		clear_bit(tid, rtwsta->ampdu_map);
+		rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta);
 		mutex_unlock(&rtwdev->mutex);
 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
 		mutex_lock(&rtwdev->mutex);
 		set_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags);
-		rtwsta_link->ampdu_params[tid].agg_num = params->buf_size;
-		rtwsta_link->ampdu_params[tid].amsdu = params->amsdu;
-		set_bit(tid, rtwsta_link->ampdu_map);
+		rtwsta->ampdu_params[tid].agg_num = params->buf_size;
+		rtwsta->ampdu_params[tid].amsdu = params->amsdu;
+		set_bit(tid, rtwsta->ampdu_map);
 		rtw89_leave_ps_mode(rtwdev);
-		rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta);
+		rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta);
 		mutex_unlock(&rtwdev->mutex);
 		break;
 	case IEEE80211_AMPDU_RX_START:
 		mutex_lock(&rtwdev->mutex);
-		rtw89_chip_h2c_ba_cam(rtwdev, rtwsta_link, true, params);
+		rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, true, params);
 		mutex_unlock(&rtwdev->mutex);
 		break;
 	case IEEE80211_AMPDU_RX_STOP:
 		mutex_lock(&rtwdev->mutex);
-		rtw89_chip_h2c_ba_cam(rtwdev, rtwsta_link, false, params);
+		rtw89_chip_h2c_ba_cam(rtwdev, rtwsta, false, params);
 		mutex_unlock(&rtwdev->mutex);
 		break;
 	default:
@@ -924,7 +1042,12 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw,
 				     struct ieee80211_sta *sta,
 				     struct station_info *sinfo)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_sta_link *rtwsta_link;
+
+	rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+	if (unlikely(!rtwsta_link))
+		return;
 
 	sinfo->txrate = rtwsta_link->ra_report.txrate;
 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
@@ -933,14 +1056,14 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw,
 static
 void __rtw89_drop_packets(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
 {
-	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
 
 	if (vif) {
-		rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
-		rtw89_mac_pkt_drop_vif(rtwdev, rtwvif_link);
+		rtwvif = vif_to_rtwvif(vif);
+		rtw89_mac_pkt_drop_vif(rtwdev, rtwvif);
 	} else {
-		rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-			rtw89_mac_pkt_drop_vif(rtwdev, rtwvif_link);
+		rtw89_for_each_rtwvif(rtwdev, rtwvif)
+			rtw89_mac_pkt_drop_vif(rtwdev, rtwvif);
 	}
 }
 
@@ -970,14 +1093,20 @@ struct rtw89_iter_bitrate_mask_data {
 static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
 {
 	struct rtw89_iter_bitrate_mask_data *br_data = data;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta_link->rtwvif_link);
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
 
 	if (vif != br_data->vif || vif->p2p)
 		return;
 
-	rtwsta_link->use_cfg_mask = true;
-	rtwsta_link->mask = *br_data->mask;
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwsta_link->use_cfg_mask = true;
+		rtwsta_link->mask = *br_data->mask;
+	}
+
 	rtw89_phy_ra_update_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED);
 }
 
@@ -1047,10 +1176,20 @@ static void rtw89_ops_sw_scan_start(struct ieee80211_hw *hw,
 				    const u8 *mac_addr)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
 
 	mutex_lock(&rtwdev->mutex);
+
+	rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev, "sw scan start: find no link on HW-0\n");
+		goto out;
+	}
+
 	rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, false);
+
+out:
 	mutex_unlock(&rtwdev->mutex);
 }
 
@@ -1058,9 +1197,20 @@ static void rtw89_ops_sw_scan_complete(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
 
 	mutex_lock(&rtwdev->mutex);
-	rtw89_core_scan_complete(rtwdev, vif, false);
+
+	rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev, "sw scan complete: find no link on HW-0\n");
+		goto out;
+	}
+
+	rtw89_core_scan_complete(rtwdev, rtwvif_link, false);
+
+out:
 	mutex_unlock(&rtwdev->mutex);
 }
 
@@ -1077,22 +1227,35 @@ static int rtw89_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			     struct ieee80211_scan_request *req)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif);
-	int ret = 0;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
+	int ret;
 
 	if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw))
 		return 1;
 
-	if (rtwdev->scanning || rtwvif_link->offchan)
-		return -EBUSY;
-
 	mutex_lock(&rtwdev->mutex);
-	rtw89_hw_scan_start(rtwdev, vif, req);
-	ret = rtw89_hw_scan_offload(rtwdev, vif, true);
+
+	if (rtwdev->scanning || rtwvif->offchan) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev, "hw scan: find no link on HW-0\n");
+		ret = -ENOLINK;
+		goto out;
+	}
+
+	rtw89_hw_scan_start(rtwdev, rtwvif_link, req);
+	ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true);
 	if (ret) {
-		rtw89_hw_scan_abort(rtwdev, vif);
+		rtw89_hw_scan_abort(rtwdev, rtwvif_link);
 		rtw89_err(rtwdev, "HW scan failed with status: %d\n", ret);
 	}
+
+out:
 	mutex_unlock(&rtwdev->mutex);
 
 	return ret;
@@ -1102,6 +1265,8 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
 
 	if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw))
 		return;
@@ -1110,7 +1275,16 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw,
 		return;
 
 	mutex_lock(&rtwdev->mutex);
-	rtw89_hw_scan_abort(rtwdev, vif);
+
+	rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev, "cancel hw scan: find no link on HW-0\n");
+		goto out;
+	}
+
+	rtw89_hw_scan_abort(rtwdev, rtwvif_link);
+
+out:
 	mutex_unlock(&rtwdev->mutex);
 }
 
@@ -1163,11 +1337,24 @@ static int rtw89_ops_assign_vif_chanctx(struct ieee80211_hw *hw,
 					struct ieee80211_chanctx_conf *ctx)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
 	int ret;
 
 	mutex_lock(&rtwdev->mutex);
+
+	rtwvif_link = rtwvif->links[link_conf->link_id];
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev,
+			  "%s: rtwvif link (link_id %u) is not active\n",
+			  __func__, link_conf->link_id);
+		ret = -ENOLINK;
+		goto out;
+	}
+
 	ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, ctx);
+
+out:
 	mutex_unlock(&rtwdev->mutex);
 
 	return ret;
@@ -1179,9 +1366,19 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw,
 					   struct ieee80211_chanctx_conf *ctx)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
 
 	mutex_lock(&rtwdev->mutex);
+
+	rtwvif_link = rtwvif->links[link_conf->link_id];
+	if (unlikely(!rtwvif_link)) {
+		rtw89_err(rtwdev,
+			  "%s: rtwvif link (link_id %u) is not active\n",
+			  __func__, link_conf->link_id);
+		return;
+	}
+
 	rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, ctx);
 	mutex_unlock(&rtwdev->mutex);
 }
@@ -1193,10 +1390,10 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw,
 				       enum ieee80211_roc_type type)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif);
-	struct rtw89_roc *roc = &rtwvif_link->roc;
+	struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
+	struct rtw89_roc *roc = &rtwvif->roc;
 
-	if (!vif)
+	if (!rtwvif)
 		return -EINVAL;
 
 	mutex_lock(&rtwdev->mutex);
@@ -1218,7 +1415,7 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw,
 	roc->chan = *chan;
 	roc->type = type;
 
-	rtw89_roc_start(rtwdev, rtwvif_link);
+	rtw89_roc_start(rtwdev, rtwvif);
 
 	mutex_unlock(&rtwdev->mutex);
 
@@ -1229,15 +1426,15 @@ static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw,
 					      struct ieee80211_vif *vif)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
-	struct rtw89_vif_link *rtwvif_link = vif_to_rtwvif_safe(vif);
+	struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
 
-	if (!rtwvif_link)
+	if (!rtwvif)
 		return -EINVAL;
 
-	cancel_delayed_work_sync(&rtwvif_link->roc.roc_work);
+	cancel_delayed_work_sync(&rtwvif->roc.roc_work);
 
 	mutex_lock(&rtwdev->mutex);
-	rtw89_roc_end(rtwdev, rtwvif_link);
+	rtw89_roc_end(rtwdev, rtwvif);
 	mutex_unlock(&rtwdev->mutex);
 
 	return 0;
@@ -1246,8 +1443,8 @@ static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw,
 static void rtw89_set_tid_config_iter(void *data, struct ieee80211_sta *sta)
 {
 	struct cfg80211_tid_config *tid_config = data;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_dev *rtwdev = rtwsta_link->rtwvif_link->rtwdev;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
 
 	rtw89_core_set_tid_config(rtwdev, sta, tid_config);
 }
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index da9491213b7b5..4b47b45f897cb 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -466,12 +466,12 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
 	ra->csi_mode = csi_mode;
 }
 
-void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
-			     u32 changed)
+static void __rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev,
+				      struct rtw89_vif_link *rtwvif_link,
+				      struct rtw89_sta_link *rtwsta_link,
+				      u32 changed)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_ra_info *ra = &rtwsta_link->ra;
 	struct ieee80211_link_sta *link_sta;
 
@@ -499,6 +499,20 @@ void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta
 	rtw89_fw_h2c_ra(rtwdev, ra, false);
 }
 
+void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
+			     u32 changed)
+{
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
+
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		__rtw89_phy_ra_update_sta(rtwdev, rtwvif_link, rtwsta_link, changed);
+	}
+}
+
 static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next,
 				 u16 rate_base, u64 ra_mask, u8 ra_mode,
 				 u32 rate_ctrl, u32 ctrl_skip, bool force)
@@ -533,12 +547,12 @@ static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next,
 		[RTW89_CHIP_BE] = RTW89_HW_RATE_V1_ ## rate, \
 	}
 
-void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
-				struct ieee80211_vif *vif,
-				const struct cfg80211_bitrate_mask *mask)
+static
+void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
+				  struct rtw89_vif_link *rtwvif_link,
+				  const struct cfg80211_bitrate_mask *mask)
 {
 	struct ieee80211_supported_band *sband;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
 	struct rtw89_phy_rate_pattern next_pattern = {0};
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
 						       rtwvif_link->chanctx_idx);
@@ -623,6 +637,18 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
 	rtw89_debug(rtwdev, RTW89_DBG_RA, "unset rate pattern\n");
 }
 
+void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
+				struct ieee80211_vif *vif,
+				const struct cfg80211_bitrate_mask *mask)
+{
+	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+	struct rtw89_vif_link *rtwvif_link;
+	unsigned int link_id;
+
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+		__rtw89_phy_rate_pattern_vif(rtwdev, rtwvif_link, mask);
+}
+
 static void rtw89_phy_ra_update_sta_iter(void *data, struct ieee80211_sta *sta)
 {
 	struct rtw89_dev *rtwdev = (struct rtw89_dev *)data;
@@ -640,7 +666,7 @@ void rtw89_phy_ra_update(struct rtw89_dev *rtwdev)
 void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link)
 {
 	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_ra_info *ra = &rtwsta_link->ra;
 	u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
 	struct ieee80211_link_sta *link_sta;
@@ -2688,13 +2714,17 @@ static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link,
 static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
 {
 	struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_sta_link *rtwsta_link;
 	struct ieee80211_link_sta *link_sta;
+	unsigned int link_id;
 
 	rcu_read_lock();
 
-	link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
-	__rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data);
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
+		__rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data);
+	}
 
 	rcu_read_unlock();
 }
@@ -4422,7 +4452,7 @@ void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev,
 				struct rtw89_phy_ul_tb_check_data *ul_tb_data)
 {
 	struct rtw89_traffic_stats *stats = &rtwdev->stats;
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 
 	if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION)
 		return;
@@ -4488,6 +4518,8 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev)
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 	struct rtw89_phy_ul_tb_check_data ul_tb_data = {};
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 
 	if (!chip->ul_tb_waveform_ctrl && !chip->ul_tb_pwr_diff)
 		return;
@@ -4495,8 +4527,9 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev)
 	if (rtwdev->total_sta_assoc != 1)
 		return;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif_link, &ul_tb_data);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif_link, &ul_tb_data);
 
 	if (!ul_tb_data.valid)
 		return;
@@ -4660,12 +4693,10 @@ struct rtw89_phy_iter_rssi_data {
 	bool rssi_changed;
 };
 
-static void rtw89_phy_stat_rssi_update_iter(void *data,
-					    struct ieee80211_sta *sta)
+static
+void __rtw89_phy_stat_rssi_update_iter(struct rtw89_sta_link *rtwsta_link,
+				       struct rtw89_phy_iter_rssi_data *rssi_data)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_phy_iter_rssi_data *rssi_data =
-					(struct rtw89_phy_iter_rssi_data *)data;
 	struct rtw89_phy_ch_info *ch_info = rssi_data->ch_info;
 	unsigned long rssi_curr;
 
@@ -4685,6 +4716,19 @@ static void rtw89_phy_stat_rssi_update_iter(void *data,
 	}
 }
 
+static void rtw89_phy_stat_rssi_update_iter(void *data,
+					    struct ieee80211_sta *sta)
+{
+	struct rtw89_phy_iter_rssi_data *rssi_data =
+					(struct rtw89_phy_iter_rssi_data *)data;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
+
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
+		__rtw89_phy_stat_rssi_update_iter(rtwsta_link, rssi_data);
+}
+
 static void rtw89_phy_stat_rssi_update(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_phy_iter_rssi_data rssi_data = {0};
@@ -5788,24 +5832,13 @@ void rtw89_phy_dig(struct rtw89_dev *rtwdev)
 		rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, false);
 }
 
-static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta)
+static void __rtw89_phy_tx_path_div_sta_iter(struct rtw89_dev *rtwdev,
+					     struct rtw89_sta_link *rtwsta_link)
 {
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_dev *rtwdev = rtwsta_link->rtwdev;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
 	struct rtw89_hal *hal = &rtwdev->hal;
-	bool *done = data;
 	u8 rssi_a, rssi_b;
 	u32 candidate;
 
-	if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls)
-		return;
-
-	if (*done)
-		return;
-
-	*done = true;
-
 	rssi_a = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_A]);
 	rssi_b = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_B]);
 
@@ -5831,6 +5864,37 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta
 	}
 }
 
+static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
+	bool *done = data;
+
+	if (WARN(ieee80211_vif_is_mld(vif), "MLD mix path_div\n"))
+		return;
+
+	if (sta->tdls)
+		return;
+
+	if (*done)
+		return;
+
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
+		if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION)
+			continue;
+
+		*done = true;
+		__rtw89_phy_tx_path_div_sta_iter(rtwdev, rtwsta_link);
+		return;
+	}
+}
+
 void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_hal *hal = &rtwdev->hal;
@@ -6040,7 +6104,7 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev)
 void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev,
 			     struct rtw89_vif_link *rtwvif_link)
 {
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 	const struct rtw89_reg_def *bss_clr_vld = &chip->bss_clr_vld;
 	enum rtw89_phy_idx phy_idx = RTW89_PHY_0;
diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index ded0b73bd6783..c1c12abc2ea93 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -147,6 +147,8 @@ static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev,
 void rtw89_leave_lps(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 
 	lockdep_assert_held(&rtwdev->mutex);
 
@@ -155,21 +157,25 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev)
 
 	__rtw89_leave_ps_mode(rtwdev);
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		rtw89_leave_lps_vif(rtwdev, rtwvif_link);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			rtw89_leave_lps_vif(rtwdev, rtwvif_link);
 }
 
 void rtw89_enter_ips(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 
 	set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
 
 	if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
 		return;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		rtw89_mac_vif_deinit(rtwdev, rtwvif_link);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			rtw89_mac_vif_deinit(rtwdev, rtwvif_link);
 
 	rtw89_core_stop(rtwdev);
 }
@@ -177,6 +183,8 @@ void rtw89_enter_ips(struct rtw89_dev *rtwdev)
 void rtw89_leave_ips(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 	int ret;
 
 	if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
@@ -188,8 +196,9 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev)
 
 	rtw89_set_channel(rtwdev);
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		rtw89_mac_vif_init(rtwdev, rtwvif_link);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+			rtw89_mac_vif_init(rtwdev, rtwvif_link);
 
 	clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
 }
@@ -269,16 +278,22 @@ void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev,
 void rtw89_recalc_lps(struct rtw89_dev *rtwdev)
 {
 	struct ieee80211_vif *vif, *found_vif = NULL;
-	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
 	enum rtw89_entity_mode mode;
 	int count = 0;
 
+	/* FIXME: Fix rtw89_enter_lps() and __rtw89_enter_ps_mode()
+	 * to take MLO cases into account before doing the following.
+	 */
+	if (rtwdev->support_mlo)
+		goto disable_lps;
+
 	mode = rtw89_get_entity_mode(rtwdev);
 	if (mode == RTW89_ENTITY_MODE_MCC)
 		goto disable_lps;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link) {
-		vif = rtwvif_to_vif(rtwvif_link);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+		vif = rtwvif_to_vif(rtwvif);
 
 		if (vif->type != NL80211_IFTYPE_STATION) {
 			count = 0;
diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c
index aa5ae02443727..bb064a086970b 100644
--- a/drivers/net/wireless/realtek/rtw89/regd.c
+++ b/drivers/net/wireless/realtek/rtw89/regd.c
@@ -794,21 +794,25 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev)
 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 	struct rtw89_reg_6ghz_tpe new = {};
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 	bool changed = false;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link) {
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
 		const struct rtw89_reg_6ghz_tpe *tmp;
 		const struct rtw89_chan *chan;
 
-		chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
-		if (chan->band_type != RTW89_BAND_6G)
-			continue;
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+			chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+			if (chan->band_type != RTW89_BAND_6G)
+				continue;
 
-		tmp = &rtwvif_link->reg_6ghz_tpe;
-		if (!tmp->valid)
-			continue;
+			tmp = &rtwvif_link->reg_6ghz_tpe;
+			if (!tmp->valid)
+				continue;
 
-		tpe_intersect_constraint(&new, tmp->constraint);
+			tpe_intersect_constraint(&new, tmp->constraint);
+		}
 	}
 
 	if (memcmp(&regulatory->reg_6ghz_tpe, &new,
@@ -873,19 +877,23 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
 	enum rtw89_reg_6ghz_power sel;
 	const struct rtw89_chan *chan;
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
+	unsigned int link_id;
 	int count = 0;
 	u8 index;
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link) {
-		chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
-		if (chan->band_type != RTW89_BAND_6G)
-			continue;
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+			chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+			if (chan->band_type != RTW89_BAND_6G)
+				continue;
 
-		if (count != 0 && rtwvif_link->reg_6ghz_power == sel)
-			continue;
+			if (count != 0 && rtwvif_link->reg_6ghz_power == sel)
+				continue;
 
-		sel = rtwvif_link->reg_6ghz_power;
-		count++;
+			sel = rtwvif_link->reg_6ghz_power;
+			count++;
+		}
 	}
 
 	if (count != 1)
diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
index 50b66eaf9bd04..7b203bb7f151a 100644
--- a/drivers/net/wireless/realtek/rtw89/ser.c
+++ b/drivers/net/wireless/realtek/rtw89/ser.c
@@ -298,54 +298,71 @@ static void drv_resume_rx(struct rtw89_ser *ser)
 	clear_bit(RTW89_SER_DRV_STOP_RX, ser->flags);
 }
 
-static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
+static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
-	rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port);
-	rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK;
-	rtwvif_link->trigger = false;
-	rtwvif_link->tdls_peer = 0;
+	struct rtw89_vif_link *rtwvif_link;
+	unsigned int link_id;
+
+	rtwvif->tdls_peer = 0;
+
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+		rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port);
+		rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK;
+		rtwvif_link->trigger = false;
+	}
 }
 
 static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta)
 {
-	struct rtw89_vif_link *target_rtwvif = (struct rtw89_vif_link *)data;
-	struct rtw89_sta_link *rtwsta_link = (struct rtw89_sta_link *)sta->drv_priv;
-	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
-	struct rtw89_dev *rtwdev = rtwvif_link->rtwdev;
+	struct rtw89_vif *target_rtwvif = (struct rtw89_vif *)data;
+	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+	struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_sta_link *rtwsta_link;
+	unsigned int link_id;
 
-	if (rtwvif_link != target_rtwvif)
+	if (rtwvif != target_rtwvif)
 		return;
 
-	if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls)
-		rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam);
-	if (sta->tdls)
-		rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam);
+	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+		rtwvif_link = rtwsta_link->rtwvif_link;
 
-	INIT_LIST_HEAD(&rtwsta_link->ba_cam_list);
+		if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls)
+			rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam);
+		if (sta->tdls)
+			rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam);
+
+		INIT_LIST_HEAD(&rtwsta_link->ba_cam_list);
+	}
 }
 
-static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
+static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
+	struct rtw89_vif_link *rtwvif_link;
+	unsigned int link_id;
+
 	ieee80211_iterate_stations_atomic(rtwdev->hw,
 					  ser_sta_deinit_cam_iter,
-					  rtwvif_link);
+					  rtwvif);
 
-	rtw89_cam_deinit(rtwdev, rtwvif_link);
+	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+		rtw89_cam_deinit(rtwdev, rtwvif_link);
 
 	bitmap_zero(rtwdev->cam_info.ba_cam_map, RTW89_MAX_BA_CAM_NUM);
 }
 
 static void ser_reset_mac_binding(struct rtw89_dev *rtwdev)
 {
-	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
 
 	rtw89_cam_reset_keys(rtwdev);
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		ser_deinit_cam(rtwdev, rtwvif_link);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		ser_deinit_cam(rtwdev, rtwvif);
 
 	rtw89_core_release_all_bits_map(rtwdev->mac_id_map, RTW89_MAX_MAC_ID_NUM);
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		ser_reset_vif(rtwdev, rtwvif_link);
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		ser_reset_vif(rtwdev, rtwvif);
 
 	rtwdev->total_sta_assoc = 0;
 }
diff --git a/drivers/net/wireless/realtek/rtw89/util.h b/drivers/net/wireless/realtek/rtw89/util.h
index a5e87a8d8642c..e669544cafd3f 100644
--- a/drivers/net/wireless/realtek/rtw89/util.h
+++ b/drivers/net/wireless/realtek/rtw89/util.h
@@ -21,14 +21,14 @@
  * twice cause the list to be added twice.
  */
 static inline bool rtw89_rtwvif_in_list(struct rtw89_dev *rtwdev,
-					struct rtw89_vif_link *new)
+					struct rtw89_vif *new)
 {
-	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
 
 	lockdep_assert_held(&rtwdev->mutex);
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
-		if (rtwvif_link == new)
+	rtw89_for_each_rtwvif(rtwdev, rtwvif)
+		if (rtwvif == new)
 			return true;
 
 	return false;
diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
index 97b527d04ad71..3e81fd974ec18 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.c
+++ b/drivers/net/wireless/realtek/rtw89/wow.c
@@ -421,7 +421,8 @@ static void rtw89_wow_construct_key_info(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
 	struct rtw89_wow_key_info *key_info = &rtw_wow->key_info;
-	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
+	struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
 	bool err = false;
 
 	rcu_read_lock();
@@ -596,7 +597,8 @@ static int rtw89_wow_get_aoac_rpt(struct rtw89_dev *rtwdev, bool rx_ready)
 static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev,
 						      u32 cipher, u8 keyidx, u8 *gtk)
 {
-	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
+	struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
 	const struct rtw89_cipher_info *cipher_info;
 	struct ieee80211_key_conf *rekey_conf;
 	struct ieee80211_key_conf *key;
@@ -632,8 +634,8 @@ static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev,
 
 static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready)
 {
-	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
+	struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
 	struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
 	struct rtw89_set_key_info_iter_data data = {.error = false,
@@ -689,16 +691,14 @@ static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev)
 
 static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev)
 {
-	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
 
 	__rtw89_enter_ps_mode(rtwdev, rtwvif_link);
 }
 
 static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev)
 {
-	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
 
 	if (rtw89_wow_mgd_linked(rtwdev))
 		rtw89_enter_lps(rtwdev, rtwvif_link, false);
@@ -708,8 +708,7 @@ static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev)
 
 static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow)
 {
-	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
 
 	if (rtw89_wow_mgd_linked(rtwdev)) {
 		rtw89_leave_lps(rtwdev);
@@ -742,6 +741,8 @@ static void rtw89_wow_set_rx_filter(struct rtw89_dev *rtwdev, bool enable)
 
 static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
 {
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
+	struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
 	struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
 	struct cfg80211_wowlan_nd_info nd_info;
@@ -788,36 +789,34 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
 		break;
 	default:
 		rtw89_warn(rtwdev, "Unknown wakeup reason %x\n", reason);
-		ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL,
-					       GFP_KERNEL);
+		ieee80211_report_wowlan_wakeup(wow_vif, NULL, GFP_KERNEL);
 		return;
 	}
 
-	ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup,
-				       GFP_KERNEL);
+	ieee80211_report_wowlan_wakeup(wow_vif, &wakeup, GFP_KERNEL);
 }
 
 static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev,
 			       struct rtw89_vif_link *rtwvif_link)
 {
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
-	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link);
+	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 
 	/* Current WoWLAN function support setting of only vif in
 	 * infra mode or no link mode. When one suitable vif is found,
 	 * stop the iteration.
 	 */
-	if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION)
+	if (rtw_wow->rtwvif_link || vif->type != NL80211_IFTYPE_STATION)
 		return;
 
 	switch (rtwvif_link->net_type) {
 	case RTW89_NET_TYPE_INFRA:
 		if (rtw_wow_has_mgd_features(rtwdev))
-			rtw_wow->wow_vif = vif;
+			rtw_wow->rtwvif_link = rtwvif_link;
 		break;
 	case RTW89_NET_TYPE_NO_LINK:
 		if (rtw_wow->pno_inited)
-			rtw_wow->wow_vif = vif;
+			rtw_wow->rtwvif_link = rtwvif_link;
 		break;
 	default:
 		break;
@@ -1049,7 +1048,7 @@ static void rtw89_wow_clear_wakeups(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
 
-	rtw_wow->wow_vif = NULL;
+	rtw_wow->rtwvif_link = NULL;
 	rtw89_core_release_all_bits_map(rtw_wow->flags, RTW89_WOW_FLAG_NUM);
 	rtw_wow->pattern_cnt = 0;
 	rtw_wow->pno_inited = false;
@@ -1076,6 +1075,7 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev,
 {
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
 	struct rtw89_vif_link *rtwvif_link;
+	struct rtw89_vif *rtwvif;
 
 	if (wowlan->disconnect)
 		set_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags);
@@ -1087,21 +1087,25 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev,
 	if (wowlan->nd_config)
 		rtw89_wow_init_pno(rtwdev, wowlan->nd_config);
 
-	rtw89_for_each_rtwvif(rtwdev, rtwvif_link)
+	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+		/* use the link on HW-0 to do wow flow */
+		rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+		if (!rtwvif_link)
+			continue;
+
 		rtw89_wow_vif_iter(rtwdev, rtwvif_link);
+	}
 
-	if (!rtw_wow->wow_vif)
+	rtwvif_link = rtw_wow->rtwvif_link;
+	if (!rtwvif_link)
 		return -EPERM;
 
-	rtwvif_link = (struct rtw89_vif_link *)rtw_wow->wow_vif->drv_priv;
 	return rtw89_wow_parse_patterns(rtwdev, rtwvif_link, wowlan);
 }
 
 static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow)
 {
-	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
-	struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
 	int ret;
 
 	ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, true);
@@ -1128,15 +1132,20 @@ static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow)
 static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow)
 {
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
-	struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link;
+	struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
 	struct ieee80211_sta *wow_sta;
 	struct rtw89_sta_link *rtwsta_link = NULL;
+	struct rtw89_sta *rtwsta;
 	int ret;
 
-	wow_sta = ieee80211_find_sta(wow_vif, rtwvif_link->bssid);
-	if (wow_sta)
-		rtwsta_link = (struct rtw89_sta_link *)wow_sta->drv_priv;
+	wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr);
+	if (wow_sta) {
+		rtwsta = sta_to_rtwsta(wow_sta);
+		rtwsta_link = rtwsta->links[rtwvif_link->link_id];
+		if (!rtwsta_link)
+			return -ENOLINK;
+	}
 
 	if (wow) {
 		if (rtw_wow->pattern_cnt)
@@ -1199,25 +1208,30 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
 	enum rtw89_fw_type fw_type = wow ? RTW89_FW_WOWLAN : RTW89_FW_NORMAL;
 	enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
-	struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link;
+	struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 	bool include_bb = !!chip->bbmcu_nr;
 	bool disable_intr_for_dlfw = false;
 	struct ieee80211_sta *wow_sta;
 	struct rtw89_sta_link *rtwsta_link = NULL;
+	struct rtw89_sta *rtwsta;
 	bool is_conn = true;
 	int ret;
 
 	if (chip_id == RTL8852C || chip_id == RTL8922A)
 		disable_intr_for_dlfw = true;
 
-	wow_sta = ieee80211_find_sta(wow_vif, rtwvif_link->bssid);
-	if (wow_sta)
-		rtwsta_link = (struct rtw89_sta_link *)wow_sta->drv_priv;
-	else
+	wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr);
+	if (wow_sta) {
+		rtwsta = sta_to_rtwsta(wow_sta);
+		rtwsta_link = rtwsta->links[rtwvif_link->link_id];
+		if (!rtwsta_link)
+			return -ENOLINK;
+	} else {
 		is_conn = false;
+	}
 
 	if (disable_intr_for_dlfw)
 		rtw89_hci_disable_intr(rtwdev);
@@ -1372,9 +1386,7 @@ static int rtw89_wow_disable_trx_pre(struct rtw89_dev *rtwdev)
 
 static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev)
 {
-	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
-	struct ieee80211_vif *vif = rtw_wow->wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
 	int ret;
 
 	ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
@@ -1446,8 +1458,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable)
 {
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
-	struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
 	int interval = rtw_wow->nd_config->scan_plans[0].interval;
 	struct rtw89_scan_option opt = {};
 	int ret;
@@ -1489,8 +1500,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable)
 static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
-	struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link;
 	int ret;
 
 	if (rtw89_wow_no_link(rtwdev)) {
@@ -1558,8 +1568,7 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev)
 static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
-	struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link;
 	int ret;
 
 	if (rtw89_wow_no_link(rtwdev)) {
diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h
index a80b4b84587dd..f91991e8f2e30 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.h
+++ b/drivers/net/wireless/realtek/rtw89/wow.h
@@ -97,16 +97,14 @@ static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev)
 #ifdef CONFIG_PM
 static inline bool rtw89_wow_mgd_linked(struct rtw89_dev *rtwdev)
 {
-	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
 
 	return rtwvif_link->net_type == RTW89_NET_TYPE_INFRA;
 }
 
 static inline bool rtw89_wow_no_link(struct rtw89_dev *rtwdev)
 {
-	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
-	struct rtw89_vif_link *rtwvif_link = (struct rtw89_vif_link *)wow_vif->drv_priv;
+	struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
 
 	return rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK;
 }
-- 
2.43.0




  parent reply	other threads:[~2024-12-03 15:49 UTC|newest]

Thread overview: 857+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-03 14:35 [PATCH 6.12 000/826] 6.12.2-rc1 review Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 001/826] MAINTAINERS: appoint myself the XFS maintainer for 6.12 LTS Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 002/826] drm/amd/display: Skip Invalid Streams from DSC Policy Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 003/826] drm/amd/display: Fix incorrect DSC recompute trigger Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 004/826] s390/facilities: Fix warning about shadow of global variable Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 005/826] s390/virtio_ccw: Fix dma_parm pointer not set up Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 006/826] efs: fix the efs new mount api implementation Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 007/826] arm64: probes: Disable kprobes/uprobes on MOPS instructions Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 008/826] kselftest/arm64: hwcap: fix f8dp2 cpuinfo name Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 009/826] kselftest/arm64: mte: fix printf type warnings about __u64 Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 010/826] kselftest/arm64: mte: fix printf type warnings about longs Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 011/826] block/fs: Pass an iocb to generic_atomic_write_valid() Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 012/826] fs/block: Check for IOCB_DIRECT in generic_atomic_write_valid() Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 013/826] s390/cio: Do not unregister the subchannel based on DNV Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 014/826] s390/pageattr: Implement missing kernel_page_present() Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 015/826] x86/pvh: Call C code via the kernel virtual mapping Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 016/826] brd: defer automatic disk creation until module initialization succeeds Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 017/826] ext4: avoid remount errors with abort mount option Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 018/826] mips: asm: fix warning when disabling MIPS_FP_SUPPORT Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 019/826] s390/cpum_sf: Fix and protect memory allocation of SDBs with mutex Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 020/826] initramfs: avoid filename buffer overrun Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 021/826] arm64: Expose ID_AA64ISAR1_EL1.XS to sanitised feature consumers Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 022/826] kselftest/arm64: Fix encoding for SVE B16B16 test Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 023/826] nvme-pci: fix freeing of the HMB descriptor table Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 024/826] m68k: mvme147: Fix SCSI controller IRQ numbers Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 025/826] m68k: mvme147: Reinstate early console Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 026/826] arm64: fix .data.rel.ro size assertion when CONFIG_LTO_CLANG Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 027/826] acpi/arm64: Adjust error handling procedure in gtdt_parse_timer_block() Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 028/826] loop: fix type of block size Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 029/826] cachefiles: Fix incorrect length return value in cachefiles_ondemand_fd_write_iter() Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 030/826] cachefiles: Fix missing pos updates " Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 031/826] cachefiles: Fix NULL pointer dereference in object->file Greg Kroah-Hartman
2024-12-03 14:35 ` [PATCH 6.12 032/826] netfs/fscache: Add a memory barrier for FSCACHE_VOLUME_CREATING Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 033/826] block: take chunk_sectors into account in bio_split_write_zeroes Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 034/826] block: fix bio_split_rw_at to take zone_write_granularity into account Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 035/826] s390/syscalls: Avoid creation of arch/arch/ directory Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 036/826] hfsplus: dont query the device logical block size multiple times Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 037/826] ext4: fix race in buffer_head read fault injection Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 038/826] nvme-pci: reverse request order in nvme_queue_rqs Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 039/826] virtio_blk: reverse request order in virtio_queue_rqs Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 040/826] crypto: mxs-dcp - Fix AES-CBC with hardware-bound keys Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 041/826] crypto: caam - Fix the pointer passed to caam_qi_shutdown() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 042/826] crypto: qat - remove check after debugfs_create_dir() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 043/826] crypto: powerpc/p10-aes-gcm - Register modules as SIMD Greg Kroah-Hartman
2024-12-04 10:00   ` Jiri Slaby
2024-12-04 10:34     ` Greg Kroah-Hartman
2024-12-04 10:45       ` Jiri Slaby
2024-12-04 12:24         ` Greg Kroah-Hartman
2024-12-04 16:22           ` Jiri Slaby
2024-12-05  4:29             ` Herbert Xu
2024-12-05  8:05               ` Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 044/826] crypto: powerpc/p10-aes-gcm - Add dependency on CRYPTO_SIMDand re-enable CRYPTO_AES_GCM_P10 Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 045/826] crypto: qat/qat_420xx - fix off by one in uof_get_name() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 046/826] crypto: qat/qat_4xxx " Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 047/826] firmware: google: Unregister driver_info on failure Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 048/826] EDAC/bluefield: Fix potential integer overflow Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 049/826] crypto: qat - remove faulty arbiter config reset Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 050/826] thermal: core: Initialize thermal zones before registering them Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 051/826] thermal: core: Rearrange PM notification code Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 052/826] thermal: core: Represent suspend-related thermal zone flags as bits Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 053/826] thermal: core: Mark thermal zones as initializing to start with Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 054/826] thermal: core: Fix race between zone registration and system suspend Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 055/826] EDAC/fsl_ddr: Fix bad bit shift operations Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 056/826] EDAC/skx_common: Differentiate memory error sources Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 057/826] EDAC/{skx_common,i10nm}: Fix incorrect far-memory error source indicator Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 058/826] crypto: pcrypt - Call crypto layer directly when padata_do_parallel() return -EBUSY Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 059/826] crypto: cavium - Fix the if condition to exit loop after timeout Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 060/826] cpufreq/amd-pstate: Dont update CPPC request in amd_pstate_cpu_boost_update() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 061/826] amd-pstate: Set min_perf to nominal_perf for active mode performance gov Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 062/826] crypto: hisilicon/qm - disable same error report before resetting Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 063/826] EDAC/igen6: Avoid segmentation fault on module unload Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 064/826] crypto: qat - Fix missing destroy_workqueue in adf_init_aer() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 065/826] crypto: inside-secure - Fix the return value of safexcel_xcbcmac_cra_init() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 066/826] sched/cpufreq: Ensure sd is rebuilt for EAS check Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 067/826] doc: rcu: update printed dynticks counter bits Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 068/826] rcu/srcutiny: dont return before reenabling preemption Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 069/826] rcu/kvfree: Fix data-race in __mod_timer / kvfree_call_rcu Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 070/826] rcu/nocb: Fix missed RCU barrier on deoffloading Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 071/826] hwmon: (pmbus/core) clear faults after setting smbalert mask Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 072/826] hwmon: (nct6775-core) Fix overflows seen when writing limit attributes Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 073/826] ACPI: CPPC: Fix _CPC register setting issue Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 074/826] thermal: testing: Use DEFINE_FREE() and __free() to simplify code Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 075/826] thermal: testing: Initialize some variables annoteded with _free() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 076/826] crypto: caam - add error check to caam_rsa_set_priv_key_form Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 077/826] crypto: bcm - add error check in the ahash_hmac_init function Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 078/826] crypto: aes-gcm-p10 - Use the correct bit to test for P10 Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 079/826] crypto: cavium - Fix an error handling path in cpt_ucode_load_fw() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 080/826] rcuscale: Do a proper cleanup if kfree_scale_init() fails Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 081/826] tools/lib/thermal: Make more generic the command encoding function Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 082/826] thermal/lib: Fix memory leak on error in thermal_genl_auto() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 083/826] x86/unwind/orc: Fix unwind for newly forked tasks Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 084/826] Revert "scripts/faddr2line: Check only two symbols when calculating symbol size" Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 085/826] cleanup: Remove address space of returned pointer Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 086/826] time: Partially revert cleanup on msecs_to_jiffies() documentation Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 087/826] time: Fix references to _msecs_to_jiffies() handling of values Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 088/826] timers: Add missing READ_ONCE() in __run_timer_base() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 089/826] locking/atomic/x86: Use ALT_OUTPUT_SP() for __alternative_atomic64() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 090/826] locking/atomic/x86: Use ALT_OUTPUT_SP() for __arch_{,try_}cmpxchg64_emu() Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 091/826] kcsan, seqlock: Support seqcount_latch_t Greg Kroah-Hartman
2024-12-03 14:36 ` [PATCH 6.12 092/826] kcsan, seqlock: Fix incorrect assumption in read_seqbegin() Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 093/826] sched/ext: Remove sched_fork() hack Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 094/826] locking/rt: Add sparse annotation PREEMPT_RTs sleeping locks Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 095/826] rust: helpers: Avoid raw_spin_lock initialization for PREEMPT_RT Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 096/826] clocksource/drivers:sp804: Make user selectable Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 097/826] clocksource/drivers/timer-ti-dm: Fix child node refcount handling Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 098/826] irqchip/riscv-aplic: Prevent crash when MSI domain is missing Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 099/826] regulator: qcom-smd: make smd_vreg_rpm static Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 100/826] spi: spi-fsl-lpspi: Use IRQF_NO_AUTOEN flag in request_irq() Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 101/826] arm64: dts: qcom: qcs6390-rb3gen2: use modem.mbn for modem DSP Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 102/826] ARM: dts: renesas: genmai: Fix partition size for QSPI NOR Flash Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 103/826] drivers: soc: xilinx: add the missing kfree in xlnx_add_cb_for_suspend() Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 104/826] microblaze: Export xmb_manager functions Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 105/826] arm64: dts: mediatek: mt8188: Fix wrong clock provider in MFG1 power domain Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 106/826] arm64: dts: mediatek: mt8395-genio-1200-evk: Fix dtbs_check error for phy Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 107/826] arm64: dts: mt8195: Fix dtbs_check error for mutex node Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 108/826] arm64: dts: mt8195: Fix dtbs_check error for infracfg_ao node Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 109/826] arm64: dts: mediatek: mt8183-kukui: Disable DPI display interface Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 110/826] arm64: dts: mt8183: Add port node to dpi node Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 111/826] soc: ti: smartreflex: Use IRQF_NO_AUTOEN flag in request_irq() Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 112/826] soc: qcom: geni-se: fix array underflow in geni_se_clk_tbl_get() Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 113/826] arm64: dts: qcom: sm6350: Fix GPU frequencies missing on some speedbins Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 114/826] arm64: dts: qcom: sda660-ifc6560: fix l10a voltage ranges Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 115/826] ARM: dts: microchip: sam9x60: Add missing property atmel,usart-mode Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 116/826] mmc: mmc_spi: drop buggy snprintf() Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 117/826] scripts/kernel-doc: Do not track section counter across processed files Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 118/826] arm64: dts: qcom: x1e80100-slim7x: Drop orientation-switch from USB SS[0-1] QMP PHYs Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 119/826] arm64: dts: qcom: x1e80100-vivobook-s15: " Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 120/826] openrisc: Implement fixmap to fix earlycon Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 121/826] efi/libstub: fix efi_parse_options() ignoring the default command line Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 122/826] tpm: fix signed/unsigned bug when checking event logs Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 123/826] media: i2c: max96717: clean up on error in max96717_subdev_init() Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 124/826] media: i2c: vgxy61: Fix an error handling path in vgxy61_detect() Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 125/826] media: i2c: ds90ub960: Fix missing return check on ub960_rxport_read call Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 126/826] arm64: dts: mt8183: krane: Fix the address of eeprom at i2c4 Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 127/826] arm64: dts: mt8183: kukui: " Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 128/826] arm64: dts: qcom: x1e80100: Resize GIC Redistributor register region Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 129/826] kernel-doc: allow object-like macros in ReST output Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 130/826] arm64: dts: ti: k3-am62x-phyboard-lyra: Drop unnecessary McASP AFIFOs Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 131/826] gpio: sloppy-logic-analyzer remove reference to rcu_momentary_dyntick_idle() Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 132/826] arm64: dts: mediatek: mt8173-elm-hana: Add vdd-supply to second source trackpad Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 133/826] arm64: dts: mediatek: mt8188: Fix USB3 PHY port default status Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 134/826] arm64: dts: mediatek: mt8195-cherry: Use correct audio codec DAI Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 135/826] Revert "cgroup: Fix memory leak caused by missing cgroup_bpf_offline" Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 136/826] cgroup/bpf: only cgroup v2 can be attached by bpf programs Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 137/826] regulator: rk808: Restrict DVS GPIOs to the RK808 variant only Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 138/826] power: sequencing: make the QCom PMU pwrseq driver depend on CONFIG_OF Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 139/826] arm64: tegra: p2180: Add mandatory compatible for WiFi node Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 140/826] arm64: dts: rockchip: Remove enable-active-low from two boards Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 141/826] arm64: dts: mt8183: fennel: add i2c2s i2c-scl-internal-delay-ns Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 142/826] arm64: dts: mt8183: burnet: " Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 143/826] arm64: dts: mt8183: cozmo: " Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 144/826] arm64: dts: mt8183: Damu: " Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 145/826] pwm: imx27: Workaround of the pwm output bug when decrease the duty cycle Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 146/826] ARM: dts: cubieboard4: Fix DCDC5 regulator constraints Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 147/826] arm64: dts: ti: k3-j7200: Fix register map for main domain pmx Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 148/826] arm64: dts: ti: k3-j7200: Fix clock ids for MCSPI instances Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 149/826] arm64: dts: ti: k3-j721e: Fix clock IDs " Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 150/826] arm64: dts: ti: k3-j721s2: " Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 151/826] watchdog: Add HAS_IOPORT dependency for SBC8360 and SBC7240 Greg Kroah-Hartman
2024-12-03 14:37 ` [PATCH 6.12 152/826] arm64: dts: qcom: x1e80100: Update C4/C5 residency/exit numbers Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 153/826] dt-bindings: cache: qcom,llcc: Fix X1E80100 reg entries Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 154/826] of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 155/826] pmdomain: ti-sci: Add missing of_node_put() for args.np Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 156/826] spi: tegra210-quad: Avoid shift-out-of-bounds Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 157/826] spi: zynqmp-gqspi: Undo runtime PM changes at driver exit time​ Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 158/826] regmap: irq: Set lockdep class for hierarchical IRQ domains Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 159/826] arm64: dts: renesas: hihope: Drop #sound-dai-cells Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 160/826] arm64: dts: imx8mn-tqma8mqnl-mba8mx-usbot: fix coexistence of output-low and output-high in GPIO Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 161/826] arm64: dts: mediatek: mt6358: fix dtbs_check error Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 162/826] arm64: dts: mediatek: mt8183-kukui-jacuzzi: Fix DP bridge supply names Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 163/826] arm64: dts: mediatek: mt8183-kukui-jacuzzi: Add supplies for fixed regulators Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 164/826] selftests/resctrl: Print accurate buffer size as part of MBM results Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 165/826] selftests/resctrl: Fix memory overflow due to unhandled wraparound Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 166/826] selftests/resctrl: Protect against array overrun during iMC config parsing Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 167/826] firmware: arm_scpi: Check the DVFS OPP count returned by the firmware Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 168/826] media: ipu6: Fix DMA and physical address debugging messages for 32-bit Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 169/826] media: ipu6: not override the dma_ops of device in driver Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 170/826] media: ipu6: remove architecture DMA ops dependency in Kconfig Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 171/826] media: venus: fix enc/dec destruction order Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 172/826] media: venus: sync with threaded IRQ during inst destruction Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 173/826] pwm: Assume a disabled PWM to emit a constant inactive output Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 174/826] media: atomisp: Add check for rgby_data memory allocation failure Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 175/826] arm64: dts: rockchip: correct analog audio name on Indiedroid Nova Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 176/826] sched_ext: scx_bpf_dispatch_from_dsq_set_*() are allowed from unlocked context Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 177/826] HID: hyperv: streamline driver probe to avoid devres issues Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 178/826] platform/x86: asus-wmi: Fix inconsistent use of thermal policies Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 179/826] platform/x86/intel/pmt: allow user offset for PMT callbacks Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 180/826] platform/x86: panasonic-laptop: Return errno correctly in show callback Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 181/826] drm/imagination: Convert to use time_before macro Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 182/826] drm/imagination: Use pvr_vm_context_get() Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 183/826] drm/mm: Mark drm_mm_interval_tree*() functions with __maybe_unused Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 184/826] drm/vc4: hvs: Dont write gamma luts on 2711 Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 185/826] drm/vc4: hdmi: Avoid hang with debug registers when suspended Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 186/826] drm/vc4: hvs: Fix dlist debug not resetting the next entry pointer Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 187/826] drm/vc4: hvs: Remove incorrect limit from hvs_dlist debugfs function Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 188/826] drm/vc4: hvs: Correct logic on stopping an HVS channel Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 189/826] wifi: ath9k: add range check for conn_rsp_epid in htc_connect_service() Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 190/826] drm/omap: Fix possible NULL dereference Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 191/826] drm/omap: Fix locking in omap_gem_new_dmabuf() Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 192/826] drm/v3d: Appease lockdep while updating GPU stats Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 193/826] wifi: p54: Use IRQF_NO_AUTOEN flag in request_irq() Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 194/826] wifi: mwifiex: " Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 195/826] udmabuf: change folios array from kmalloc to kvmalloc Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 196/826] udmabuf: fix vmap_udmabuf error page set Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 197/826] drm/imx/dcss: Use IRQF_NO_AUTOEN flag in request_irq() Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 198/826] drm/imx/ipuv3: " Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 199/826] drm/imx: parallel-display: drop edid override support Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 200/826] drm/imx: ldb: drop custom EDID support Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 201/826] drm/imx: ldb: drop custom DDC bus support Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 202/826] drm/imx: ldb: switch to drm_panel_bridge Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 203/826] drm/imx: parallel-display: " Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 204/826] drm/imx: Add missing DRM_BRIDGE_CONNECTOR dependency Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 205/826] drm/panel: nt35510: Make new commands optional Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 206/826] drm/v3d: Address race-condition in MMU flush Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 207/826] drm/v3d: Flush the MMU before we supply more memory to the binner Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 208/826] drm/amdgpu: Fix JPEG v4.0.3 register write Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 209/826] wifi: ath10k: fix invalid VHT parameters in supported_vht_mcs_rate_nss1 Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 210/826] wifi: ath10k: fix invalid VHT parameters in supported_vht_mcs_rate_nss2 Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 211/826] wifi: ath12k: Skip Rx TID cleanup for self peer Greg Kroah-Hartman
2024-12-03 14:38 ` [PATCH 6.12 212/826] dt-bindings: vendor-prefixes: Add NeoFidelity, Inc Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 213/826] ASoC: fsl_micfil: fix regmap_write_bits usage Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 214/826] ASoC: dt-bindings: mt6359: Update generic node name and dmic-mode Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 215/826] drm/amdgpu/gfx9: Add Cleaner Shader Deinitialization in gfx_v9_0 Module Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 216/826] ASoC: fsl-asoc-card: Add missing handling of {hp,mic}-dt-gpios Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 217/826] drm/bridge: anx7625: Drop EDID cache on bridge power off Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 218/826] drm/bridge: it6505: " Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 219/826] libbpf: Fix expected_attach_type set handling in program load callback Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 220/826] libbpf: Fix output .symtab byte-order during linking Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 221/826] selftests/bpf: Fix uprobe_multi compilation error Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 222/826] dlm: fix swapped args sb_flags vs sb_status Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 223/826] wifi: rtl8xxxu: Perform update_beacon_work when beaconing is enabled Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 224/826] ASoC: amd: acp: fix for inconsistent indenting Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 225/826] ASoC: amd: acp: fix for cpu dai index logic Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 226/826] drm/amd/display: fix a memleak issue when driver is removed Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 227/826] wifi: ath12k: fix use-after-free in ath12k_dp_cc_cleanup() Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 228/826] wifi: ath12k: fix one more memcpy size error Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 229/826] libbpf: Add missing per-arch include path Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 230/826] selftests: bpf: " Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 231/826] bpf: Fix the xdp_adjust_tail sample prog issue Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 232/826] selftests/bpf: Fix backtrace printing for selftests crashes Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 233/826] wifi: ath11k: Fix CE offset address calculation for WCN6750 in SSR Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 234/826] selftests/bpf: add missing header include for htons Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 235/826] wifi: cfg80211: check radio iface combination for multi radio per wiphy Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 236/826] ice: consistently use q_idx in ice_vc_cfg_qs_msg() Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 237/826] drm/vc4: hdmi: Increase audio MAI fifo dreq threshold Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 238/826] drm/vc4: Introduce generation number enum Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 239/826] drm/vc4: Match drm_dev_enter and exit calls in vc4_hvs_lut_load Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 240/826] drm/vc4: Match drm_dev_enter and exit calls in vc4_hvs_atomic_flush Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 241/826] drm/vc4: Correct generation check in vc4_hvs_lut_load Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 242/826] libbpf: fix sym_is_subprog() logic for weak global subprogs Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 243/826] accel/ivpu: Prevent recovery invocation during probe and resume Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 244/826] ASoC: rt722-sdca: Remove logically deadcode in rt722-sdca.c Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 245/826] libbpf: never interpret subprogs in .text as entry programs Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 246/826] netdevsim: copy addresses for both in and out paths Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 247/826] drm/bridge: tc358767: Fix link properties discovery Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 248/826] drm/panic: Select ZLIB_DEFLATE for DRM_PANIC_SCREEN_QR_CODE Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 249/826] selftests/bpf: Fix msg_verify_data in test_sockmap Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 250/826] selftests/bpf: Fix txmsg_redir of test_txmsg_pull " Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 251/826] wifi: mwifiex: add missing locking for cfg80211 calls Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 252/826] wifi: wilc1000: Set MAC after operation mode Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 253/826] wifi: mwifiex: Fix memcpy() field-spanning write warning in mwifiex_config_scan() Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 254/826] drm: fsl-dcu: enable PIXCLK on LS1021A Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 255/826] drm: panel: nv3052c: correct spi_device_id for RG35XX panel Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 256/826] drm/msm/dpu: on SDM845 move DSPP_3 to LM_5 block Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 257/826] drm/msm/dpu: drop LM_3 / LM_4 on SDM845 Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 258/826] drm/msm/dpu: drop LM_3 / LM_4 on MSM8998 Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 259/826] octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_common.c Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 260/826] octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_ethtool.c Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 261/826] octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_flows.c Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 262/826] octeontx2-pf: handle otx2_mbox_get_rsp errors in cn10k.c Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 263/826] octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_dmac_flt.c Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 264/826] octeontx2-pf: handle otx2_mbox_get_rsp errors in otx2_dcbnl.c Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 265/826] selftests/bpf: fix test_spin_lock_fail.cs global vars usage Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 266/826] libbpf: move global data mmap()ing into bpf_object__load() Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 267/826] wifi: rtw89: rename rtw89_vif to rtw89_vif_link ahead for MLO Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 268/826] wifi: rtw89: rename rtw89_sta to rtw89_sta_link " Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 269/826] wifi: rtw89: read bss_conf corresponding to the link Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 270/826] wifi: rtw89: read link_sta " Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 271/826] wifi: rtw89: refactor VIF related func ahead for MLO Greg Kroah-Hartman
2024-12-03 14:39 ` [PATCH 6.12 272/826] wifi: rtw89: refactor STA " Greg Kroah-Hartman
2024-12-03 14:40 ` Greg Kroah-Hartman [this message]
2024-12-03 14:40 ` [PATCH 6.12 274/826] wifi: rtw89: Fix TX fail with A2DP after scanning Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 275/826] wifi: rtw89: unlock on error path in rtw89_ops_unassign_vif_chanctx() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 276/826] drm/panfrost: Remove unused id_mask from struct panfrost_model Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 277/826] bpf, arm64: Remove garbage frame for struct_ops trampoline Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 278/826] drm/msm/adreno: Use IRQF_NO_AUTOEN flag in request_irq() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 279/826] drm/msm/gpu: Check the status of registration to PM QoS Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 280/826] drm/xe/hdcp: Fix gsc structure check in fw check status Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 281/826] drm/etnaviv: Request pages from DMA32 zone on addressing_limited Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 282/826] drm/etnaviv: hold GPU lock across perfmon sampling Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 283/826] drm/amd/display: Increase idle worker HPD detection time Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 284/826] drm/amd/display: Reduce HPD Detection Interval for IPS Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 285/826] drm/nouveau/gr/gf100: Fix missing unlock in gf100_gr_chan_new() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 286/826] drm: zynqmp_kms: Unplug DRM device before removal Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 287/826] drm: xlnx: zynqmp_disp: layer may be null while releasing Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 288/826] wifi: wfx: Fix error handling in wfx_core_init() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 289/826] wifi: cw1200: Fix potential NULL dereference Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 290/826] drm/msm/dpu: cast crtc_clk calculation to u64 in _dpu_core_perf_calc_clk() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 291/826] bpf, bpftool: Fix incorrect disasm pc Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 292/826] bpf: Tighten tail call checks for lingering locks, RCU, preempt_disable Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 293/826] drm/vkms: Drop unnecessary call to drm_crtc_cleanup() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 294/826] drm/amdgpu: Fix the memory allocation issue in amdgpu_discovery_get_nps_info() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 295/826] drm/amdkfd: Use dynamic allocation for CU occupancy array in kfd_get_cu_occupancy() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 296/826] bpf: Mark raw_tp arguments with PTR_MAYBE_NULL Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 297/826] drm: use ATOMIC64_INIT() for atomic64_t Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 298/826] netfilter: nf_tables: avoid false-positive lockdep splat on rule deletion Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 299/826] netfilter: nf_tables: must hold rcu read lock while iterating expression type list Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 300/826] netfilter: nf_tables: must hold rcu read lock while iterating object " Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 301/826] netlink: typographical error in nlmsg_type constants definition Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 302/826] wifi: rtw89: coex: check NULL return of kmalloc in btc_fw_set_monreg() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 303/826] drm/panfrost: Add missing OPP table refcnt decremental Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 304/826] drm/panthor: introduce job cycle and timestamp accounting Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 305/826] drm/panthor: record current and maximum device clock frequencies Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 306/826] drm/panthor: Fix OPP refcnt leaks in devfreq initialisation Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 307/826] isofs: avoid memory leak in iocharset Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 308/826] selftests/bpf: Add txmsg_pass to pull/push/pop in test_sockmap Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 309/826] selftests/bpf: Fix SENDPAGE data logic " Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 310/826] selftests/bpf: Fix total_bytes in msg_loop_rx " Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 311/826] selftests/bpf: Add push/pop checking for msg_verify_data " Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 312/826] bpf, sockmap: Several fixes to bpf_msg_push_data Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 313/826] bpf, sockmap: Several fixes to bpf_msg_pop_data Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 314/826] bpf, sockmap: Fix sk_msg_reset_curr Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 315/826] ipv6: release nexthop on device removal Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 316/826] selftests: net: really check for bg process completion Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 317/826] wifi: cfg80211: Remove the Medium Synchronization Delay validity check Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 318/826] wifi: iwlwifi: allow fast resume on ax200 Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 319/826] wifi: iwlwifi: mvm: tell iwlmei when we finished suspending Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 320/826] drm/amdgpu: fix ACA bank count boundary check error Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 321/826] drm/amdgpu: Fix map/unmap queue logic Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 322/826] drm/amdkfd: Fix wrong usage of INIT_WORK() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 323/826] bpf: Allow return values 0 and 1 for kprobe session Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 324/826] bpf: Force uprobe bpf program to always return 0 Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 325/826] selftests/bpf: skip the timer_lockup test for single-CPU nodes Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 326/826] ipv6: Fix soft lockups in fib6_select_path under high next hop churn Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 327/826] net: rfkill: gpio: Add check for clk_enable() Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 328/826] Revert "wifi: iwlegacy: do not skip frames with bad FCS" Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 329/826] bpf: Use function pointers count as struct_ops links count Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 330/826] bpf: Add kernel symbol for struct_ops trampoline Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 331/826] ALSA: usx2y: Use snd_card_free_when_closed() at disconnection Greg Kroah-Hartman
2024-12-03 14:40 ` [PATCH 6.12 332/826] ALSA: us122l: " Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 333/826] ALSA: caiaq: " Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 334/826] ALSA: 6fire: Release resources at card release Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 335/826] i2c: dev: Fix memory leak when underlying adapter does not support I2C Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 336/826] selftests: netfilter: Fix missing return values in conntrack_dump_flush Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 337/826] Bluetooth: btintel_pcie: Add handshake between driver and firmware Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 338/826] Bluetooth: btintel: Do no pass vendor events to stack Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 339/826] Bluetooth: btmtk: adjust the position to init iso data anchor Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 340/826] Bluetooth: btbcm: fix missing of_node_put() in btbcm_get_board_name() Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 341/826] Bluetooth: ISO: Use kref to track lifetime of iso_conn Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 342/826] Bluetooth: ISO: Do not emit LE PA Create Sync if previous is pending Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 343/826] Bluetooth: ISO: Do not emit LE BIG " Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 344/826] Bluetooth: ISO: Send BIG Create Sync via hci_sync Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 345/826] Bluetooth: fix use-after-free in device_for_each_child() Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 346/826] xsk: Free skb when TX metadata options are invalid Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 347/826] erofs: fix file-backed mounts over FUSE Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 348/826] erofs: fix blksize < PAGE_SIZE for file-backed mounts Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 349/826] erofs: handle NONHEAD !delta[1] lclusters gracefully Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 350/826] dlm: fix dlm_recover_members refcount on error Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 351/826] eth: fbnic: dont disable the PCI device twice Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 352/826] net: txgbe: remove GPIO interrupt controller Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 353/826] net: txgbe: fix null pointer to pcs Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 354/826] netpoll: Use rcu_access_pointer() in netpoll_poll_lock Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 355/826] wireguard: selftests: load nf_conntrack if not present Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 356/826] bpf: fix recursive lock when verdict program return SK_PASS Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 357/826] unicode: Fix utf8_load() error path Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 358/826] cppc_cpufreq: Use desired perf if feedback ctrs are 0 or unchanged Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 359/826] RDMA/core: Provide rdma_user_mmap_disassociate() to disassociate mmap pages Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 360/826] RDMA/hns: Disassociate mmap pages for all uctx when HW is being reset Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 361/826] pinctrl: renesas: rzg2l: Fix missing return in rzg2l_pinctrl_register() Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 362/826] clk: mediatek: drop two dead config options Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 363/826] trace/trace_event_perf: remove duplicate samples on the first tracepoint event Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 364/826] pinctrl: zynqmp: drop excess struct member description Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 365/826] pinctrl: renesas: Select PINCTRL_RZG2L for RZ/V2H(P) SoC Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 366/826] clk: qcom: videocc-sm8550: depend on either gcc-sm8550 or gcc-sm8650 Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 367/826] iommu/s390: Implement blocking domain Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 368/826] scsi: hisi_sas: Enable all PHYs that are not disabled by user during controller reset Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 369/826] powerpc/vdso: Flag VDSO64 entry points as functions Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 370/826] mfd: tps65010: Use IRQF_NO_AUTOEN flag in request_irq() to fix race Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 371/826] mfd: da9052-spi: Change read-mask to write-mask Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 372/826] mfd: intel_soc_pmic_bxtwc: Use IRQ domain for USB Type-C device Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 373/826] mfd: intel_soc_pmic_bxtwc: Use IRQ domain for TMU device Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 374/826] mfd: intel_soc_pmic_bxtwc: Use IRQ domain for PMIC devices Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 375/826] mfd: intel_soc_pmic_bxtwc: Fix IRQ domain names duplication Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 376/826] cpufreq: loongson2: Unregister platform_driver on failure Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 377/826] powerpc/fadump: Refactor and prepare fadump_cma_init for late init Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 378/826] powerpc/fadump: Move fadump_cma_init to setup_arch() after initmem_init() Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 379/826] mtd: hyperbus: rpc-if: Add missing MODULE_DEVICE_TABLE Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 380/826] mtd: rawnand: atmel: Fix possible memory leak Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 381/826] clk: Allow kunit tests to run without OF_OVERLAY enabled Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 382/826] powerpc/mm/fault: Fix kfence page fault reporting Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 383/826] iommu/tegra241-cmdqv: Staticize cmdqv_debugfs_dir Greg Kroah-Hartman
2024-12-06  8:54   ` Jiri Slaby
2024-12-06  9:19     ` Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 384/826] clk: sophgo: avoid integer overflow in sg2042_pll_recalc_rate() Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 385/826] mtd: spi-nor: spansion: Use nor->addr_nbytes in octal DTR mode in RD_ANY_REG_OP Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 386/826] powerpc/pseries: Fix dtl_access_lock to be a rw_semaphore Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 387/826] cpufreq: CPPC: Fix possible null-ptr-deref for cpufreq_cpu_get_raw() Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 388/826] cpufreq: CPPC: Fix possible null-ptr-deref for cppc_get_cpu_cost() Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 389/826] iommu/amd/pgtbl_v2: Take protection domain lock before invalidating TLB Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 390/826] RDMA/hns: Fix an AEQE overflow error caused by untimely update of eq_db_ci Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 391/826] RDMA/hns: Fix flush cqe error when racing with destroy qp Greg Kroah-Hartman
2024-12-03 14:41 ` [PATCH 6.12 392/826] RDMA/hns: Modify debugfs name Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 393/826] RDMA/hns: Use dev_* printings in hem code instead of ibdev_* Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 394/826] RDMA/hns: Fix cpu stuck caused by printings during reset Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 395/826] RDMA/rxe: Fix the qp flush warnings in req Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 396/826] RDMA/bnxt_re: Check cqe flags to know imm_data vs inv_irkey Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 397/826] clk: sunxi-ng: d1: Fix PLL_AUDIO0 preset Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 398/826] clk: renesas: rzg2l: Fix FOUTPOSTDIV clk Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 399/826] RDMA/rxe: Set queue pair cur_qp_state when being queried Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 400/826] RDMA/mlx5: Call dev_put() after the blocking notifier Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 401/826] RDMA/core: Implement RoCE GID port rescan and export delete function Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 402/826] RDMA/mlx5: Ensure active slave attachment to the bond IB device Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 403/826] RISC-V: KVM: Fix APLIC in_clrip and clripnum write emulation Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 404/826] riscv: kvm: Fix out-of-bounds array access Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 405/826] clk: imx: lpcg-scu: SW workaround for errata (e10858) Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 406/826] clk: imx: fracn-gppll: correct PLL initialization flow Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 407/826] clk: imx: fracn-gppll: fix pll power up Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 408/826] clk: imx: clk-scu: fix clk enable state save and restore Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 409/826] clk: imx: imx8-acm: Fix return value check in clk_imx_acm_attach_pm_domains() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 410/826] iommu/vt-d: Fix checks and print in dmar_fault_dump_ptes() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 411/826] iommu/vt-d: Fix checks and print in pgtable_walk() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 412/826] checkpatch: always parse orig_commit in fixes tag Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 413/826] mfd: rt5033: Fix missing regmap_del_irq_chip() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 414/826] leds: max5970: Fix unreleased fwnode_handle in probe function Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 415/826] leds: ktd2692: Set missing timing properties Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 416/826] fs/proc/kcore.c: fix coccinelle reported ERROR instances Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 417/826] scsi: target: Fix incorrect function name in pscsi_create_type_disk() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 418/826] scsi: bfa: Fix use-after-free in bfad_im_module_exit() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 419/826] scsi: fusion: Remove unused variable rc Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 420/826] scsi: qedf: Fix a possible memory leak in qedf_alloc_and_init_sb() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 421/826] scsi: qedi: Fix a possible memory leak in qedi_alloc_and_init_sb() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 422/826] scsi: sg: Enable runtime power management Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 423/826] x86/tdx: Introduce wrappers to read and write TD metadata Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 424/826] x86/tdx: Rename tdx_parse_tdinfo() to tdx_setup() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 425/826] x86/tdx: Dynamically disable SEPT violations from causing #VEs Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 426/826] powerpc/fadump: allocate memory for additional parameters early Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 427/826] fadump: reserve param area if below boot_mem_top Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 428/826] RDMA/hns: Fix out-of-order issue of requester when setting FENCE Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 429/826] RDMA/hns: Fix NULL pointer derefernce in hns_roce_map_mr_sg() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 430/826] cpufreq: loongson3: Check for error code from devm_mutex_init() call Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 431/826] cpufreq: CPPC: Fix wrong return value in cppc_get_cpu_cost() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 432/826] cpufreq: CPPC: Fix wrong return value in cppc_get_cpu_power() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 433/826] kasan: move checks to do_strncpy_from_user Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 434/826] kunit: skb: use "gfp" variable instead of hardcoding GFP_KERNEL Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 435/826] ocfs2: fix uninitialized value in ocfs2_file_read_iter() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 436/826] zram: ZRAM_DEF_COMP should depend on ZRAM Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 437/826] iommu/tegra241-cmdqv: Fix alignment failure at max_n_shift Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 438/826] dax: delete a stale directory pmem Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 439/826] KVM: PPC: Book3S HV: Stop using vc->dpdes for nested KVM guests Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 440/826] KVM: PPC: Book3S HV: Avoid returning to nested hypervisor on pending doorbells Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 441/826] powerpc/sstep: make emulate_vsx_load and emulate_vsx_store static Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 442/826] RDMA/hns: Fix different dgids mapping to the same dip_idx Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 443/826] KVM: PPC: Book3S HV: Fix kmv -> kvm typo Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 444/826] powerpc/kexec: Fix return of uninitialized variable Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 445/826] fbdev: sh7760fb: Fix a possible memory leak in sh7760fb_alloc_mem() Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 446/826] RDMA/mlx5: Move events notifier registration to be after device registration Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 447/826] clk: clk-apple-nco: Add NULL check in applnco_probe Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 448/826] clk: ralink: mtmips: fix clock plan for Ralink SoC RT3883 Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 449/826] clk: ralink: mtmips: fix clocks probe order in oldest ralink SoCs Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 450/826] clk: en7523: remove REG_PCIE*_{MEM,MEM_MASK} configuration Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 451/826] clk: en7523: move clock_register in hw_init callback Greg Kroah-Hartman
2024-12-03 14:42 ` [PATCH 6.12 452/826] clk: en7523: introduce chip_scu regmap Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 453/826] clk: en7523: fix estimation of fixed rate for EN7581 Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 454/826] dt-bindings: clock: axi-clkgen: include AXI clk Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 455/826] clk: clk-axi-clkgen: make sure to enable the AXI bus clock Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 456/826] zram: permit only one post-processing operation at a time Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 457/826] zram: fix NULL pointer in comp_algorithm_show() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 458/826] RDMA/bnxt_re: Correct the sequence of device suspend Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 459/826] arm64: dts: qcom: sc8180x: Add a SoC-specific compatible to cpufreq-hw Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 460/826] pinctrl: k210: Undef K210_PC_DEFAULT Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 461/826] rtla/timerlat: Do not set params->user_workload with -U Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 462/826] smb: cached directories can be more than root file handle Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 463/826] mailbox: mtk-cmdq: fix wrong use of sizeof in cmdq_get_clocks() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 464/826] mailbox: arm_mhuv2: clean up loop in get_irq_chan_comb() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 465/826] x86: fix off-by-one in access_ok() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 466/826] perf cs-etm: Dont flush when packet_queue fills up Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 467/826] gfs2: Rename GLF_VERIFY_EVICT to GLF_VERIFY_DELETE Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 468/826] gfs2: Allow immediate GLF_VERIFY_DELETE work Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 469/826] gfs2: Fix unlinked inode cleanup Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 470/826] perf stat: Uniquify event name improvements Greg Kroah-Hartman
2024-12-03 17:24   ` Thorsten Leemhuis
2024-12-04 17:43     ` Thorsten Leemhuis
2024-12-05  8:54     ` James Clark
2024-12-05  9:27       ` Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 471/826] perf mem: Fix printing PERF_MEM_LVLNUM_{L2_MHB|MSC} Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 472/826] dt-bindings: PCI: mediatek-gen3: Allow exact number of clocks only Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 473/826] PCI: Fix reset_method_store() memory leak Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 474/826] perf jevents: Dont stop at the first matched pmu when searching a events table Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 475/826] perf stat: Close cork_fd when create_perf_stat_counter() failed Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 476/826] perf stat: Fix affinity memory leaks on error path Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 477/826] perf trace: Keep exited threads for summary Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 478/826] perf test attr: Add back missing topdown events Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 479/826] rust: rbtree: fix `SAFETY` comments that should be `# Safety` sections Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 480/826] f2fs: compress: fix inconsistent update of i_blocks in release_compress_blocks and reserve_compress_blocks Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 481/826] f2fs: fix null-ptr-deref in f2fs_submit_page_bio() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 482/826] mailbox, remoteproc: k3-m4+: fix compile testing Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 483/826] f2fs: fix to account dirty data in __get_secs_required() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 484/826] perf dso: Fix symtab_type for kmod compression Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 485/826] perf disasm: Fix capstone memory leak Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 486/826] perf probe: Fix libdw " Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 487/826] perf probe: Correct demangled symbols in C++ program Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 488/826] rust: kernel: fix THIS_MODULE header path in ThisModule doc comment Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 489/826] rust: macros: fix documentation of the paste! macro Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 490/826] PCI: cpqphp: Fix PCIBIOS_* return value confusion Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 491/826] rust: block: fix formatting of `kernel::block::mq::request` module Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 492/826] perf disasm: Use disasm_line__free() to properly free disasm_line Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 493/826] perf disasm: Fix not cleaning up disasm_line in symbol__disassemble_raw() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 494/826] virtiofs: use pages instead of pointer for kernel direct IO Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 495/826] perf ftrace latency: Fix unit on histogram first entry when using --use-nsec Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 496/826] i3c: master: Remove i3c_dev_disable_ibi_locked(olddev) on device hotjoin Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 497/826] f2fs: fix the wrong f2fs_bug_on condition in f2fs_do_replace_block Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 498/826] f2fs: check curseg->inited before write_sum_page in change_curseg Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 499/826] f2fs: Fix not used variable index Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 500/826] f2fs: fix to avoid potential deadlock in f2fs_record_stop_reason() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 501/826] f2fs: fix to avoid use GC_AT when setting gc_mode as GC_URGENT_LOW or GC_URGENT_MID Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 502/826] PCI: qcom: Enable MSI interrupts together with Link up if Global IRQ is supported Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 503/826] PCI: qcom-ep: Move controller cleanups to qcom_pcie_perst_deassert() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 504/826] PCI: tegra194: Move controller cleanups to pex_ep_event_pex_rst_deassert() Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 505/826] PCI: j721e: Deassert PERST# after a delay of PCIE_T_PVPERL_MS milliseconds Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 506/826] perf build: Add missing cflags when building with custom libtraceevent Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 507/826] f2fs: fix race in concurrent f2fs_stop_gc_thread Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 508/826] f2fs: fix to map blocks correctly for direct write Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 509/826] f2fs: fix to avoid forcing direct write to use buffered IO on inline_data inode Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 510/826] perf trace: avoid garbage when not printing a trace events arguments Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 511/826] m68k: mcfgpio: Fix incorrect register offset for CONFIG_M5441x Greg Kroah-Hartman
2024-12-03 14:43 ` [PATCH 6.12 512/826] m68k: coldfire/device.c: only build FEC when HW macros are defined Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 513/826] svcrdma: Address an integer overflow Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 514/826] nfsd: drop inode parameter from nfsd4_change_attribute() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 515/826] perf list: Fix topic and pmu_name argument order Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 516/826] perf trace: Fix tracing itself, creating feedback loops Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 517/826] perf trace: Do not lose last events in a race Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 518/826] perf trace: Avoid garbage when not printing a syscalls arguments Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 519/826] remoteproc: qcom: pas: Remove subdevs on the error path of adsp_probe() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 520/826] remoteproc: qcom: adsp: " Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 521/826] remoteproc: qcom: pas: add minidump_id to SM8350 resources Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 522/826] rpmsg: glink: use only lower 16-bits of param2 for CMD_OPEN name length Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 523/826] remoteproc: qcom_q6v5_mss: Re-order writes to the IMEM region Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 524/826] PCI: endpoint: epf-mhi: Avoid NULL dereference if DT lacks mmio Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 525/826] NFSD: Prevent NULL dereference in nfsd4_process_cb_update() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 526/826] NFSD: Cap the number of bytes copied by nfs4_reset_recoverydir() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 527/826] nfsd: release svc_expkey/svc_export with rcu_work Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 528/826] svcrdma: fix miss destroy percpu_counter in svc_rdma_proc_init() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 529/826] NFSD: Fix nfsd4_shutdown_copy() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 530/826] nfs_common: must not hold RCU while calling nfsd_file_put_local Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 531/826] f2fs: fix to do cast in F2FS_{BLK_TO_BYTES, BTYES_TO_BLK} to avoid overflow Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 532/826] perf bpf-filter: Return -ENOMEM directly when pfi allocation fails Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 533/826] hwmon: (tps23861) Fix reporting of negative temperatures Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 534/826] hwmon: (aquacomputer_d5next) Fix length of speed_input array Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 535/826] phy: airoha: Fix REG_CSR_2L_PLL_CMN_RESERVE0 config in airoha_pcie_phy_init_clk_out() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 536/826] phy: airoha: Fix REG_PCIE_PMA_TX_RESET config in airoha_pcie_phy_init_csr_2l() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 537/826] phy: airoha: Fix REG_CSR_2L_JCPLL_SDM_HREN config in airoha_pcie_phy_init_ssc_jcpll() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 538/826] phy: airoha: Fix REG_CSR_2L_RX{0,1}_REV0 definitions Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 539/826] vdpa/mlx5: Fix suboptimal range on iotlb iteration Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 540/826] vfio/mlx5: Fix an unwind issue in mlx5vf_add_migration_pages() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 541/826] vfio/mlx5: Fix unwind flows in mlx5vf_pci_save/resume_device_data() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 542/826] selftests/mount_setattr: Fix failures on 64K PAGE_SIZE kernels Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 543/826] gpio: zevio: Add missed label initialisation Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 544/826] vfio/pci: Properly hide first-in-list PCIe extended capability Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 545/826] fs_parser: update mount_api doc to match function signature Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 546/826] LoongArch: Fix build failure with GCC 15 (-std=gnu23) Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 547/826] LoongArch: BPF: Sign-extend return values Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 548/826] power: supply: core: Remove might_sleep() from power_supply_put() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 549/826] power: supply: bq27xxx: Fix registers of bq27426 Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 550/826] power: supply: rt9471: Fix wrong WDT function regfield declaration Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 551/826] power: supply: rt9471: Use IC status regfield to report real charger status Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 552/826] fs/ntfs3: Equivalent transition from page to folio Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 553/826] power: reset: ep93xx: add AUXILIARY_BUS dependency Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 554/826] net: usb: lan78xx: Fix double free issue with interrupt buffer allocation Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 555/826] net: usb: lan78xx: Fix memory leak on device unplug by freeing PHY device Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 556/826] tg3: Set coherent DMA mask bits to 31 for BCM57766 chipsets Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 557/826] net: usb: lan78xx: Fix refcounting and autosuspend on invalid WoL configuration Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 558/826] net: microchip: vcap: Add typegroup table terminators in kunit tests Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 559/826] netlink: fix false positive warning in extack during dumps Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 560/826] exfat: fix file being changed by unaligned direct write Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 561/826] net/l2tp: fix warning in l2tp_exit_net found by syzbot Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 562/826] s390/iucv: MSG_PEEK causes memory leak in iucv_sock_destruct() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 563/826] rtase: Refactor the rtase_check_mac_version_valid() function Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 564/826] rtase: Correct the speed for RTL907XD-V1 Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 565/826] rtase: Corrects error handling of the rtase_check_mac_version_valid() Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 566/826] net/ipv6: delete temporary address if mngtmpaddr is removed or unmanaged Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 567/826] net: mdio-ipq4019: add missing error check Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 568/826] marvell: pxa168_eth: fix call balance of pep->clk handling routines Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 569/826] net: stmmac: dwmac-socfpga: Set RX watchdog interrupt as broken Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 570/826] octeontx2-af: RPM: Fix mismatch in lmac type Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 571/826] octeontx2-af: RPM: Fix low network performance Greg Kroah-Hartman
2024-12-03 14:44 ` [PATCH 6.12 572/826] octeontx2-af: RPM: fix stale RSFEC counters Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 573/826] octeontx2-af: RPM: fix stale FCFEC counters Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 574/826] octeontx2-af: Quiesce traffic before NIX block reset Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 575/826] spi: atmel-quadspi: Fix register name in verbose logging function Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 576/826] net: hsr: fix hsr_init_sk() vs network/transport headers Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 577/826] bnxt_en: Reserve rings after PCIe AER recovery if NIC interface is down Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 578/826] bnxt_en: Set backplane link modes correctly for ethtool Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 579/826] bnxt_en: Fix queue start to update vnic RSS table Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 580/826] bnxt_en: Fix receive ring space parameters when XDP is active Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 581/826] bnxt_en: Refactor bnxt_ptp_init() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 582/826] bnxt_en: Unregister PTP during PCI shutdown and suspend Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 583/826] Bluetooth: MGMT: Fix slab-use-after-free Read in set_powered_sync Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 584/826] Bluetooth: MGMT: Fix possible deadlocks Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 585/826] llc: Improve setsockopt() handling of malformed user input Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 586/826] rxrpc: " Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 587/826] tcp: Fix use-after-free of nreq in reqsk_timer_handler() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 588/826] ip6mr: fix tables suspicious RCU usage Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 589/826] ipmr: " Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 590/826] iio: light: al3010: Fix an error handling path in al3010_probe() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 591/826] usb: using mutex lock and supporting O_NONBLOCK flag in iowarrior_read() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 592/826] usb: yurex: make waiting on yurex_write interruptible Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 593/826] USB: chaoskey: fail open after removal Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 594/826] USB: chaoskey: Fix possible deadlock chaoskey_list_lock Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 595/826] misc: apds990x: Fix missing pm_runtime_disable() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 596/826] devres: Fix page faults when tracing devres from unloaded modules Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 597/826] usb: gadget: uvc: wake pump everytime we update the free list Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 598/826] interconnect: qcom: icc-rpmh: probe defer incase of missing QoS clock dependency Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 599/826] iio: backend: fix wrong pointer passed to IS_ERR() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 600/826] iio: adc: ad4000: fix reading unsigned data Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 601/826] iio: adc: ad4000: Check for error code from devm_mutex_init() call Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 602/826] iio: adc: pac1921: " Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 603/826] iio: accel: adxl380: fix raw sample read Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 604/826] phy: realtek: usb: fix NULL deref in rtk_usb2phy_probe Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 605/826] phy: realtek: usb: fix NULL deref in rtk_usb3phy_probe Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 606/826] counter: stm32-timer-cnt: Add check for clk_enable() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 607/826] counter: ti-ecap-capture: " Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 608/826] bus: mhi: host: Switch trace_mhi_gen_tre fields to native endian Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 609/826] usb: typec: fix potential array underflow in ucsi_ccg_sync_control() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 610/826] firmware_loader: Fix possible resource leak in fw_log_firmware_info() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 611/826] ALSA: hda/realtek: Update ALC256 depop procedure Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 612/826] drm/radeon: Fix spurious unplug event on radeon HDMI Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 613/826] drm/amd/display: Fix null check for pipe_ctx->plane_state in dcn20_program_pipe Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 614/826] drm/amd/display: Fix null check for pipe_ctx->plane_state in hwss_setup_dpp Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 615/826] ASoC: imx-audmix: Add NULL check in imx_audmix_probe Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 616/826] drm/xe/ufence: Wake up waiters after setting ufence->signalled Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 617/826] apparmor: fix Do simple duplicate message elimination Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 618/826] ALSA: core: Fix possible NULL dereference caused by kunit_kzalloc() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 619/826] ASoC: amd: yc: Fix for enabling DMIC on acp6x via _DSD entry Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 620/826] ASoC: mediatek: Check num_codecs is not zero to avoid panic during probe Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 621/826] s390/pci: Fix potential double remove of hotplug slot Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 622/826] f2fs: fix fiemap failure issue when page size is 16KB Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 623/826] net_sched: sch_fq: dont follow the fast path if Tx is behind now Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 624/826] xen: Fix the issue of resource not being properly released in xenbus_dev_probe() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 625/826] ALSA: usb-audio: Fix potential out-of-bound accesses for Extigy and Mbox devices Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 626/826] ALSA: usb-audio: Fix out of bounds reads when finding clock sources Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 627/826] usb: ehci-spear: fix call balance of sehci clk handling routines Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 628/826] usb: typec: ucsi: glink: fix off-by-one in connector_status Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 629/826] xfs: fix simplify extent lookup in xfs_can_free_eofblocks Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 630/826] ext4: supress data-race warnings in ext4_free_inodes_{count,set}() Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 631/826] ext4: fix FS_IOC_GETFSMAP handling Greg Kroah-Hartman
2024-12-03 14:45 ` [PATCH 6.12 632/826] MAINTAINERS: update location of media main tree Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 633/826] docs: media: update location of the media patches Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 634/826] jfs: xattr: check invalid xattr size more strictly Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 635/826] ASoC: amd: yc: Add a quirk for microfone on Lenovo ThinkPad P14s Gen 5 21MES00B00 Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 636/826] ASoC: codecs: Fix atomicity violation in snd_soc_component_get_drvdata() Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 637/826] ASoC: da7213: Populate max_register to regmap_config Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 638/826] perf/x86/intel/pt: Fix buffer full but size is 0 case Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 639/826] crypto: x86/aegis128 - access 32-bit arguments as 32-bit Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 640/826] KVM: x86: switch hugepage recovery thread to vhost_task Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 641/826] KVM: x86/mmu: Skip the "try unsync" path iff the old SPTE was a leaf SPTE Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 642/826] KVM: x86: add back X86_LOCAL_APIC dependency Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 643/826] KVM: x86: Break CONFIG_KVM_X86s direct dependency on KVM_INTEL || KVM_AMD Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 644/826] powerpc/pseries: Fix KVM guest detection for disabling hardlockup detector Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 645/826] KVM: arm64: vgic-v3: Sanitise guest writes to GICR_INVLPIR Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 646/826] KVM: arm64: Ignore PMCNTENSET_EL0 while checking for overflow status Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 647/826] Revert "KVM: VMX: Move LOAD_IA32_PERF_GLOBAL_CTRL errata handling out of setup_vmcs_config()" Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 648/826] KVM: arm64: Dont retire aborted MMIO instruction Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 649/826] KVM: arm64: vgic-its: Clear ITE when DISCARD frees an ITE Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 650/826] KVM: arm64: Get rid of userspace_irqchip_in_use Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 651/826] KVM: arm64: vgic-its: Add a data length check in vgic_its_save_* Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 652/826] KVM: arm64: vgic-its: Clear DTE when MAPD unmaps a device Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 653/826] Compiler Attributes: disable __counted_by for clang < 19.1.3 Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 654/826] PCI: Fix use-after-free of slot->bus on hot remove Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 655/826] LoongArch: Explicitly specify code model in Makefile Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 656/826] clk: clk-loongson2: Fix memory corruption bug in struct loongson2_clk_provider Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 657/826] clk: clk-loongson2: Fix potential buffer overflow in flexible-array member access Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 658/826] fsnotify: fix sending inotify event with unexpected filename Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 659/826] fsnotify: Fix ordering of iput() and watched_objects decrement Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 660/826] comedi: Flush partial mappings in error case Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 661/826] apparmor: test: Fix memory leak for aa_unpack_strdup() Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 662/826] iio: dac: adi-axi-dac: fix wrong register bitfield Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 663/826] tty: ldsic: fix tty_ldisc_autoload sysctls proc_handler Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 664/826] locking/lockdep: Avoid creating new name string literals in lockdep_set_subclass() Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 665/826] tools/nolibc: s390: include std.h Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 666/826] fcntl: make F_DUPFD_QUERY associative Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 667/826] pinctrl: qcom: spmi: fix debugfs drive strength Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 668/826] dt-bindings: pinctrl: samsung: Fix interrupt constraint for variants with fallbacks Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 669/826] dt-bindings: iio: dac: ad3552r: fix maximum spi speed Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 670/826] exfat: fix uninit-value in __exfat_get_dentry_set Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 671/826] exfat: fix out-of-bounds access of directory entries Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 672/826] xhci: Fix control transfer error on Etron xHCI host Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 673/826] xhci: Combine two if statements for " Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 674/826] xhci: Dont perform Soft Retry " Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 675/826] xhci: Dont issue Reset Device command to " Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 676/826] Bluetooth: Fix type of len in rfcomm_sock_getsockopt{,_old}() Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 677/826] usb: xhci: Limit Stop Endpoint retries Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 678/826] usb: xhci: Fix TD invalidation under pending Set TR Dequeue Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 679/826] usb: xhci: Avoid queuing redundant Stop Endpoint commands Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 680/826] ARM: dts: omap36xx: declare 1GHz OPP as turbo again Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 681/826] wifi: ath12k: fix warning when unbinding Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 682/826] wifi: rtlwifi: Drastically reduce the attempts to read efuse in case of failures Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 683/826] wifi: nl80211: fix bounds checker error in nl80211_parse_sched_scan Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 684/826] wifi: ath12k: fix crash when unbinding Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 685/826] wifi: brcmfmac: release root node in all execution paths Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 686/826] Revert "fs: dont block i_writecount during exec" Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 687/826] Revert "f2fs: remove unreachable lazytime mount option parsing" Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 688/826] Revert "usb: gadget: composite: fix OS descriptors w_value logic" Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 689/826] serial: sh-sci: Clean sci_ports[0] after at earlycon exit Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 690/826] Revert "serial: sh-sci: Clean sci_ports[0] after at earlycon exit" Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 691/826] io_uring: fix corner case forgetting to vunmap Greg Kroah-Hartman
2024-12-03 14:46 ` [PATCH 6.12 692/826] io_uring: check for overflows in io_pin_pages Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 693/826] blk-settings: round down io_opt to physical_block_size Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 694/826] gpio: exar: set value when external pull-up or pull-down is present Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 695/826] netfilter: ipset: add missing range check in bitmap_ip_uadt Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 696/826] spi: Fix acpi deferred irq probe Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 697/826] mtd: spi-nor: core: replace dummy buswidth from addr to data Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 698/826] cpufreq: mediatek-hw: Fix wrong return value in mtk_cpufreq_get_cpu_power() Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 699/826] cifs: support mounting with alternate password to allow password rotation Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 700/826] parisc/ftrace: Fix function graph tracing disablement Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 701/826] RISC-V: Scalar unaligned access emulated on hotplug CPUs Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 702/826] RISC-V: Check scalar unaligned access on all CPUs Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 703/826] ksmbd: fix use-after-free in SMB request handling Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 704/826] smb: client: fix NULL ptr deref in crypto_aead_setkey() Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 705/826] platform/chrome: cros_ec_typec: fix missing fwnode reference decrement Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 706/826] irqchip/irq-mvebu-sei: Move misplaced select() callback to SEI CP domain Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 707/826] x86/CPU/AMD: Terminate the erratum_1386_microcode array Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 708/826] ubi: wl: Put source PEB into correct list if trying locking LEB failed Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 709/826] um: ubd: Do not use drvdata in release Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 710/826] um: net: " Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 711/826] dt-bindings: serial: rs485: Fix rs485-rts-delay property Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 712/826] serial: 8250_fintek: Add support for F81216E Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 713/826] serial: 8250: omap: Move pm_runtime_get_sync Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 714/826] serial: amba-pl011: Fix RX stall when DMA is used Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 715/826] serial: amba-pl011: fix build regression Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 716/826] Revert "block, bfq: merge bfq_release_process_ref() into bfq_put_cooperator()" Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 717/826] mtd: ubi: fix unreleased fwnode_handle in find_volume_fwnode() Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 718/826] block: Prevent potential deadlock in blk_revalidate_disk_zones() Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 719/826] um: vector: Do not use drvdata in release Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 720/826] sh: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 721/826] iio: gts: Fix uninitialized symbol ret Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 722/826] ublk: fix ublk_ch_mmap() for 64K page size Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 723/826] arm64: tls: Fix context-switching of tpidrro_el0 when kpti is enabled Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 724/826] block: fix missing dispatching request when queue is started or unquiesced Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 725/826] block: fix ordering between checking QUEUE_FLAG_QUIESCED request adding Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 726/826] block: fix ordering between checking BLK_MQ_S_STOPPED " Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 727/826] blk-mq: Make blk_mq_quiesce_tagset() hold the tag list mutex less long Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 728/826] gve: Flow steering trigger reset only for timeout error Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 729/826] HID: wacom: Interpret tilt data from Intuos Pro BT as signed values Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 730/826] i40e: Fix handling changed priv flags Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 731/826] media: wl128x: Fix atomicity violation in fmc_send_cmd() Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 732/826] media: intel/ipu6: do not handle interrupts when device is disabled Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 733/826] arm64: dts: mediatek: mt8186-corsola-voltorb: Merge speaker codec nodes Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 734/826] netdev-genl: Hold rcu_read_lock in napi_get Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 735/826] soc: fsl: cpm1: qmc: Set the ret error code on platform_get_irq() failure Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 736/826] soc: fsl: rcpm: fix missing of_node_put() in copy_ippdexpcr1_setting() Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 737/826] media: v4l2-core: v4l2-dv-timings: check cvt/gtf result Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 738/826] x86/mm: Carve out INVLPG inline asm for use by others Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 739/826] x86/microcode/AMD: Flush patch buffer mapping after application Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 740/826] ALSA: rawmidi: Fix kvfree() call in spinlock Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 741/826] ALSA: ump: Fix evaluation of MIDI 1.0 FB info Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 742/826] ALSA: pcm: Add sanity NULL check for the default mmap fault handler Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 743/826] ALSA: hda/realtek: Update ALC225 depop procedure Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 744/826] ALSA: hda/realtek: Enable speaker pins for Medion E15443 platform Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 745/826] ALSA: hda/realtek: Set PCBeep to default value for ALC274 Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 746/826] ALSA: hda/realtek: Fix Internal Speaker and Mic boost of Infinix Y4 Max Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 747/826] ALSA: hda/realtek: fix mute/micmute LEDs dont work for EliteBook X G1i Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 748/826] ALSA: hda/realtek: Apply quirk for Medion E15433 Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 749/826] fs/smb/client: implement chmod() for SMB3 POSIX Extensions Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 750/826] smb: client: fix use-after-free of signing key Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 751/826] smb3: request handle caching when caching directories Greg Kroah-Hartman
2024-12-03 14:47 ` [PATCH 6.12 752/826] smb: client: handle max length for SMB symlinks Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 753/826] smb: Dont leak cfid when reconnect races with open_cached_dir Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 754/826] smb: prevent use-after-free due to open_cached_dir error paths Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 755/826] smb: During unmount, ensure all cached dir instances drop their dentry Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 756/826] usb: misc: ljca: set small runtime autosuspend delay Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 757/826] usb: misc: ljca: move usb_autopm_put_interface() after wait for response Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 758/826] usb: dwc3: ep0: Dont clear ep0 DWC3_EP_TRANSFER_STARTED Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 759/826] usb: musb: Fix hardware lockup on first Rx endpoint request Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 760/826] usb: dwc3: gadget: Add missing check for single port RAM in TxFIFO resizing logic Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 761/826] usb: dwc3: gadget: Fix checking for number of TRBs left Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 762/826] usb: dwc3: gadget: Fix looping of queued SG entries Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 763/826] staging: vchiq_arm: Fix missing refcount decrement in error path for fw_node Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 764/826] counter: stm32-timer-cnt: fix device_node handling in probe_encoder() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 765/826] ublk: fix error code for unsupported command Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 766/826] lib: string_helpers: silence snprintf() output truncation warning Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 767/826] f2fs: fix to do sanity check on node blkaddr in truncate_node() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 768/826] ipc: fix memleak if msg_init_ns failed in create_ipc_ns Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 769/826] Input: cs40l50 - fix wrong usage of INIT_WORK() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 770/826] NFSD: Prevent a potential integer overflow Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 771/826] SUNRPC: make sure cache entry active before cache_show Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 772/826] um: Fix potential integer overflow during physmem setup Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 773/826] um: Fix the return value of elf_core_copy_task_fpregs Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 774/826] kfifo: dont include dma-mapping.h in kfifo.h Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 775/826] um: ubd: Initialize ubds disk pointer in ubd_add Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 776/826] um: Always dump trace for specified task in show_stack Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 777/826] NFSv4.0: Fix a use-after-free problem in the asynchronous open() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 778/826] nfs/localio: must clear res.replen in nfs_local_read_done Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 779/826] rtc: st-lpc: Use IRQF_NO_AUTOEN flag in request_irq() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 780/826] rtc: abx80x: Fix WDT bit position of the status register Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 781/826] rtc: check if __rtc_read_time was successful in rtc_timer_do_work() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 782/826] ubi: fastmap: wl: Schedule fm_work if wear-leveling pool is empty Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 783/826] ubifs: Correct the total block count by deducting journal reservation Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 784/826] ubi: fastmap: Fix duplicate slab cache names while attaching Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 785/826] ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 786/826] jffs2: fix use of uninitialized variable Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 787/826] hostfs: Fix the NULL vs IS_ERR() bug for __filemap_get_folio() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 788/826] net/9p/usbg: fix handling of the failed kzalloc() memory allocation Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 789/826] rtc: rzn1: fix BCD to rtc_time conversion errors Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 790/826] Revert "nfs: dont reuse partially completed requests in nfs_lock_and_join_requests" Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 791/826] nvme/multipath: Fix RCU list traversal to use SRCU primitive Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 792/826] blk-mq: add non_owner variant of start_freeze/unfreeze queue APIs Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 793/826] block: model freeze & enter queue as lock for supporting lockdep Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 794/826] block: fix uaf for flush rq while iterating tags Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 795/826] block: return unsigned int from bdev_io_min Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 796/826] nvme-fabrics: fix kernel crash while shutting down controller Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 797/826] 9p/xen: fix init sequence Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 798/826] 9p/xen: fix release of IRQ Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 799/826] perf/arm-smmuv3: Fix lockdep assert in ->event_init() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 800/826] perf/arm-cmn: Ensure port and device id bits are set properly Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 801/826] smb: client: disable directory caching when dir_cache_timeout is zero Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 802/826] x86/Documentation: Update algo in init_size description of boot protocol Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 803/826] cifs: Fix parsing native symlinks relative to the export Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 804/826] cifs: Fix parsing reparse point with native symlink in SMB1 non-UNICODE session Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 805/826] rtc: ab-eoz9: dont fail temperature reads on undervoltage notification Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 806/826] Rename .data.unlikely to .data..unlikely Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 807/826] Rename .data.once to .data..once to fix resetting WARN*_ONCE Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 808/826] kbuild: deb-pkg: Dont fail if modules.order is missing Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 809/826] smb: Initialize cfid->tcon before performing network ops Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 810/826] block: Dont allow an atomic write be truncated in blkdev_write_iter() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 811/826] modpost: remove incorrect code in do_eisa_entry() Greg Kroah-Hartman
2024-12-03 14:48 ` [PATCH 6.12 812/826] cifs: during remount, make sure passwords are in sync Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 813/826] cifs: unlock on error in smb3_reconfigure() Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 814/826] nfs: ignore SB_RDONLY when mounting nfs Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 815/826] sunrpc: clear XPRT_SOCK_UPD_TIMEOUT when reset transport Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 816/826] SUNRPC: timeout and cancel TLS handshake with -ETIMEDOUT Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 817/826] sunrpc: fix one UAF issue caused by sunrpc kernel tcp socket Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 818/826] nfs/blocklayout: Dont attempt unregister for invalid block device Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 819/826] nfs/blocklayout: Limit repeat device registration on failure Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 820/826] block, bfq: fix bfqq uaf in bfq_limit_depth() Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 821/826] brd: decrease the number of allocated pages which discarded Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 822/826] sh: intc: Fix use-after-free bug in register_intc_controller() Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 823/826] tools/power turbostat: Fix trailing \n parsing Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 824/826] tools/power turbostat: Fix childs argument forwarding Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 825/826] block: always verify unfreeze lock on the owner task Greg Kroah-Hartman
2024-12-03 14:49 ` [PATCH 6.12 826/826] block: dont verify IO lock for freeze/unfreeze in elevator_init_mq() Greg Kroah-Hartman
2024-12-03 21:32 ` [PATCH 6.12 000/826] 6.12.2-rc1 review Peter Schneider
2024-12-03 22:07 ` Mark Brown
2024-12-03 22:36 ` Florian Fainelli
2024-12-04  0:24 ` SeongJae Park
2024-12-04  7:09 ` Ron Economos
2024-12-04 13:00 ` Naresh Kamboju
2024-12-04 16:48   ` Nathan Chancellor
2024-12-05  9:23     ` Greg Kroah-Hartman
2024-12-04 16:53 ` Shuah Khan
2024-12-04 18:44 ` Miguel Ojeda
2024-12-05 11:13 ` Muhammad Usama Anjum
2024-12-05 11:22 ` Pavel Machek
2024-12-05 14:39 ` Jon Hunter
2024-12-05 14:46   ` Jon Hunter
2024-12-05 15:46 ` Peter Jung
2024-12-05 17:51   ` Linus Torvalds
2024-12-06  5:48     ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241203144754.424173605@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=kevin_yang@realtek.com \
    --cc=patches@lists.linux.dev \
    --cc=pkshih@realtek.com \
    --cc=sashal@kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox