Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Apr 2026 21:09:04 +0000
From:      Bjoern A. Zeeb <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: bcdf750def1d - stable/15 - rtw88: update Realtek's rtw88 driver
Message-ID:  <69e938f0.275fb.738f6d4f@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch stable/15 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=bcdf750def1d5776140e1114ef155f9b018beac3

commit bcdf750def1d5776140e1114ef155f9b018beac3
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-04-18 14:21:04 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-04-22 20:57:11 +0000

    rtw88: update Realtek's rtw88 driver
    
    This version is based on
    git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    028ef9c96e96197026887c0f092424679298aae8 ( tag: v7.0 ).
    
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 41b641cc0537d1288cc05332bb4c5de3dcb12589)
---
 sys/contrib/dev/rtw88/fw.c        |  2 +-
 sys/contrib/dev/rtw88/main.c      | 54 +++++++++++++++++++++++++++------------
 sys/contrib/dev/rtw88/main.h      |  2 +-
 sys/contrib/dev/rtw88/phy.c       | 20 +++++++++++++++
 sys/contrib/dev/rtw88/phy.h       |  2 ++
 sys/contrib/dev/rtw88/rtw8723cs.c |  2 +-
 sys/contrib/dev/rtw88/rtw8723ds.c |  2 +-
 sys/contrib/dev/rtw88/rtw8821cs.c |  2 +-
 sys/contrib/dev/rtw88/rtw8821cu.c |  2 ++
 sys/contrib/dev/rtw88/rtw8822b.c  |  3 ++-
 sys/contrib/dev/rtw88/rtw8822bs.c |  2 +-
 sys/contrib/dev/rtw88/rtw8822cs.c |  2 +-
 sys/contrib/dev/rtw88/sdio.c      |  6 ++---
 sys/contrib/dev/rtw88/sdio.h      |  2 +-
 sys/contrib/dev/rtw88/usb.c       |  5 ++--
 sys/contrib/dev/rtw88/util.c      |  4 +--
 16 files changed, 78 insertions(+), 34 deletions(-)

diff --git a/sys/contrib/dev/rtw88/fw.c b/sys/contrib/dev/rtw88/fw.c
index 5ce4a6bcffb6..1574b2422240 100644
--- a/sys/contrib/dev/rtw88/fw.c
+++ b/sys/contrib/dev/rtw88/fw.c
@@ -1331,7 +1331,7 @@ static struct rtw_rsvd_page *rtw_alloc_rsvd_page(struct rtw_dev *rtwdev,
 {
 	struct rtw_rsvd_page *rsvd_pkt = NULL;
 
-	rsvd_pkt = kzalloc(sizeof(*rsvd_pkt), GFP_KERNEL);
+	rsvd_pkt = kzalloc_obj(*rsvd_pkt);
 
 	if (!rsvd_pkt)
 		return NULL;
diff --git a/sys/contrib/dev/rtw88/main.c b/sys/contrib/dev/rtw88/main.c
index b38709b180fd..43d537d0daba 100644
--- a/sys/contrib/dev/rtw88/main.c
+++ b/sys/contrib/dev/rtw88/main.c
@@ -811,10 +811,10 @@ void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel)
 }
 EXPORT_SYMBOL(rtw_set_rx_freq_band);
 
-void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period)
+void rtw_set_dtim_period(struct rtw_dev *rtwdev, u8 dtim_period)
 {
 	rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_TIMIE);
-	rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period - 1);
+	rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period ? dtim_period - 1 : 0);
 }
 
 void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel,
@@ -1568,6 +1568,8 @@ void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
 
 	set_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
 	set_bit(RTW_FLAG_SCANNING, rtwdev->flags);
+
+	rtw_phy_dig_set_max_coverage(rtwdev);
 }
 
 void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
@@ -1579,6 +1581,7 @@ void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
 	if (!rtwvif)
 		return;
 
+	rtw_phy_dig_reset(rtwdev);
 	clear_bit(RTW_FLAG_SCANNING, rtwdev->flags);
 	clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
 
@@ -1743,14 +1746,41 @@ static u16 rtw_get_max_scan_ie_len(struct rtw_dev *rtwdev)
 	return len;
 }
 
+static struct ieee80211_supported_band *
+rtw_sband_dup(struct rtw_dev *rtwdev,
+	      const struct ieee80211_supported_band *sband)
+{
+	struct ieee80211_supported_band *dup;
+
+	dup = devm_kmemdup(rtwdev->dev, sband, sizeof(*sband), GFP_KERNEL);
+	if (!dup)
+		return NULL;
+
+	dup->channels = devm_kmemdup_array(rtwdev->dev, sband->channels,
+					   sband->n_channels,
+					   sizeof(*sband->channels),
+					   GFP_KERNEL);
+	if (!dup->channels)
+		return NULL;
+
+	dup->bitrates = devm_kmemdup_array(rtwdev->dev, sband->bitrates,
+					   sband->n_bitrates,
+					   sizeof(*sband->bitrates),
+					   GFP_KERNEL);
+	if (!dup->bitrates)
+		return NULL;
+
+	return dup;
+}
+
 static void rtw_set_supported_band(struct ieee80211_hw *hw,
 				   const struct rtw_chip_info *chip)
 {
-	struct rtw_dev *rtwdev = hw->priv;
 	struct ieee80211_supported_band *sband;
+	struct rtw_dev *rtwdev = hw->priv;
 
 	if (chip->band & RTW_BAND_2G) {
-		sband = kmemdup(&rtw_band_2ghz, sizeof(*sband), GFP_KERNEL);
+		sband = rtw_sband_dup(rtwdev, &rtw_band_2ghz);
 		if (!sband)
 			goto err_out;
 #if defined(__linux__)
@@ -1763,7 +1793,7 @@ static void rtw_set_supported_band(struct ieee80211_hw *hw,
 	}
 
 	if (chip->band & RTW_BAND_5G) {
-		sband = kmemdup(&rtw_band_5ghz, sizeof(*sband), GFP_KERNEL);
+		sband = rtw_sband_dup(rtwdev, &rtw_band_5ghz);
 		if (!sband)
 			goto err_out;
 #if defined(__linux__)
@@ -1787,13 +1817,6 @@ err_out:
 	rtw_err(rtwdev, "failed to set supported band\n");
 }
 
-static void rtw_unset_supported_band(struct ieee80211_hw *hw,
-				     const struct rtw_chip_info *chip)
-{
-	kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]);
-	kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]);
-}
-
 static void rtw_vif_smps_iter(void *data, u8 *mac,
 			      struct ieee80211_vif *vif)
 {
@@ -2425,10 +2448,7 @@ EXPORT_SYMBOL(rtw_register_hw);
 
 void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
 {
-	const struct rtw_chip_info *chip = rtwdev->chip;
-
 	ieee80211_unregister_hw(hw);
-	rtw_unset_supported_band(hw, chip);
 	rtw_debugfs_deinit(rtwdev);
 	rtw_led_deinit(rtwdev);
 }
@@ -2549,10 +2569,10 @@ void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable)
 
 	if (enable) {
 		rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
-		rtw_write32_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+		rtw_write8_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
 	} else {
 		rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
-		rtw_write32_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+		rtw_write8_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
 	}
 }
 
diff --git a/sys/contrib/dev/rtw88/main.h b/sys/contrib/dev/rtw88/main.h
index d1e4f3e41ba1..212f5150e012 100644
--- a/sys/contrib/dev/rtw88/main.h
+++ b/sys/contrib/dev/rtw88/main.h
@@ -2235,7 +2235,7 @@ enum nl80211_band rtw_hw_to_nl80211_band(enum rtw_supported_band hw_band)
 }
 
 void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel);
-void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period);
+void rtw_set_dtim_period(struct rtw_dev *rtwdev, u8 dtim_period);
 void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
 			    struct rtw_channel_params *ch_param);
 bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target);
diff --git a/sys/contrib/dev/rtw88/phy.c b/sys/contrib/dev/rtw88/phy.c
index 55be0d8e0c28..e2ac5c6fd500 100644
--- a/sys/contrib/dev/rtw88/phy.c
+++ b/sys/contrib/dev/rtw88/phy.c
@@ -370,6 +370,26 @@ static void rtw_phy_statistics(struct rtw_dev *rtwdev)
 #define DIG_CVRG_MIN				0x1c
 #define DIG_RSSI_GAIN_OFFSET			15
 
+void rtw_phy_dig_set_max_coverage(struct rtw_dev *rtwdev)
+{
+	/* Lower values result in greater coverage. */
+	rtw_dbg(rtwdev, RTW_DBG_PHY, "Setting IGI=%#x for max coverage\n",
+		DIG_CVRG_MIN);
+
+	rtw_phy_dig_write(rtwdev, DIG_CVRG_MIN);
+}
+
+void rtw_phy_dig_reset(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 last_igi;
+
+	last_igi = dm_info->igi_history[0];
+	rtw_dbg(rtwdev, RTW_DBG_PHY, "Resetting IGI=%#x\n", last_igi);
+
+	rtw_phy_dig_write(rtwdev, last_igi);
+}
+
 static bool
 rtw_phy_dig_check_damping(struct rtw_dm_info *dm_info)
 {
diff --git a/sys/contrib/dev/rtw88/phy.h b/sys/contrib/dev/rtw88/phy.h
index c9e6b869661d..8449936497bb 100644
--- a/sys/contrib/dev/rtw88/phy.h
+++ b/sys/contrib/dev/rtw88/phy.h
@@ -146,6 +146,8 @@ static inline int rtw_check_supported_rfe(struct rtw_dev *rtwdev)
 }
 
 void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi);
+void rtw_phy_dig_reset(struct rtw_dev *rtwdev);
+void rtw_phy_dig_set_max_coverage(struct rtw_dev *rtwdev);
 
 struct rtw_power_params {
 	u8 pwr_base;
diff --git a/sys/contrib/dev/rtw88/rtw8723cs.c b/sys/contrib/dev/rtw88/rtw8723cs.c
index 1f98d35a8dd1..2018c9d76dd1 100644
--- a/sys/contrib/dev/rtw88/rtw8723cs.c
+++ b/sys/contrib/dev/rtw88/rtw8723cs.c
@@ -23,9 +23,9 @@ static struct sdio_driver rtw_8723cs_driver = {
 	.id_table = rtw_8723cs_id_table,
 	.probe = rtw_sdio_probe,
 	.remove = rtw_sdio_remove,
+	.shutdown = rtw_sdio_shutdown,
 	.drv = {
 		.pm = &rtw_sdio_pm_ops,
-		.shutdown = rtw_sdio_shutdown
 	}};
 module_sdio_driver(rtw_8723cs_driver);
 
diff --git a/sys/contrib/dev/rtw88/rtw8723ds.c b/sys/contrib/dev/rtw88/rtw8723ds.c
index 206b77e5b98e..e38c90b769a2 100644
--- a/sys/contrib/dev/rtw88/rtw8723ds.c
+++ b/sys/contrib/dev/rtw88/rtw8723ds.c
@@ -28,10 +28,10 @@ static struct sdio_driver rtw_8723ds_driver = {
 	.name = KBUILD_MODNAME,
 	.probe = rtw_sdio_probe,
 	.remove = rtw_sdio_remove,
+	.shutdown = rtw_sdio_shutdown,
 	.id_table = rtw_8723ds_id_table,
 	.drv = {
 		.pm = &rtw_sdio_pm_ops,
-		.shutdown = rtw_sdio_shutdown,
 	}
 };
 module_sdio_driver(rtw_8723ds_driver);
diff --git a/sys/contrib/dev/rtw88/rtw8821cs.c b/sys/contrib/dev/rtw88/rtw8821cs.c
index 6d94162213c6..58e0ef219cdc 100644
--- a/sys/contrib/dev/rtw88/rtw8821cs.c
+++ b/sys/contrib/dev/rtw88/rtw8821cs.c
@@ -23,10 +23,10 @@ static struct sdio_driver rtw_8821cs_driver = {
 	.name = KBUILD_MODNAME,
 	.probe = rtw_sdio_probe,
 	.remove = rtw_sdio_remove,
+	.shutdown = rtw_sdio_shutdown,
 	.id_table = rtw_8821cs_id_table,
 	.drv = {
 		.pm = &rtw_sdio_pm_ops,
-		.shutdown = rtw_sdio_shutdown,
 	}
 };
 module_sdio_driver(rtw_8821cs_driver);
diff --git a/sys/contrib/dev/rtw88/rtw8821cu.c b/sys/contrib/dev/rtw88/rtw8821cu.c
index 0f42819f787c..47ecd0394960 100644
--- a/sys/contrib/dev/rtw88/rtw8821cu.c
+++ b/sys/contrib/dev/rtw88/rtw8821cu.c
@@ -37,6 +37,8 @@ static const struct usb_device_id rtw_8821cu_id_table[] = {
 	  .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd811, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0105, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Mercusys */
 	{},
 };
 MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table);
diff --git a/sys/contrib/dev/rtw88/rtw8822b.c b/sys/contrib/dev/rtw88/rtw8822b.c
index b37b301fc866..f9097bc337df 100644
--- a/sys/contrib/dev/rtw88/rtw8822b.c
+++ b/sys/contrib/dev/rtw88/rtw8822b.c
@@ -1005,7 +1005,8 @@ static int rtw8822b_set_antenna(struct rtw_dev *rtwdev,
 	hal->antenna_tx = antenna_tx;
 	hal->antenna_rx = antenna_rx;
 
-	rtw8822b_config_trx_mode(rtwdev, antenna_tx, antenna_rx, false);
+	if (test_bit(RTW_FLAG_POWERON, rtwdev->flags))
+		rtw8822b_config_trx_mode(rtwdev, antenna_tx, antenna_rx, false);
 
 	return 0;
 }
diff --git a/sys/contrib/dev/rtw88/rtw8822bs.c b/sys/contrib/dev/rtw88/rtw8822bs.c
index 744781dcb419..2de9b11540c5 100644
--- a/sys/contrib/dev/rtw88/rtw8822bs.c
+++ b/sys/contrib/dev/rtw88/rtw8822bs.c
@@ -23,10 +23,10 @@ static struct sdio_driver rtw_8822bs_driver = {
 	.name = KBUILD_MODNAME,
 	.probe = rtw_sdio_probe,
 	.remove = rtw_sdio_remove,
+	.shutdown = rtw_sdio_shutdown,
 	.id_table = rtw_8822bs_id_table,
 	.drv = {
 		.pm = &rtw_sdio_pm_ops,
-		.shutdown = rtw_sdio_shutdown,
 	}
 };
 module_sdio_driver(rtw_8822bs_driver);
diff --git a/sys/contrib/dev/rtw88/rtw8822cs.c b/sys/contrib/dev/rtw88/rtw8822cs.c
index 322281e07eb8..b00ef4173962 100644
--- a/sys/contrib/dev/rtw88/rtw8822cs.c
+++ b/sys/contrib/dev/rtw88/rtw8822cs.c
@@ -23,10 +23,10 @@ static struct sdio_driver rtw_8822cs_driver = {
 	.name = KBUILD_MODNAME,
 	.probe = rtw_sdio_probe,
 	.remove = rtw_sdio_remove,
+	.shutdown = rtw_sdio_shutdown,
 	.id_table = rtw_8822cs_id_table,
 	.drv = {
 		.pm = &rtw_sdio_pm_ops,
-		.shutdown = rtw_sdio_shutdown,
 	}
 };
 module_sdio_driver(rtw_8822cs_driver);
diff --git a/sys/contrib/dev/rtw88/sdio.c b/sys/contrib/dev/rtw88/sdio.c
index e35de52d8eb4..1318e94f8524 100644
--- a/sys/contrib/dev/rtw88/sdio.c
+++ b/sys/contrib/dev/rtw88/sdio.c
@@ -1290,8 +1290,7 @@ static int rtw_sdio_init_tx(struct rtw_dev *rtwdev)
 
 	for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++)
 		skb_queue_head_init(&rtwsdio->tx_queue[i]);
-	rtwsdio->tx_handler_data = kmalloc(sizeof(*rtwsdio->tx_handler_data),
-					   GFP_KERNEL);
+	rtwsdio->tx_handler_data = kmalloc_obj(*rtwsdio->tx_handler_data);
 	if (!rtwsdio->tx_handler_data)
 		goto err_destroy_wq;
 
@@ -1414,9 +1413,8 @@ void rtw_sdio_remove(struct sdio_func *sdio_func)
 }
 EXPORT_SYMBOL(rtw_sdio_remove);
 
-void rtw_sdio_shutdown(struct device *dev)
+void rtw_sdio_shutdown(struct sdio_func *sdio_func)
 {
-	struct sdio_func *sdio_func = dev_to_sdio_func(dev);
 	const struct rtw_chip_info *chip;
 	struct ieee80211_hw *hw;
 	struct rtw_dev *rtwdev;
diff --git a/sys/contrib/dev/rtw88/sdio.h b/sys/contrib/dev/rtw88/sdio.h
index 3c659ed180f0..457e8b02380e 100644
--- a/sys/contrib/dev/rtw88/sdio.h
+++ b/sys/contrib/dev/rtw88/sdio.h
@@ -166,7 +166,7 @@ extern const struct dev_pm_ops rtw_sdio_pm_ops;
 int rtw_sdio_probe(struct sdio_func *sdio_func,
 		   const struct sdio_device_id *id);
 void rtw_sdio_remove(struct sdio_func *sdio_func);
-void rtw_sdio_shutdown(struct device *dev);
+void rtw_sdio_shutdown(struct sdio_func *sdio_func);
 
 static inline bool rtw_sdio_is_sdio30_supported(struct rtw_dev *rtwdev)
 {
diff --git a/sys/contrib/dev/rtw88/usb.c b/sys/contrib/dev/rtw88/usb.c
index 69a4cb60184f..1c2a1a328f09 100644
--- a/sys/contrib/dev/rtw88/usb.c
+++ b/sys/contrib/dev/rtw88/usb.c
@@ -403,7 +403,7 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list
 	if (skb_queue_empty(list))
 		return false;
 
-	txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC);
+	txcb = kmalloc_obj(*txcb, GFP_ATOMIC);
 	if (!txcb)
 		return false;
 
@@ -965,7 +965,8 @@ static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
 	struct sk_buff *rx_skb;
 	int i;
 
-	rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH, 0);
+	rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH | WQ_PERCPU,
+				       0);
 	if (!rtwusb->rxwq) {
 		rtw_err(rtwdev, "failed to create RX work queue\n");
 		return -ENOMEM;
diff --git a/sys/contrib/dev/rtw88/util.c b/sys/contrib/dev/rtw88/util.c
index 66819f694405..fcd6eb1ab32a 100644
--- a/sys/contrib/dev/rtw88/util.c
+++ b/sys/contrib/dev/rtw88/util.c
@@ -122,7 +122,7 @@ static void rtw_collect_sta_iter(void *data, struct ieee80211_sta *sta)
 	struct rtw_iter_stas_data *iter_stas = data;
 	struct rtw_stas_entry *stas_entry;
 
-	stas_entry = kmalloc(sizeof(*stas_entry), GFP_ATOMIC);
+	stas_entry = kmalloc_obj(*stas_entry, GFP_ATOMIC);
 	if (!stas_entry)
 		return;
 
@@ -172,7 +172,7 @@ static void rtw_collect_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 	struct rtw_iter_vifs_data *iter_stas = data;
 	struct rtw_vifs_entry *vifs_entry;
 
-	vifs_entry = kmalloc(sizeof(*vifs_entry), GFP_ATOMIC);
+	vifs_entry = kmalloc_obj(*vifs_entry, GFP_ATOMIC);
 	if (!vifs_entry)
 		return;
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e938f0.275fb.738f6d4f>