summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek')
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c37
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c52
-rw-r--r--drivers/net/wireless/realtek/rtw88/Makefile2
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c8
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.h3
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h6
-rw-r--r--drivers/net/wireless/realtek/rtw88/pci.c47
-rw-r--r--drivers/net/wireless/realtek/rtw88/pci.h1
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822c.c1
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/wow.c107
13 files changed, 182 insertions, 88 deletions
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index 01735776345a..7ddce3c3f0c4 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -1378,6 +1378,8 @@ struct rtl8xxxu_priv {
u8 no_pape:1;
u8 int_buf[USB_INTR_CONTENT_LENGTH];
u8 rssi_level;
+ DECLARE_BITMAP(tx_aggr_started, IEEE80211_NUM_TIDS);
+ DECLARE_BITMAP(tid_tx_operational, IEEE80211_NUM_TIDS);
/*
* Only one virtual interface permitted because only STA mode
* is supported and no iface_combinations are provided.
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index ac1061caacd6..774341b0005a 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -1670,7 +1670,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv)
priv->rf_paths = 2;
priv->rx_paths = 2;
priv->tx_paths = 2;
- priv->usb_interrupts = 1;
+ priv->usb_interrupts = 0;
priv->rtl_chip = RTL8192C;
}
priv->has_wifi = 1;
@@ -1680,7 +1680,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv)
priv->rx_paths = 1;
priv->tx_paths = 1;
priv->rtl_chip = RTL8188C;
- priv->usb_interrupts = 1;
+ priv->usb_interrupts = 0;
priv->has_wifi = 1;
}
@@ -4805,6 +4805,8 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
+ u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
u32 rate;
u16 rate_flags = tx_info->control.rates[0].flags;
u16 seq_number;
@@ -4828,7 +4830,7 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
tx_desc->txdw3 = cpu_to_le32((u32)seq_number << TXDESC32_SEQ_SHIFT);
- if (ampdu_enable)
+ if (ampdu_enable && test_bit(tid, priv->tid_tx_operational))
tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_ENABLE);
else
tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_BREAK);
@@ -4876,6 +4878,8 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
struct rtl8xxxu_txdesc40 *tx_desc40;
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
+ u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
u32 rate;
u16 rate_flags = tx_info->control.rates[0].flags;
u16 seq_number;
@@ -4902,7 +4906,7 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
tx_desc40->txdw9 = cpu_to_le32((u32)seq_number << TXDESC40_SEQ_SHIFT);
- if (ampdu_enable)
+ if (ampdu_enable && test_bit(tid, priv->tid_tx_operational))
tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_ENABLE);
else
tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_BREAK);
@@ -5015,12 +5019,19 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
if (ieee80211_is_data_qos(hdr->frame_control) && sta) {
if (sta->ht_cap.ht_supported) {
u32 ampdu, val32;
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
+ u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
ampdu = (u32)sta->ht_cap.ampdu_density;
val32 = ampdu << TXDESC_AMPDU_DENSITY_SHIFT;
tx_desc->txdw2 |= cpu_to_le32(val32);
ampdu_enable = true;
+
+ if (!test_bit(tid, priv->tx_aggr_started) &&
+ !(skb->protocol == cpu_to_be16(ETH_P_PAE)))
+ if (!ieee80211_start_tx_ba_session(sta, tid, 0))
+ set_bit(tid, priv->tx_aggr_started);
}
}
@@ -6096,6 +6107,7 @@ rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct device *dev = &priv->udev->dev;
u8 ampdu_factor, ampdu_density;
struct ieee80211_sta *sta = params->sta;
+ u16 tid = params->tid;
enum ieee80211_ampdu_mlme_action action = params->action;
switch (action) {
@@ -6108,17 +6120,20 @@ rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
dev_dbg(dev,
"Changed HT: ampdu_factor %02x, ampdu_density %02x\n",
ampdu_factor, ampdu_density);
- break;
+ return IEEE80211_AMPDU_TX_START_IMMEDIATE;
+ case IEEE80211_AMPDU_TX_STOP_CONT:
case IEEE80211_AMPDU_TX_STOP_FLUSH:
- dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH\n", __func__);
- rtl8xxxu_set_ampdu_factor(priv, 0);
- rtl8xxxu_set_ampdu_min_space(priv, 0);
- break;
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
- dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH_CONT\n",
- __func__);
+ dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP\n", __func__);
rtl8xxxu_set_ampdu_factor(priv, 0);
rtl8xxxu_set_ampdu_min_space(priv, 0);
+ clear_bit(tid, priv->tx_aggr_started);
+ clear_bit(tid, priv->tid_tx_operational);
+ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ break;
+ case IEEE80211_AMPDU_TX_OPERATIONAL:
+ dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_OPERATIONAL\n", __func__);
+ set_bit(tid, priv->tid_tx_operational);
break;
case IEEE80211_AMPDU_RX_START:
dev_dbg(dev, "%s: IEEE80211_AMPDU_RX_START\n", __func__);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
index 76dd881ef9bb..9b83c710c9b8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
@@ -160,6 +160,15 @@ static u32 targetchnl_2g[TARGET_CHNL_NUM_2G] = {
25711, 25658, 25606, 25554, 25502, 25451, 25328
};
+static const u8 channel_all[59] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+ 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+ 114, 116, 118, 120, 122, 124, 126, 128, 130,
+ 132, 134, 136, 138, 140, 149, 151, 153, 155,
+ 157, 159, 161, 163, 165
+};
+
static u32 _rtl92d_phy_calculate_bit_shift(u32 bitmask)
{
u32 i = ffs(bitmask);
@@ -681,7 +690,7 @@ static bool _rtl92d_phy_bb_config(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
- bool rtstatus = true;
+ bool rtstatus;
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "==>\n");
rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw,
@@ -1354,15 +1363,7 @@ static void _rtl92d_phy_switch_rf_setting(struct ieee80211_hw *hw, u8 channel)
u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl)
{
- u8 channel_all[59] = {
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
- 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
- 114, 116, 118, 120, 122, 124, 126, 128, 130,
- 132, 134, 136, 138, 140, 149, 151, 153, 155,
- 157, 159, 161, 163, 165
- };
- u8 place = chnl;
+ u8 place;
if (chnl > 14) {
for (place = 14; place < sizeof(channel_all); place++) {
@@ -3220,37 +3221,28 @@ void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw)
u8 rtl92d_get_chnlgroup_fromarray(u8 chnl)
{
u8 group;
- u8 channel_info[59] = {
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56,
- 58, 60, 62, 64, 100, 102, 104, 106, 108,
- 110, 112, 114, 116, 118, 120, 122, 124,
- 126, 128, 130, 132, 134, 136, 138, 140,
- 149, 151, 153, 155, 157, 159, 161, 163,
- 165
- };
- if (channel_info[chnl] <= 3)
+ if (channel_all[chnl] <= 3)
group = 0;
- else if (channel_info[chnl] <= 9)
+ else if (channel_all[chnl] <= 9)
group = 1;
- else if (channel_info[chnl] <= 14)
+ else if (channel_all[chnl] <= 14)
group = 2;
- else if (channel_info[chnl] <= 44)
+ else if (channel_all[chnl] <= 44)
group = 3;
- else if (channel_info[chnl] <= 54)
+ else if (channel_all[chnl] <= 54)
group = 4;
- else if (channel_info[chnl] <= 64)
+ else if (channel_all[chnl] <= 64)
group = 5;
- else if (channel_info[chnl] <= 112)
+ else if (channel_all[chnl] <= 112)
group = 6;
- else if (channel_info[chnl] <= 126)
+ else if (channel_all[chnl] <= 126)
group = 7;
- else if (channel_info[chnl] <= 140)
+ else if (channel_all[chnl] <= 140)
group = 8;
- else if (channel_info[chnl] <= 153)
+ else if (channel_all[chnl] <= 153)
group = 9;
- else if (channel_info[chnl] <= 159)
+ else if (channel_all[chnl] <= 159)
group = 10;
else
group = 11;
diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index c0e4b111c8b4..73d6807a8cdf 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -15,9 +15,9 @@ rtw88_core-y += main.o \
ps.o \
sec.o \
bf.o \
- wow.o \
regd.o
+rtw88_core-$(CONFIG_PM) += wow.o
obj-$(CONFIG_RTW88_8822B) += rtw88_8822b.o
rtw88_8822b-objs := rtw8822b.o rtw8822b_table.o
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 3bfa5ecc0053..e6399519584b 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -819,7 +819,7 @@ static u16 rtw_get_rsvd_page_probe_req_size(struct rtw_dev *rtwdev,
continue;
if ((!ssid && !rsvd_pkt->ssid) ||
rtw_ssid_equal(rsvd_pkt->ssid, ssid))
- size = rsvd_pkt->skb->len;
+ size = rsvd_pkt->probe_req_size;
}
return size;
@@ -1047,6 +1047,8 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
ssid->ssid_len, 0);
else
skb_new = ieee80211_probereq_get(hw, vif->addr, NULL, 0, 0);
+ if (skb_new)
+ rsvd_pkt->probe_req_size = (u16)skb_new->len;
break;
case RSVD_NLO_INFO:
skb_new = rtw_nlo_info_get(hw);
@@ -1643,6 +1645,7 @@ int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
static void __rtw_fw_update_pkt(struct rtw_dev *rtwdev, u8 pkt_id, u16 size,
u8 location)
{
+ struct rtw_chip_info *chip = rtwdev->chip;
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
u16 total_size = H2C_PKT_HDR_SIZE + H2C_PKT_UPDATE_PKT_LEN;
@@ -1653,6 +1656,7 @@ static void __rtw_fw_update_pkt(struct rtw_dev *rtwdev, u8 pkt_id, u16 size,
UPDATE_PKT_SET_LOCATION(h2c_pkt, location);
/* include txdesc size */
+ size += chip->tx_pkt_desc_sz;
UPDATE_PKT_SET_SIZE(h2c_pkt, size);
rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
@@ -1662,7 +1666,7 @@ void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev,
struct cfg80211_ssid *ssid)
{
u8 loc;
- u32 size;
+ u16 size;
loc = rtw_get_rsvd_page_probe_req_location(rtwdev, ssid);
if (!loc) {
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index a8a7162fbe64..64dcde35a021 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -99,7 +99,7 @@ enum rtw_beacon_filter_offload_mode {
BCN_FILTER_OFFLOAD_MODE_2,
BCN_FILTER_OFFLOAD_MODE_3,
- BCN_FILTER_OFFLOAD_MODE_DEFAULT = BCN_FILTER_OFFLOAD_MODE_1,
+ BCN_FILTER_OFFLOAD_MODE_DEFAULT = BCN_FILTER_OFFLOAD_MODE_0,
};
struct rtw_coex_info_req {
@@ -147,6 +147,7 @@ struct rtw_rsvd_page {
u8 page;
bool add_txdesc;
struct cfg80211_ssid *ssid;
+ u16 probe_req_size;
};
enum rtw_keep_alive_pkt_type {
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index c6364837e83b..6bb55e663fc3 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -1338,6 +1338,8 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev,
if (rtw_chip_has_rx_ldpc(rtwdev))
ht_cap->cap |= IEEE80211_HT_CAP_LDPC_CODING;
+ if (rtw_chip_has_tx_stbc(rtwdev))
+ ht_cap->cap |= IEEE80211_HT_CAP_TX_STBC;
if (efuse->hw_cap.bw & BIT(RTW_CHANNEL_WIDTH_40))
ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index e5af375b3dd0..56812127a053 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -1146,6 +1146,7 @@ struct rtw_chip_info {
u8 txgi_factor;
bool is_pwr_by_rate_dec;
bool rx_ldpc;
+ bool tx_stbc;
u8 max_power_index;
u16 fw_fifo_addr[RTW_FW_FIFO_MAX];
@@ -1959,6 +1960,11 @@ static inline bool rtw_chip_has_rx_ldpc(struct rtw_dev *rtwdev)
return rtwdev->chip->rx_ldpc;
}
+static inline bool rtw_chip_has_tx_stbc(struct rtw_dev *rtwdev)
+{
+ return rtwdev->chip->tx_stbc;
+}
+
static inline void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id)
{
clear_bit(mac_id, rtwdev->mac_id_map);
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index e7d17ab8f113..a7a6ebfaa203 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -268,11 +268,6 @@ static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev,
int i, allocated;
int ret = 0;
- if (len > TRX_BD_IDX_MASK) {
- rtw_err(rtwdev, "len %d exceeds maximum RX entries\n", len);
- return -EINVAL;
- }
-
head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL);
if (!head) {
rtw_err(rtwdev, "failed to allocate rx ring\n");
@@ -1359,6 +1354,25 @@ static void rtw_pci_clkreq_set(struct rtw_dev *rtwdev, bool enable)
rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value);
}
+static void rtw_pci_clkreq_pad_low(struct rtw_dev *rtwdev, bool enable)
+{
+ u8 value;
+ int ret;
+
+ ret = rtw_dbi_read8(rtwdev, RTK_PCIE_LINK_CFG, &value);
+ if (ret) {
+ rtw_err(rtwdev, "failed to read CLKREQ_L1, ret=%d", ret);
+ return;
+ }
+
+ if (enable)
+ value &= ~BIT_CLKREQ_N_PAD;
+ else
+ value |= BIT_CLKREQ_N_PAD;
+
+ rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value);
+}
+
static void rtw_pci_aspm_set(struct rtw_dev *rtwdev, bool enable)
{
u8 value;
@@ -1500,11 +1514,25 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev)
static int __maybe_unused rtw_pci_suspend(struct device *dev)
{
+ struct ieee80211_hw *hw = dev_get_drvdata(dev);
+ struct rtw_dev *rtwdev = hw->priv;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+
+ if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6)
+ rtw_pci_clkreq_pad_low(rtwdev, true);
return 0;
}
static int __maybe_unused rtw_pci_resume(struct device *dev)
{
+ struct ieee80211_hw *hw = dev_get_drvdata(dev);
+ struct rtw_dev *rtwdev = hw->priv;
+ struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+
+ if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6)
+ rtw_pci_clkreq_pad_low(rtwdev, false);
return 0;
}
@@ -1701,6 +1729,15 @@ static const struct dmi_system_id rtw88_pci_quirks[] = {
},
.driver_data = (void *)BIT(QUIRK_DIS_PCI_CAP_ASPM),
},
+ {
+ .callback = disable_pci_caps,
+ .ident = "HP HP Pavilion Laptop 14-ce0xxx",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Laptop 14-ce0xxx"),
+ },
+ .driver_data = (void *)BIT(QUIRK_DIS_PCI_CAP_ASPM),
+ },
{}
};
diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h
index 0ffae887527a..66f78eb7757c 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.h
+++ b/drivers/net/wireless/realtek/rtw88/pci.h
@@ -37,6 +37,7 @@
#define RTK_PCIE_LINK_CFG 0x0719
#define BIT_CLKREQ_SW_EN BIT(4)
#define BIT_L1_SW_EN BIT(3)
+#define BIT_CLKREQ_N_PAD BIT(0)
#define RTK_PCIE_CLKDLY_CTRL 0x0725
#define BIT_PCI_BCNQ_FLAG BIT(4)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index 8bf3cd3a3678..f3ad079967a6 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -5288,6 +5288,7 @@ struct rtw_chip_info rtw8822c_hw_spec = {
.bfer_su_max_num = 2,
.bfer_mu_max_num = 1,
.rx_ldpc = true,
+ .tx_stbc = true,
#ifdef CONFIG_PM
.wow_fw_name = "rtw88/rtw8822c_wow_fw.bin",
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index 0193708fc013..3a101aa139ed 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -162,7 +162,7 @@ void rtw_tx_report_purge_timer(struct timer_list *t)
if (skb_queue_len(&tx_report->queue) == 0)
return;
- rtw_dbg(rtwdev, RTW_DBG_TX, "purge skb(s) not reported by firmware\n");
+ rtw_warn(rtwdev, "failed to get tx report from firmware\n");
spin_lock_irqsave(&tx_report->q_lock, flags);
skb_queue_purge(&tx_report->queue);
diff --git a/drivers/net/wireless/realtek/rtw88/wow.c b/drivers/net/wireless/realtek/rtw88/wow.c
index fc9544f4e5e4..89dc595094d5 100644
--- a/drivers/net/wireless/realtek/rtw88/wow.c
+++ b/drivers/net/wireless/realtek/rtw88/wow.c
@@ -12,26 +12,54 @@
static void rtw_wow_show_wakeup_reason(struct rtw_dev *rtwdev)
{
+ struct cfg80211_wowlan_nd_info nd_info;
+ struct cfg80211_wowlan_wakeup wakeup = {
+ .pattern_idx = -1,
+ };
u8 reason;
reason = rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON);
- if (reason == RTW_WOW_RSN_RX_DEAUTH)
+ switch (reason) {
+ case RTW_WOW_RSN_RX_DEAUTH:
+ wakeup.disconnect = true;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx deauth\n");
- else if (reason == RTW_WOW_RSN_DISCONNECT)
+ break;
+ case RTW_WOW_RSN_DISCONNECT:
+ wakeup.disconnect = true;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: AP is off\n");
- else if (reason == RTW_WOW_RSN_RX_MAGIC_PKT)
+ break;
+ case RTW_WOW_RSN_RX_MAGIC_PKT:
+ wakeup.magic_pkt = true;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx magic packet\n");
- else if (reason == RTW_WOW_RSN_RX_GTK_REKEY)
+ break;
+ case RTW_WOW_RSN_RX_GTK_REKEY:
+ wakeup.gtk_rekey_failure = true;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx gtk rekey\n");
- else if (reason == RTW_WOW_RSN_RX_PTK_REKEY)
- rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx ptk rekey\n");
- else if (reason == RTW_WOW_RSN_RX_PATTERN_MATCH)
+ break;
+ case RTW_WOW_RSN_RX_PATTERN_MATCH:
+ /* Current firmware and driver don't report pattern index
+ * Use pattern_idx to 0 defaultly.
+ */
+ wakeup.pattern_idx = 0;
rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx pattern match packet\n");
- else if (reason == RTW_WOW_RSN_RX_NLO)
+ break;
+ case RTW_WOW_RSN_RX_NLO:
+ /* Current firmware and driver don't report ssid index.
+ * Use 0 for n_matches based on its comment.
+ */
+ nd_info.n_matches = 0;
+ wakeup.net_detect = &nd_info;
rtw_dbg(rtwdev, RTW_DBG_WOW, "Rx NLO\n");
- else
+ break;
+ default:
rtw_warn(rtwdev, "Unknown wakeup reason %x\n", reason);
+ ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL,
+ GFP_KERNEL);
+ return;
+ }
+ ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup,
+ GFP_KERNEL);
}
static void rtw_wow_pattern_write_cam(struct rtw_dev *rtwdev, u8 addr,
@@ -283,15 +311,26 @@ static void rtw_wow_rx_dma_start(struct rtw_dev *rtwdev)
static int rtw_wow_check_fw_status(struct rtw_dev *rtwdev, bool wow_enable)
{
- /* wait 100ms for wow firmware to finish work */
- msleep(100);
+ int ret;
+ u8 check;
+ u32 check_dis;
if (wow_enable) {
- if (rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON))
+ ret = read_poll_timeout(rtw_read8, check, !check, 1000,
+ 100000, true, rtwdev,
+ REG_WOWLAN_WAKE_REASON);
+ if (ret)
goto wow_fail;
} else {
- if (rtw_read32_mask(rtwdev, REG_FE1IMR, BIT_FS_RXDONE) ||
- rtw_read32_mask(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE))
+ ret = read_poll_timeout(rtw_read32_mask, check_dis,
+ !check_dis, 1000, 100000, true, rtwdev,
+ REG_FE1IMR, BIT_FS_RXDONE);
+ if (ret)
+ goto wow_fail;
+ ret = read_poll_timeout(rtw_read32_mask, check_dis,
+ !check_dis, 1000, 100000, false, rtwdev,
+ REG_RXPKT_NUM, BIT_RW_RELEASE);
+ if (ret)
goto wow_fail;
}
@@ -432,37 +471,31 @@ static void rtw_wow_fw_media_status(struct rtw_dev *rtwdev, bool connect)
rtw_iterate_stas_atomic(rtwdev, rtw_wow_fw_media_status_iter, &data);
}
-static void rtw_wow_config_pno_rsvd_page(struct rtw_dev *rtwdev,
- struct rtw_vif *rtwvif)
+static int rtw_wow_config_wow_fw_rsvd_page(struct rtw_dev *rtwdev)
{
- rtw_add_rsvd_page_pno(rtwdev, rtwvif);
-}
-
-static void rtw_wow_config_linked_rsvd_page(struct rtw_dev *rtwdev,
- struct rtw_vif *rtwvif)
-{
- rtw_add_rsvd_page_sta(rtwdev, rtwvif);
-}
+ struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+ struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
-static void rtw_wow_config_rsvd_page(struct rtw_dev *rtwdev,
- struct rtw_vif *rtwvif)
-{
rtw_remove_rsvd_page(rtwdev, rtwvif);
- if (rtw_wow_mgd_linked(rtwdev)) {
- rtw_wow_config_linked_rsvd_page(rtwdev, rtwvif);
- } else if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags) &&
- rtw_wow_no_link(rtwdev)) {
- rtw_wow_config_pno_rsvd_page(rtwdev, rtwvif);
- }
+ if (rtw_wow_no_link(rtwdev))
+ rtw_add_rsvd_page_pno(rtwdev, rtwvif);
+ else
+ rtw_add_rsvd_page_sta(rtwdev, rtwvif);
+
+ return rtw_fw_download_rsvd_page(rtwdev);
}
-static int rtw_wow_dl_fw_rsvd_page(struct rtw_dev *rtwdev)
+static int rtw_wow_config_normal_fw_rsvd_page(struct rtw_dev *rtwdev)
{
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
- rtw_wow_config_rsvd_page(rtwdev, rtwvif);
+ rtw_remove_rsvd_page(rtwdev, rtwvif);
+ rtw_add_rsvd_page_sta(rtwdev, rtwvif);
+
+ if (rtw_wow_no_link(rtwdev))
+ return 0;
return rtw_fw_download_rsvd_page(rtwdev);
}
@@ -660,7 +693,7 @@ static int rtw_wow_enable(struct rtw_dev *rtwdev)
set_bit(RTW_FLAG_WOWLAN, rtwdev->flags);
- ret = rtw_wow_dl_fw_rsvd_page(rtwdev);
+ ret = rtw_wow_config_wow_fw_rsvd_page(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to download wowlan rsvd page\n");
goto error;
@@ -733,7 +766,7 @@ static int rtw_wow_disable(struct rtw_dev *rtwdev)
goto out;
}
- ret = rtw_wow_dl_fw_rsvd_page(rtwdev);
+ ret = rtw_wow_config_normal_fw_rsvd_page(rtwdev);
if (ret)
rtw_err(rtwdev, "failed to download normal rsvd page\n");