summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-04 13:45:09 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-04 13:45:09 +0200
commit8ca1f4c6fb1462ee120730ea75c19da10d2f2d6f (patch)
treefa6bebc72c42a94b66d4b3676371753d31e66702 /drivers/net
parent9372da540bfdcfa345309043e57b335c900a8ad9 (diff)
parent199c9959d3a9b53f346c221757fc7ac507fbac50 (diff)
downloadlinux-stable-linux-rolling-stable.tar.gz
linux-stable-linux-rolling-stable.zip
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wan/hdlc_ppp.c15
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/agg.c9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/ptp.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ptp.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c15
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/usb.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/main.c3
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/8188e.c1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/8188f.c1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/8192c.c1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/8192e.c1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/8192f.c1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/8710b.c1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/8723a.c1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/8723b.c1
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/core.c64
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/regs.h2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.c7
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c13
22 files changed, 135 insertions, 16 deletions
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index 159295c4bd6d..302ed27944e7 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -619,7 +619,6 @@ static void ppp_start(struct net_device *dev)
struct proto *proto = &ppp->protos[i];
proto->dev = dev;
- timer_setup(&proto->timer, ppp_timer, 0);
proto->state = CLOSED;
}
ppp->protos[IDX_LCP].pid = PID_LCP;
@@ -639,6 +638,15 @@ static void ppp_close(struct net_device *dev)
ppp_tx_flush();
}
+static void ppp_timer_release(struct net_device *dev)
+{
+ struct ppp *ppp = get_ppp(dev);
+ int i;
+
+ for (i = 0; i < IDX_COUNT; i++)
+ timer_shutdown_sync(&ppp->protos[i].timer);
+}
+
static struct hdlc_proto proto = {
.start = ppp_start,
.stop = ppp_stop,
@@ -647,6 +655,7 @@ static struct hdlc_proto proto = {
.ioctl = ppp_ioctl,
.netif_rx = ppp_rx,
.module = THIS_MODULE,
+ .detach = ppp_timer_release,
};
static const struct header_ops ppp_header_ops = {
@@ -657,7 +666,7 @@ static int ppp_ioctl(struct net_device *dev, struct if_settings *ifs)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
struct ppp *ppp;
- int result;
+ int i, result;
switch (ifs->type) {
case IF_GET_PROTO:
@@ -685,6 +694,8 @@ static int ppp_ioctl(struct net_device *dev, struct if_settings *ifs)
return result;
ppp = get_ppp(dev);
+ for (i = 0; i < IDX_COUNT; i++)
+ timer_setup(&ppp->protos[i].timer, ppp_timer, 0);
spin_lock_init(&ppp->lock);
ppp->req_timeout = 2;
ppp->cr_retries = 10;
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index bbb86f165141..5a50b623bd07 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -1040,6 +1040,7 @@ void ath11k_dp_free(struct ath11k_base *ab)
idr_destroy(&dp->tx_ring[i].txbuf_idr);
spin_unlock_bh(&dp->tx_ring[i].tx_idr_lock);
kfree(dp->tx_ring[i].tx_status);
+ dp->tx_ring[i].tx_status = NULL;
}
/* Deinit any SOC level resource */
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
index 3bf36f8f6874..e3627ad0321c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
@@ -64,6 +64,9 @@ static void iwl_mld_release_frames_from_notif(struct iwl_mld *mld,
}
/* pick any STA ID to find the pointer */
+ if (WARN_ON_ONCE(!ba_data->sta_mask))
+ goto out_unlock;
+
sta_id = ffs(ba_data->sta_mask) - 1;
link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
@@ -166,6 +169,9 @@ void iwl_mld_del_ba(struct iwl_mld *mld, int queue,
goto out_unlock;
/* pick any STA ID to find the pointer */
+ if (WARN_ON_ONCE(!ba_data->sta_mask))
+ goto out_unlock;
+
sta_id = ffs(ba_data->sta_mask) - 1;
link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
@@ -347,6 +353,9 @@ static void iwl_mld_rx_agg_session_expired(struct timer_list *t)
}
/* timer expired, pick any STA ID to find the pointer */
+ if (WARN_ON_ONCE(!ba_data->sta_mask))
+ goto unlock;
+
sta_id = ffs(ba_data->sta_mask) - 1;
link_sta = rcu_dereference(ba_data->mld->fw_id_to_link_sta[sta_id]);
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
index c65f4b56a327..20ae338e5696 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
@@ -321,10 +321,10 @@ void iwl_mld_ptp_remove(struct iwl_mld *mld)
mld->ptp_data.ptp_clock_info.name,
ptp_clock_index(mld->ptp_data.ptp_clock));
+ cancel_delayed_work_sync(&mld->ptp_data.dwork);
ptp_clock_unregister(mld->ptp_data.ptp_clock);
mld->ptp_data.ptp_clock = NULL;
mld->ptp_data.last_gp2 = 0;
mld->ptp_data.wrap_counter = 0;
- cancel_delayed_work_sync(&mld->ptp_data.dwork);
}
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
index f7b620136c85..e05e531b09f0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
@@ -325,11 +325,11 @@ void iwl_mvm_ptp_remove(struct iwl_mvm *mvm)
mvm->ptp_data.ptp_clock_info.name,
ptp_clock_index(mvm->ptp_data.ptp_clock));
+ cancel_delayed_work_sync(&mvm->ptp_data.dwork);
ptp_clock_unregister(mvm->ptp_data.ptp_clock);
mvm->ptp_data.ptp_clock = NULL;
memset(&mvm->ptp_data.ptp_clock_info, 0,
sizeof(mvm->ptp_data.ptp_clock_info));
mvm->ptp_data.last_gp2 = 0;
- cancel_delayed_work_sync(&mvm->ptp_data.dwork);
}
}
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 4ae5e4715a9c..b78b4cd206e0 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -1576,6 +1576,7 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
{
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
struct mt76_dev *dev = phy->dev;
+ struct mt76_wcid *published;
int ret;
int i;
@@ -1595,11 +1596,19 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
mtxq->wcid = wcid->idx;
}
- ewma_signal_init(&wcid->rssi);
- rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
+ published = rcu_dereference_protected(dev->wcid[wcid->idx],
+ lockdep_is_held(&dev->mutex));
+ if (published != wcid) {
+ WARN_ON_ONCE(published);
+ ewma_signal_init(&wcid->rssi);
+ rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
+ mt76_wcid_init(wcid, phy->band_idx);
+ } else {
+ wcid->phy_idx = phy->band_idx;
+ }
+
phy->num_sta++;
- mt76_wcid_init(wcid, phy->band_idx);
out:
mutex_unlock(&dev->mutex);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
index 01cb3b2830f3..459c4044f0d1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
@@ -16,6 +16,7 @@ static const struct usb_device_id mt76x2u_device_table[] = {
{ USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USBAC1200 - Alfa AWUS036ACM */
{ USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */
{ USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */
+ { USB_DEVICE(0x056e, 0x400a) }, /* ELECOM WDC-867SU3S */
{ USB_DEVICE(0x0e8d, 0x7632) }, /* HC-M7662BU1 */
{ USB_DEVICE(0x0471, 0x2126) }, /* LiteOn WN4516R module, nonstandard USB connector */
{ USB_DEVICE(0x0471, 0x7600) }, /* LiteOn WN4519R module, nonstandard USB connector */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 73d3722739d0..79cc30a3b29e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -1265,6 +1265,9 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_AP)
break;
+ if (vif->type == NL80211_IFTYPE_STATION && sta->tdls)
+ continue;
+
link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
if (!link_sta)
continue;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8188e.c b/drivers/net/wireless/realtek/rtl8xxxu/8188e.c
index 766a7a7c7d28..fea5aec9ced9 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/8188e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/8188e.c
@@ -1866,6 +1866,7 @@ struct rtl8xxxu_fileops rtl8188eu_fops = {
.has_tx_report = 1,
.init_reg_pkt_life_time = 1,
.gen2_thermal_meter = 1,
+ .hw_feature_report = 0,
.max_sec_cam_num = 32,
.adda_1t_init = 0x0b1b25a0,
.adda_1t_path_on = 0x0bdb25a0,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8188f.c b/drivers/net/wireless/realtek/rtl8xxxu/8188f.c
index 3abf14d7044f..5556aad1a7ad 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/8188f.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/8188f.c
@@ -1745,6 +1745,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
.init_reg_rxfltmap = 1,
.init_reg_pkt_life_time = 1,
.init_reg_hmtfr = 1,
+ .hw_feature_report = 1,
.ampdu_max_time = 0x70,
.ustime_tsf_edca = 0x28,
.max_aggr_num = 0x0c14,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/8192c.c
index 444872131c66..508322a8f310 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/8192c.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/8192c.c
@@ -723,6 +723,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = {
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
.supports_ap = 1,
+ .hw_feature_report = 0,
.max_macid_num = 32,
.max_sec_cam_num = 32,
.adda_1t_init = 0x0b1b25a0,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/8192e.c
index 8e123bbfc665..690ace303150 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/8192e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/8192e.c
@@ -1751,6 +1751,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops = {
.has_s0s1 = 0,
.gen2_thermal_meter = 1,
.needs_full_init = 1,
+ .hw_feature_report = 0,
.supports_ap = 1,
.max_macid_num = 128,
.max_sec_cam_num = 64,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8192f.c b/drivers/net/wireless/realtek/rtl8xxxu/8192f.c
index cd2156b7a57a..5f076da4b550 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/8192f.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/8192f.c
@@ -2074,6 +2074,7 @@ struct rtl8xxxu_fileops rtl8192fu_fops = {
.init_reg_rxfltmap = 1,
.init_reg_pkt_life_time = 1,
.init_reg_hmtfr = 1,
+ .hw_feature_report = 1,
.ampdu_max_time = 0x5e,
.ustime_tsf_edca = 0x50,
.max_aggr_num = 0x1f1f,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8710b.c b/drivers/net/wireless/realtek/rtl8xxxu/8710b.c
index 11c63c320eae..a87e692bfc81 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/8710b.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/8710b.c
@@ -1852,6 +1852,7 @@ struct rtl8xxxu_fileops rtl8710bu_fops = {
.init_reg_rxfltmap = 1,
.init_reg_pkt_life_time = 1,
.init_reg_hmtfr = 1,
+ .hw_feature_report = 0, /* TODO, it's different */
.ampdu_max_time = 0x5e,
/*
* The RTL8710BU vendor driver uses 0x50 here and it works fine,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8723a.c b/drivers/net/wireless/realtek/rtl8xxxu/8723a.c
index 4f4493d0bfc2..18e038b82f49 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/8723a.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/8723a.c
@@ -632,6 +632,7 @@ struct rtl8xxxu_fileops rtl8723au_fops = {
.rx_agg_buf_size = 16000,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
+ .hw_feature_report = 0,
.max_sec_cam_num = 32,
.adda_1t_init = 0x0b1b25a0,
.adda_1t_path_on = 0x0bdb25a0,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/8723b.c
index cc2e60b06f64..e314ef991b38 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/8723b.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/8723b.c
@@ -1746,6 +1746,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
.gen2_thermal_meter = 1,
.needs_full_init = 1,
.init_reg_hmtfr = 1,
+ .hw_feature_report = 0,
.ampdu_max_time = 0x5e,
.ustime_tsf_edca = 0x50,
.max_aggr_num = 0x0c14,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c
index f20fade0c099..40af324f5f0a 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c
@@ -14,6 +14,7 @@
*/
#include <linux/firmware.h>
+#include <linux/iopoll.h>
#include "regs.h"
#include "rtl8xxxu.h"
@@ -3915,6 +3916,46 @@ static inline u8 rtl8xxxu_get_macid(struct rtl8xxxu_priv *priv,
return sta_info->macid;
}
+static void rtl8xxxu_request_hw_feature(struct rtl8xxxu_priv *priv)
+{
+ if (!priv->fops->hw_feature_report)
+ return;
+
+ rtl8xxxu_write8(priv, REG_C2HEVT_MSG_NORMAL, C2H_HW_FEATURE_DUMP);
+}
+
+static int rtl8xxxu_dump_hw_feature(struct rtl8xxxu_priv *priv)
+{
+ static const u8 bw_map[8] = { 0, 0, 160, 5, 10, 20, 40, 80 };
+ struct rtl8xxxu_hw_feature *hw_feature = &priv->hw_feature;
+ u8 feature[13];
+ int i, ret;
+ u8 id, bw;
+
+ if (!priv->fops->hw_feature_report) {
+ hw_feature->max_bw = 40;
+ return 0;
+ }
+
+ ret = read_poll_timeout(rtl8xxxu_read8, id,
+ id == C2H_HW_FEATURE_REPORT,
+ 10000, 800000, false,
+ priv, REG_C2HEVT_MSG_NORMAL);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(feature); i++)
+ feature[i] = rtl8xxxu_read8(priv, REG_C2HEVT_MSG_NORMAL + 2 + i);
+
+ rtl8xxxu_write8(priv, REG_C2HEVT_MSG_NORMAL, 0);
+
+ bw = u8_get_bits(feature[6], GENMASK(2, 0));
+
+ hw_feature->max_bw = bw_map[bw];
+
+ return 0;
+}
+
static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
{
struct rtl8xxxu_priv *priv = hw->priv;
@@ -3961,6 +4002,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
*/
rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, fops->trxff_boundary);
+ rtl8xxxu_request_hw_feature(priv);
+
for (int retry = 5; retry >= 0 ; retry--) {
ret = rtl8xxxu_download_firmware(priv);
dev_dbg(dev, "%s: download_firmware %i\n", __func__, ret);
@@ -3976,6 +4019,12 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
if (ret)
goto exit;
+ ret = rtl8xxxu_dump_hw_feature(priv);
+ if (ret) {
+ dev_err(dev, "failed to dump hw feature\n");
+ goto exit;
+ }
+
if (fops->phy_init_antenna_selection)
fops->phy_init_antenna_selection(priv);
@@ -7835,15 +7884,20 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
sband->ht_cap.ht_supported = true;
sband->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
sband->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
- sband->ht_cap.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
- IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ sband->ht_cap.cap = IEEE80211_HT_CAP_SGI_20;
+
+ if (priv->hw_feature.max_bw >= 40) {
+ sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+ sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ } else {
+ dev_info(&udev->dev, "hardware doesn't support HT40\n");
+ }
+
memset(&sband->ht_cap.mcs, 0, sizeof(sband->ht_cap.mcs));
sband->ht_cap.mcs.rx_mask[0] = 0xff;
sband->ht_cap.mcs.rx_mask[4] = 0x01;
- if (priv->rf_paths > 1) {
+ if (priv->rf_paths > 1)
sband->ht_cap.mcs.rx_mask[1] = 0xff;
- sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
- }
sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
hw->wiphy->bands[NL80211_BAND_2GHZ] = sband;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/regs.h b/drivers/net/wireless/realtek/rtl8xxxu/regs.h
index 0741db8d08bf..eafaef1438b9 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/regs.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/regs.h
@@ -447,6 +447,8 @@
/* 8188EU */
#define REG_32K_CTRL 0x0194
#define REG_C2HEVT_MSG_NORMAL 0x01a0
+#define C2H_HW_FEATURE_REPORT 0x19
+#define C2H_HW_FEATURE_DUMP 0xfd
/* 8192EU/8723BU/8812 */
#define REG_C2HEVT_CMD_ID_8723B 0x01ae
#define REG_C2HEVT_CLEAR 0x01af
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index 9fb2583ffffc..eeb18eb0e4c0 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -1789,11 +1789,17 @@ struct rtl8xxxu_cfo_tracking {
#define RTL8XXXU_BC_MC_MACID1 1
#define RTL8XXXU_MAX_SEC_CAM_NUM 64
+struct rtl8xxxu_hw_feature {
+ u8 max_bw;
+};
+
struct rtl8xxxu_priv {
struct ieee80211_hw *hw;
struct usb_device *udev;
struct rtl8xxxu_fileops *fops;
+ struct rtl8xxxu_hw_feature hw_feature;
+
spinlock_t tx_urb_lock;
struct list_head tx_urb_free_list;
int tx_urb_free_count;
@@ -2009,6 +2015,7 @@ struct rtl8xxxu_fileops {
u8 init_reg_pkt_life_time:1;
u8 init_reg_hmtfr:1;
u8 supports_concurrent:1;
+ u8 hw_feature_report:1;
u8 ampdu_max_time;
u8 ustime_tsf_edca;
u16 max_aggr_num;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
index 1155365348f3..d5de09d75f45 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h
@@ -291,7 +291,7 @@ static inline int get_rx_desc_paggr(__le32 *__pdesc)
static inline int get_rx_status_desc_rpt_sel(__le32 *__pdesc)
{
- return le32_get_bits(*(__pdesc + 1), BIT(28));
+ return le32_get_bits(*(__pdesc + 2), BIT(28));
}
static inline int get_rx_desc_rxmcs(__le32 *__pdesc)
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index 3106edb84fb4..a6e43314a4e9 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -196,6 +196,7 @@ void rtw_tx_report_purge_timer(struct timer_list *t)
void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn)
{
struct rtw_tx_report *tx_report = &rtwdev->tx_report;
+ unsigned long timeout = RTW_TX_PROBE_TIMEOUT;
unsigned long flags;
u8 *drv_data;
@@ -207,7 +208,11 @@ void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn)
__skb_queue_tail(&tx_report->queue, skb);
spin_unlock_irqrestore(&tx_report->q_lock, flags);
- mod_timer(&tx_report->purge_timer, jiffies + RTW_TX_PROBE_TIMEOUT);
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8723D &&
+ rtwdev->hci.type == RTW_HCI_TYPE_USB)
+ timeout = msecs_to_jiffies(2500);
+
+ mod_timer(&tx_report->purge_timer, jiffies + timeout);
}
EXPORT_SYMBOL(rtw_tx_report_enqueue);
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 718940ebba31..1a0bdbf52cb0 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -399,6 +399,7 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list
int agg_num = 0;
unsigned int align_next = 0;
u8 qsel;
+ int ret;
if (skb_queue_empty(list))
return false;
@@ -456,7 +457,13 @@ queue:
tx_desc = (struct rtw_tx_desc *)skb_head->data;
qsel = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_QSEL);
- rtw_usb_write_port(rtwdev, qsel, skb_head, rtw_usb_write_port_tx_complete, txcb);
+ ret = rtw_usb_write_port(rtwdev, qsel, skb_head,
+ rtw_usb_write_port_tx_complete, txcb);
+ if (ret) {
+ ieee80211_purge_tx_queue(rtwdev->hw, &txcb->tx_ack_queue);
+ kfree(txcb);
+ return false;
+ }
return true;
}
@@ -518,8 +525,10 @@ static int rtw_usb_write_data(struct rtw_dev *rtwdev,
ret = rtw_usb_write_port(rtwdev, qsel, skb,
rtw_usb_write_port_complete, skb);
- if (unlikely(ret))
+ if (unlikely(ret)) {
rtw_err(rtwdev, "failed to do USB write, ret=%d\n", ret);
+ dev_kfree_skb_any(skb);
+ }
return ret;
}