diff options
Diffstat (limited to 'drivers/net/wireless/realtek')
54 files changed, 2377 insertions, 891 deletions
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c index 2905baea6239..070c0431c482 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c @@ -1023,9 +1023,6 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) dma_addr_t *mapping; entry = priv->rx_ring + priv->rx_ring_sz*i; if (!skb) { - dma_free_coherent(&priv->pdev->dev, - priv->rx_ring_sz * 32, - priv->rx_ring, priv->rx_ring_dma); wiphy_err(dev->wiphy, "Cannot allocate RX skb\n"); return -ENOMEM; } @@ -1037,9 +1034,7 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) if (dma_mapping_error(&priv->pdev->dev, *mapping)) { kfree_skb(skb); - dma_free_coherent(&priv->pdev->dev, - priv->rx_ring_sz * 32, - priv->rx_ring, priv->rx_ring_dma); + priv->rx_buf[i] = NULL; wiphy_err(dev->wiphy, "Cannot map DMA for RX skb\n"); return -ENOMEM; } @@ -1130,7 +1125,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) ret = rtl8180_init_rx_ring(dev); if (ret) - return ret; + goto err_free_rings; for (i = 0; i < (dev->queues + 1); i++) if ((ret = rtl8180_init_tx_ring(dev, i, 16))) diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c index 0c5c66401daa..7aa2da0cd63c 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c @@ -338,14 +338,16 @@ static void rtl8187_rx_cb(struct urb *urb) spin_unlock_irqrestore(&priv->rx_queue.lock, f); skb_put(skb, urb->actual_length); - if (unlikely(urb->status)) { - dev_kfree_skb_irq(skb); - return; - } + if (unlikely(urb->status)) + goto free_skb; if (!priv->is_rtl8187b) { - struct rtl8187_rx_hdr *hdr = - (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); + struct rtl8187_rx_hdr *hdr; + + if (skb->len < sizeof(struct rtl8187_rx_hdr)) + goto free_skb; + + hdr = (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); flags = le32_to_cpu(hdr->flags); /* As with the RTL8187B below, the AGC is used to calculate * signal strength. In this case, the scaling @@ -355,8 +357,12 @@ static void rtl8187_rx_cb(struct urb *urb) rx_status.antenna = (hdr->signal >> 7) & 1; rx_status.mactime = le64_to_cpu(hdr->mac_time); } else { - struct rtl8187b_rx_hdr *hdr = - (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); + struct rtl8187b_rx_hdr *hdr; + + if (skb->len < sizeof(struct rtl8187b_rx_hdr)) + goto free_skb; + + hdr = (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); /* The Realtek datasheet for the RTL8187B shows that the RX * header contains the following quantities: signal quality, * RSSI, AGC, the received power in dB, and the measured SNR. @@ -409,6 +415,11 @@ static void rtl8187_rx_cb(struct urb *urb) skb_unlink(skb, &priv->rx_queue); dev_kfree_skb_irq(skb); } + return; + +free_skb: + dev_kfree_skb_irq(skb); + return; } static int rtl8187_init_urbs(struct ieee80211_hw *dev) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/8192c.c index 73034e7e41d1..444872131c66 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/8192c.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/8192c.c @@ -593,6 +593,84 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) return 0; } +static void rtl8192cu_power_off(struct rtl8xxxu_priv *priv) +{ + u32 val32; + u16 val16; + u8 val8; + int i; + + /* + * Workaround for 8188RU LNA power leakage problem. + */ + if (priv->rtl_chip == RTL8188R) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); + val32 |= BIT(1); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); + } + + /* _DisableRFAFEAndResetBB */ + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_AC, 0xff, 0); + + rtl8xxxu_write8_set(priv, REG_APSD_CTRL, APSD_CTRL_OFF); + rtl8xxxu_write32_set(priv, REG_FPGA0_XCD_RF_PARM, FPGA0_RF_PARM_CLK_GATE); + + rtl8xxxu_write8(priv, REG_SYS_FUNC, + SYS_FUNC_USBA | SYS_FUNC_USBD | SYS_FUNC_BB_GLB_RSTN); + rtl8xxxu_write8(priv, REG_SYS_FUNC, SYS_FUNC_USBA | SYS_FUNC_USBD); + + /* _ResetDigitalProcedure1 */ + if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_DL_READY) { + rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); + + rtl8xxxu_write8(priv, REG_FWIMR, 0x20); + + rtl8xxxu_write8(priv, REG_HMTFR + 3, 0x20); + + for (i = 0; i < 100; i++) { + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + if (!(val16 & SYS_FUNC_CPU_ENABLE)) + break; + + fsleep(50); + } + + if (i == 100) { + rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, + (SYS_FUNC_HWPDN | SYS_FUNC_ELDR) >> 8); + msleep(10); + } + } + + val8 = (SYS_FUNC_HWPDN | SYS_FUNC_ELDR | SYS_FUNC_CPU_ENABLE) >> 8; + rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, val8); + + /* _DisableGPIO */ + rtl8xxxu_write16(priv, REG_GPIO_PIN_CTRL + 2, 0); + val32 = rtl8xxxu_read32(priv, REG_GPIO_PIN_CTRL) & 0xffff00ff; + val32 |= (val32 & 0xff) << 8; + val32 |= 0x00ff0000; + rtl8xxxu_write32(priv, REG_GPIO_PIN_CTRL, val32); + + rtl8xxxu_write8(priv, REG_GPIO_MUXCFG + 3, 0); + val16 = rtl8xxxu_read16(priv, REG_GPIO_MUXCFG + 2) & 0xff0f; + val16 |= (val16 & 0xf) << 4; + val16 |= 0x0780; + rtl8xxxu_write16(priv, REG_GPIO_MUXCFG + 2, val16); + + /* _DisableAnalog */ + val8 = 0x23; + if (priv->vendor_umc && priv->chip_cut == 1) + val8 |= BIT(3); + rtl8xxxu_write8(priv, REG_SPS0_CTRL, val8); + + val16 = APS_FSMCO_HOST | APS_FSMCO_HW_SUSPEND | APS_FSMCO_PFM_ALDN; + rtl8xxxu_write16(priv, REG_APS_FSMCO, val16); + + rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e); +} + static int rtl8192cu_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { @@ -618,7 +696,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = { .parse_efuse = rtl8192cu_parse_efuse, .load_firmware = rtl8192cu_load_firmware, .power_on = rtl8192cu_power_on, - .power_off = rtl8xxxu_power_off, + .power_off = rtl8192cu_power_off, .read_efuse = rtl8xxxu_read_efuse, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8723a.c b/drivers/net/wireless/realtek/rtl8xxxu/8723a.c index ecbc324e4609..4f4493d0bfc2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/8723a.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/8723a.c @@ -411,6 +411,119 @@ exit: return ret; } +static int rtl8723au_active_to_emu(struct rtl8xxxu_priv *priv) +{ + u8 val8; + int count, ret = 0; + + /* Start of rtl8723AU_card_enable_flow */ + /* Act to Cardemu sequence*/ + /* Turn off RF */ + rtl8xxxu_write8(priv, REG_RF_CTRL, 0); + + /* 0x004E[7] = 0, switch DPDT_SEL_P output from register 0x0065[2] */ + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); + val8 &= ~LEDCFG2_DPDT_SELECT; + rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + + /* 0x0005[1] = 1 turn off MAC by HW state machine*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 |= BIT(1); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + if ((val8 & BIT(1)) == 0) + break; + udelay(10); + } + + if (!count) { + dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n", + __func__); + ret = -EBUSY; + goto exit; + } + + /* 0x0000[5] = 1 analog Ips to digital, 1:isolation */ + val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL); + val8 |= SYS_ISO_ANALOG_IPS; + rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8); + + /* 0x0020[0] = 0 disable LDOA12 MACRO block*/ + val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL); + val8 &= ~LDOA15_ENABLE; + rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8); + +exit: + return ret; +} + +static int rtl8723au_emu_to_disabled(struct rtl8xxxu_priv *priv) +{ + u8 val8; + + /* 0x0007[7:0] = 0x20 SOP option to disable BG/MB */ + rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20); + + /* 0x04[12:11] = 01 enable WL suspend */ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~BIT(4); + val8 |= BIT(3); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 |= BIT(7); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* 0x48[16] = 1 to enable GPIO9 as EXT wakeup */ + val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8); + + return 0; +} + +static void rtl8723au_power_off(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + + rtl8xxxu_flush_fifo(priv); + + rtl8xxxu_active_to_lps(priv); + + /* Turn off RF */ + rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00); + + /* Reset Firmware if running in RAM */ + if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL) + rtl8xxxu_firmware_self_reset(priv); + + /* Reset MCU */ + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 &= ~SYS_FUNC_CPU_ENABLE; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + + /* Reset MCU ready status */ + rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); + + rtl8723au_active_to_emu(priv); + rtl8723au_emu_to_disabled(priv); + + /* Reset MCU IO Wrapper */ + val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); + val8 &= ~BIT(0); + rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); + + val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); + + /* RSV_CTRL 0x1C[7:0] = 0x0e lock ISO/CLK/Power control register */ + rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e); +} + #define XTAL1 GENMASK(23, 18) #define XTAL0 GENMASK(17, 12) @@ -492,7 +605,7 @@ struct rtl8xxxu_fileops rtl8723au_fops = { .parse_efuse = rtl8723au_parse_efuse, .load_firmware = rtl8723au_load_firmware, .power_on = rtl8723au_power_on, - .power_off = rtl8xxxu_power_off, + .power_off = rtl8723au_power_off, .read_efuse = rtl8xxxu_read_efuse, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c index 3ded5952729f..c06ad064f37c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c @@ -20,7 +20,6 @@ #define DRIVER_NAME "rtl8xxxu" int rtl8xxxu_debug; -static bool rtl8xxxu_ht40_2g; static bool rtl8xxxu_dma_aggregation; static int rtl8xxxu_dma_agg_timeout = -1; static int rtl8xxxu_dma_agg_pages = -1; @@ -45,8 +44,6 @@ MODULE_FIRMWARE("rtlwifi/rtl8192fufw.bin"); module_param_named(debug, rtl8xxxu_debug, int, 0600); MODULE_PARM_DESC(debug, "Set debug mask"); -module_param_named(ht40_2g, rtl8xxxu_ht40_2g, bool, 0600); -MODULE_PARM_DESC(ht40_2g, "Enable HT40 support on the 2.4GHz band"); module_param_named(dma_aggregation, rtl8xxxu_dma_aggregation, bool, 0600); MODULE_PARM_DESC(dma_aggregation, "Enable DMA packet aggregation"); module_param_named(dma_agg_timeout, rtl8xxxu_dma_agg_timeout, int, 0600); @@ -1252,7 +1249,7 @@ void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw) opmode &= ~BW_OPMODE_20MHZ; rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); rsr &= ~RSR_RSC_BANDWIDTH_40M; - if (sec_ch_above) + if (!sec_ch_above) rsr |= RSR_RSC_UPPER_SUB_CHANNEL; else rsr |= RSR_RSC_LOWER_SUB_CHANNEL; @@ -1321,9 +1318,8 @@ void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw) for (i = RF_A; i < priv->rf_paths; i++) { val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG); - if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40) - val32 &= ~MODE_AG_CHANNEL_20MHZ; - else + val32 &= ~MODE_AG_BW_MASK; + if (hw->conf.chandef.width != NL80211_CHAN_WIDTH_40) val32 |= MODE_AG_CHANNEL_20MHZ; rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32); } @@ -1374,9 +1370,11 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw) hw->conf.chandef.chan->center_freq) { sec_ch_above = 1; channel += 2; + subchannel = 2; } else { sec_ch_above = 0; channel -= 2; + subchannel = 1; } val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); @@ -3637,54 +3635,6 @@ static void rtl8xxxu_set_ampdu_min_space(struct rtl8xxxu_priv *priv, u8 density) rtl8xxxu_write8(priv, REG_AMPDU_MIN_SPACE, val8); } -static int rtl8xxxu_active_to_emu(struct rtl8xxxu_priv *priv) -{ - u8 val8; - int count, ret = 0; - - /* Start of rtl8723AU_card_enable_flow */ - /* Act to Cardemu sequence*/ - /* Turn off RF */ - rtl8xxxu_write8(priv, REG_RF_CTRL, 0); - - /* 0x004E[7] = 0, switch DPDT_SEL_P output from register 0x0065[2] */ - val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); - val8 &= ~LEDCFG2_DPDT_SELECT; - rtl8xxxu_write8(priv, REG_LEDCFG2, val8); - - /* 0x0005[1] = 1 turn off MAC by HW state machine*/ - val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); - val8 |= BIT(1); - rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); - - for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { - val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); - if ((val8 & BIT(1)) == 0) - break; - udelay(10); - } - - if (!count) { - dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n", - __func__); - ret = -EBUSY; - goto exit; - } - - /* 0x0000[5] = 1 analog Ips to digital, 1:isolation */ - val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL); - val8 |= SYS_ISO_ANALOG_IPS; - rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8); - - /* 0x0020[0] = 0 disable LDOA12 MACRO block*/ - val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL); - val8 &= ~LDOA15_ENABLE; - rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8); - -exit: - return ret; -} - int rtl8xxxu_active_to_lps(struct rtl8xxxu_priv *priv) { u8 val8; @@ -3761,31 +3711,6 @@ void rtl8xxxu_disabled_to_emu(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); } -static int rtl8xxxu_emu_to_disabled(struct rtl8xxxu_priv *priv) -{ - u8 val8; - - /* 0x0007[7:0] = 0x20 SOP option to disable BG/MB */ - rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20); - - /* 0x04[12:11] = 01 enable WL suspend */ - val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); - val8 &= ~BIT(4); - val8 |= BIT(3); - rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); - - val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); - val8 |= BIT(7); - rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); - - /* 0x48[16] = 1 to enable GPIO9 as EXT wakeup */ - val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); - val8 |= BIT(0); - rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8); - - return 0; -} - int rtl8xxxu_flush_fifo(struct rtl8xxxu_priv *priv) { struct device *dev = &priv->udev->dev; @@ -3863,56 +3788,6 @@ void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); } -void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv) -{ - u8 val8; - u16 val16; - u32 val32; - - /* - * Workaround for 8188RU LNA power leakage problem. - */ - if (priv->rtl_chip == RTL8188R) { - val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); - val32 |= BIT(1); - rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); - } - - rtl8xxxu_flush_fifo(priv); - - rtl8xxxu_active_to_lps(priv); - - /* Turn off RF */ - rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00); - - /* Reset Firmware if running in RAM */ - if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL) - rtl8xxxu_firmware_self_reset(priv); - - /* Reset MCU */ - val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); - val16 &= ~SYS_FUNC_CPU_ENABLE; - rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - - /* Reset MCU ready status */ - rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); - - rtl8xxxu_active_to_emu(priv); - rtl8xxxu_emu_to_disabled(priv); - - /* Reset MCU IO Wrapper */ - val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); - val8 &= ~BIT(0); - rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); - - val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); - val8 |= BIT(0); - rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); - - /* RSV_CTRL 0x1C[7:0] = 0x0e lock ISO/CLK/Power control register */ - rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e); -} - void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv, u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5) { @@ -5018,8 +4893,7 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, sgi = 1; highest_rate = fls(ramask) - 1; - if (rtl8xxxu_ht40_2g && - (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) bw = RATE_INFO_BW_40; else bw = RATE_INFO_BW_20; @@ -5345,9 +5219,19 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, tx_desc->txdw5 |= cpu_to_le32(TXDESC32_RETRY_LIMIT_ENABLE); } - if (ieee80211_is_data_qos(hdr->frame_control)) + if (ieee80211_is_data_qos(hdr->frame_control)) { tx_desc->txdw4 |= cpu_to_le32(TXDESC32_QOS); + if (conf_is_ht40(&hw->conf)) { + tx_desc->txdw4 |= cpu_to_le32(TXDESC_DATA_BW); + + if (conf_is_ht40_minus(&hw->conf)) + tx_desc->txdw4 |= cpu_to_le32(TXDESC_PRIME_CH_OFF_UPPER); + else + tx_desc->txdw4 |= cpu_to_le32(TXDESC_PRIME_CH_OFF_LOWER); + } + } + if (short_preamble) tx_desc->txdw4 |= cpu_to_le32(TXDESC32_SHORT_PREAMBLE); @@ -5813,7 +5697,7 @@ static void jaguar2_rx_parse_phystats_type1(struct rtl8xxxu_priv *priv, !rtl8xxxu_is_sta_sta(priv) && (rtl8xxxu_is_packet_match_bssid(priv, hdr, 0) || rtl8xxxu_is_packet_match_bssid(priv, hdr, 1)); - u8 pwdb_max = 0; + u8 pwdb_max = 0, rxsc; int rx_path; if (parse_cfo) { @@ -5828,6 +5712,16 @@ static void jaguar2_rx_parse_phystats_type1(struct rtl8xxxu_priv *priv, pwdb_max = max(pwdb_max, phy_stats1->pwdb[rx_path]); rx_status->signal = pwdb_max - 110; + + if (rxmcs >= DESC_RATE_6M && rxmcs <= DESC_RATE_54M) + rxsc = phy_stats1->l_rxsc; + else + rxsc = phy_stats1->ht_rxsc; + + if (phy_stats1->rf_mode == 0 || rxsc == 1 || rxsc == 2) + rx_status->bw = RATE_INFO_BW_20; + else + rx_status->bw = RATE_INFO_BW_40; } static void jaguar2_rx_parse_phystats_type2(struct rtl8xxxu_priv *priv, @@ -6454,6 +6348,8 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) rtl8xxxu_rx_update_rssi(priv, rx_status, hdr); + } else { + rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; } rx_status->mactime = rx_desc->tsfl; @@ -6560,6 +6456,8 @@ int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb) rtl8xxxu_rx_update_rssi(priv, rx_status, hdr); + } else { + rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; } rx_status->mactime = rx_desc->tsfl; @@ -7906,15 +7804,15 @@ static int rtl8xxxu_probe(struct usb_interface *interface, goto err_set_intfdata; } + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) + rtl8xxxu_dump_efuse(priv); + ret = priv->fops->parse_efuse(priv); if (ret) { dev_err(&udev->dev, "Fatal - failed to parse EFuse\n"); goto err_set_intfdata; } - if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) - rtl8xxxu_dump_efuse(priv); - rtl8xxxu_print_chipinfo(priv); ret = priv->fops->load_firmware(priv); @@ -7949,7 +7847,8 @@ 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; + sband->ht_cap.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_SUP_WIDTH_20_40; 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; @@ -7958,15 +7857,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface, sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; } sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - /* - * Some APs will negotiate HT20_40 in a noisy environment leading - * to miserable performance. Rather than defaulting to this, only - * enable it if explicitly requested at module load time. - */ - if (rtl8xxxu_ht40_2g) { - dev_info(&udev->dev, "Enabling HT_20_40 on the 2.4GHz band\n"); - sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - } + hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; hw->wiphy->rts_threshold = 2347; @@ -8136,6 +8027,9 @@ static const struct usb_device_id dev_table[] = { /* TP-Link TL-WN823N V2 */ {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0135, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192fu_fops}, +/* D-Link AN3U rev. A1 */ +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3328, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, #ifdef CONFIG_RTL8XXXU_UNTESTED /* Still supported by rtlwifi */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/regs.h b/drivers/net/wireless/realtek/rtl8xxxu/regs.h index 61c0c0ec07b3..0741db8d08bf 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/regs.h @@ -40,6 +40,7 @@ #define APS_FSMCO_SW_LPS BIT(10) #define APS_FSMCO_HW_SUSPEND BIT(11) #define APS_FSMCO_PCIE BIT(12) +#define APS_FSMCO_HOST BIT(14) #define APS_FSMCO_HW_POWERDOWN BIT(15) #define APS_FSMCO_WLON_RESET BIT(16) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index f42463e595cc..9fb2583ffffc 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -2078,7 +2078,6 @@ int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, const struct rtl8xxxu_reg32val *array); int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, const char *fw_name); void rtl8xxxu_firmware_self_reset(struct rtl8xxxu_priv *priv); -void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv); void rtl8xxxu_identify_vendor_1bit(struct rtl8xxxu_priv *priv, u32 vendor); void rtl8xxxu_identify_vendor_2bits(struct rtl8xxxu_priv *priv, u32 vendor); void rtl8xxxu_config_endpoints_sie(struct rtl8xxxu_priv *priv); diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index e26feb8de658..09e5a16d7252 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -445,7 +445,7 @@ static int _rtl_init_deferred_work(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct workqueue_struct *wq; - wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name); + wq = alloc_workqueue("%s", WQ_UNBOUND, 0, rtlpriv->cfg->name); if (!wq) return -ENOMEM; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c index 7252bc621211..9a9f9e14f472 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c @@ -694,7 +694,7 @@ void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { p2p_ps_offload->role = 1; - p2p_ps_offload->allstasleep = -1; + p2p_ps_offload->allstasleep = 0; } else { p2p_ps_offload->role = 0; } diff --git a/drivers/net/wireless/realtek/rtw88/bf.c b/drivers/net/wireless/realtek/rtw88/bf.c index c827c4a2814b..0d0ccbc7d00c 100644 --- a/drivers/net/wireless/realtek/rtw88/bf.c +++ b/drivers/net/wireless/realtek/rtw88/bf.c @@ -124,8 +124,11 @@ void rtw_bf_init_bfer_entry_mu(struct rtw_dev *rtwdev, void rtw_bf_cfg_sounding(struct rtw_dev *rtwdev, struct rtw_vif *vif, enum rtw_trx_desc_rate rate) { + u8 csi_rsc = CSI_RSC_FOLLOW_RX_PACKET_BW; u32 psf_ctl = 0; - u8 csi_rsc = 0x1; + + if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) + csi_rsc = CSI_RSC_PRIMARY_20M_BW; psf_ctl = rtw_read32(rtwdev, REG_BBPSF_CTRL) | BIT_WMAC_USE_NDPARATE | @@ -387,6 +390,9 @@ void rtw_bf_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate, csi_cfg = rtw_read32(rtwdev, REG_BBPSF_CTRL) & ~BIT_MASK_CSI_RATE; cur_rrsr = rtw_read16(rtwdev, REG_RRSR); + if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) + csi_cfg |= BIT_CSI_FORCE_RATE; + if (rssi >= 40) { if (cur_rate != DESC_RATE54M) { cur_rrsr |= BIT(DESC_RATE54M); diff --git a/drivers/net/wireless/realtek/rtw88/bf.h b/drivers/net/wireless/realtek/rtw88/bf.h index 7b40c2c03856..a5d3010e6be6 100644 --- a/drivers/net/wireless/realtek/rtw88/bf.h +++ b/drivers/net/wireless/realtek/rtw88/bf.h @@ -33,6 +33,7 @@ #define BIT_SHIFT_R_MU_RL 12 #define BIT_SHIFT_WMAC_TXMU_ACKPOLICY 4 #define BIT_SHIFT_CSI_RATE 24 +#define BIT_CSI_FORCE_RATE BIT(15) #define BIT_MASK_R_MU_RL (R_MU_RL << BIT_SHIFT_R_MU_RL) #define BIT_MASK_R_MU_TABLE_VALID 0x3f @@ -48,6 +49,12 @@ #define RTW_SND_CTRL_REMOVE 0x98 #define RTW_SND_CTRL_SOUNDING 0x9B +enum csi_rsc { + CSI_RSC_PRIMARY_20M_BW = 0, + CSI_RSC_FOLLOW_RX_PACKET_BW = 1, + CSI_RSC_DUPLICATE_MODE = 2, +}; + enum csi_seg_len { HAL_CSI_SEG_4K = 0, HAL_CSI_SEG_8K = 1, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c index 44e28e583964..2769b86ce1b2 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c @@ -79,6 +79,8 @@ static const struct usb_device_id rtw_8822bu_id_table[] = { .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* D-Link DWA-T185 rev. A1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x03d1, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* BUFFALO WI-U2-866DM */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x03d0, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* BUFFALO WI-U3-866DHP */ {}, }; MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822cu.c b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c index 324fd5c8bfd4..755f76840b12 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822cu.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c @@ -21,6 +21,8 @@ static const struct usb_device_id rtw_8822cu_id_table[] = { .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, /* Alpha - Alpha */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3329, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, /* D-Link AC13U rev. A1 */ {}, }; MODULE_DEVICE_TABLE(usb, rtw_8822cu_id_table); diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 3b5126ffc81a..009202c627d2 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -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_UNBOUND, + 0); if (!rtwusb->rxwq) { rtw_err(rtwdev, "failed to create RX work queue\n"); return -ENOMEM; diff --git a/drivers/net/wireless/realtek/rtw89/Kconfig b/drivers/net/wireless/realtek/rtw89/Kconfig index 4288c30b400a..44d8a7f32bf2 100644 --- a/drivers/net/wireless/realtek/rtw89/Kconfig +++ b/drivers/net/wireless/realtek/rtw89/Kconfig @@ -74,6 +74,17 @@ config RTW89_8852AE 802.11ax PCIe wireless network (Wi-Fi 6) adapter +config RTW89_8852AU + tristate "Realtek 8852AU USB wireless network (Wi-Fi 6) adapter" + depends on USB + select RTW89_CORE + select RTW89_USB + select RTW89_8852A + help + Select this option will enable support for 8852AU chipset + + 802.11ax USB wireless network (Wi-Fi 6) adapter + config RTW89_8852BE tristate "Realtek 8852BE PCI wireless network (Wi-Fi 6) adapter" depends on PCI @@ -121,6 +132,17 @@ config RTW89_8852CE 802.11ax PCIe wireless network (Wi-Fi 6E) adapter +config RTW89_8852CU + tristate "Realtek 8852CU USB wireless network (Wi-Fi 6E) adapter" + depends on USB + select RTW89_CORE + select RTW89_USB + select RTW89_8852C + help + Select this option will enable support for 8852CU chipset + + 802.11ax USB wireless network (Wi-Fi 6E) adapter + config RTW89_8922AE tristate "Realtek 8922AE/8922AE-VS PCI wireless network (Wi-Fi 7) adapter" depends on PCI diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile index 23e43c444f69..1be81f254fca 100644 --- a/drivers/net/wireless/realtek/rtw89/Makefile +++ b/drivers/net/wireless/realtek/rtw89/Makefile @@ -43,6 +43,9 @@ rtw89_8852a-objs := rtw8852a.o \ obj-$(CONFIG_RTW89_8852AE) += rtw89_8852ae.o rtw89_8852ae-objs := rtw8852ae.o +obj-$(CONFIG_RTW89_8852AU) += rtw89_8852au.o +rtw89_8852au-objs := rtw8852au.o + obj-$(CONFIG_RTW89_8852B_COMMON) += rtw89_8852b_common.o rtw89_8852b_common-objs := rtw8852b_common.o @@ -75,6 +78,9 @@ rtw89_8852c-objs := rtw8852c.o \ obj-$(CONFIG_RTW89_8852CE) += rtw89_8852ce.o rtw89_8852ce-objs := rtw8852ce.o +obj-$(CONFIG_RTW89_8852CU) += rtw89_8852cu.o +rtw89_8852cu-objs := rtw8852cu.o + obj-$(CONFIG_RTW89_8922A) += rtw89_8922a.o rtw89_8922a-objs := rtw8922a.o \ rtw8922a_rfk.o diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c index 385a238fe5cc..9370cbda945c 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.c +++ b/drivers/net/wireless/realtek/rtw89/cam.c @@ -236,7 +236,8 @@ static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, if (ret) rtw89_err(rtwdev, "failed to update dctl cam del key: %d\n", ret); - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_INFO_CHANGE); if (ret) rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret); } @@ -276,7 +277,8 @@ static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, ret); return ret; } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_INFO_CHANGE); if (ret) { rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n", ret); @@ -760,7 +762,8 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, u8 *cmd) + struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_addr_cam_v0 *h2c) { struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, rtwsta_link); @@ -780,20 +783,19 @@ int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, rcu_read_unlock(); - FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx); - FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset); - FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len); - FWCMD_SET_ADDR_BSSID_VALID(cmd, bssid_cam->valid); - FWCMD_SET_ADDR_BSSID_MASK(cmd, bss_mask); - FWCMD_SET_ADDR_BSSID_BB_SEL(cmd, bssid_cam->phy_idx); - FWCMD_SET_ADDR_BSSID_BSS_COLOR(cmd, bss_color); - - FWCMD_SET_ADDR_BSSID_BSSID0(cmd, bssid_cam->bssid[0]); - FWCMD_SET_ADDR_BSSID_BSSID1(cmd, bssid_cam->bssid[1]); - FWCMD_SET_ADDR_BSSID_BSSID2(cmd, bssid_cam->bssid[2]); - FWCMD_SET_ADDR_BSSID_BSSID3(cmd, bssid_cam->bssid[3]); - FWCMD_SET_ADDR_BSSID_BSSID4(cmd, bssid_cam->bssid[4]); - FWCMD_SET_ADDR_BSSID_BSSID5(cmd, bssid_cam->bssid[5]); + h2c->w12 = le32_encode_bits(bssid_cam->bssid_cam_idx, ADDR_CAM_W12_BSSID_IDX) | + le32_encode_bits(bssid_cam->offset, ADDR_CAM_W12_BSSID_OFFSET) | + le32_encode_bits(bssid_cam->len, ADDR_CAM_W12_BSSID_LEN); + h2c->w13 = le32_encode_bits(bssid_cam->valid, ADDR_CAM_W13_BSSID_VALID) | + le32_encode_bits(bss_mask, ADDR_CAM_W13_BSSID_MASK) | + le32_encode_bits(bssid_cam->phy_idx, ADDR_CAM_W13_BSSID_BB_SEL) | + le32_encode_bits(bss_color, ADDR_CAM_W13_BSSID_BSS_COLOR) | + le32_encode_bits(bssid_cam->bssid[0], ADDR_CAM_W13_BSSID_BSSID0) | + le32_encode_bits(bssid_cam->bssid[1], ADDR_CAM_W13_BSSID_BSSID1); + h2c->w14 = le32_encode_bits(bssid_cam->bssid[2], ADDR_CAM_W14_BSSID_BSSID2) | + le32_encode_bits(bssid_cam->bssid[3], ADDR_CAM_W14_BSSID_BSSID3) | + le32_encode_bits(bssid_cam->bssid[4], ADDR_CAM_W14_BSSID_BSSID4) | + le32_encode_bits(bssid_cam->bssid[5], ADDR_CAM_W14_BSSID_BSSID5); return 0; } @@ -813,18 +815,21 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, - u8 *cmd) + struct rtw89_h2c_addr_cam_v0 *h2c) { 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_link_to_sta_safe(rtwsta_link); + const struct rtw89_chip_info *chip = rtwdev->chip; 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; + u8 ver = chip->addrcam_ver; u8 sma_start = 0; u8 tma_start = 0; const u8 *tma; + u8 mac_id; rcu_read_lock(); @@ -845,69 +850,79 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, sma_hash = rtw89_cam_addr_hash(sma_start, sma); tma_hash = rtw89_cam_addr_hash(tma_start, tma); - FWCMD_SET_ADDR_IDX(cmd, addr_cam->addr_cam_idx); - FWCMD_SET_ADDR_OFFSET(cmd, addr_cam->offset); - FWCMD_SET_ADDR_LEN(cmd, addr_cam->len); - - FWCMD_SET_ADDR_VALID(cmd, addr_cam->valid); - FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif_link->net_type); - FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif_link->bcn_hit_cond); - FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif_link->hit_rule); - FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif_link->phy_idx); - FWCMD_SET_ADDR_ADDR_MASK(cmd, addr_cam->addr_mask); - FWCMD_SET_ADDR_MASK_SEL(cmd, addr_cam->mask_sel); - FWCMD_SET_ADDR_SMA_HASH(cmd, sma_hash); - FWCMD_SET_ADDR_TMA_HASH(cmd, tma_hash); - - FWCMD_SET_ADDR_BSSID_CAM_IDX(cmd, addr_cam->bssid_cam_idx); - - FWCMD_SET_ADDR_SMA0(cmd, sma[0]); - FWCMD_SET_ADDR_SMA1(cmd, sma[1]); - FWCMD_SET_ADDR_SMA2(cmd, sma[2]); - FWCMD_SET_ADDR_SMA3(cmd, sma[3]); - FWCMD_SET_ADDR_SMA4(cmd, sma[4]); - FWCMD_SET_ADDR_SMA5(cmd, sma[5]); - - FWCMD_SET_ADDR_TMA0(cmd, tma[0]); - FWCMD_SET_ADDR_TMA1(cmd, tma[1]); - FWCMD_SET_ADDR_TMA2(cmd, tma[2]); - FWCMD_SET_ADDR_TMA3(cmd, tma[3]); - FWCMD_SET_ADDR_TMA4(cmd, tma[4]); - FWCMD_SET_ADDR_TMA5(cmd, tma[5]); - - FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif_link->port); - FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif_link->port); - FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif_link->trigger); - FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif_link->lsig_txop); - FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif_link->tgt_ind); - FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif_link->frm_tgt_ind); - FWCMD_SET_ADDR_MACID(cmd, rtwsta_link ? rtwsta_link->mac_id : - rtwvif_link->mac_id); + mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + + if (ver == 0) + h2c->w1 = le32_encode_bits(addr_cam->addr_cam_idx, ADDR_CAM_W1_IDX) | + le32_encode_bits(addr_cam->offset, ADDR_CAM_W1_OFFSET) | + le32_encode_bits(addr_cam->len, ADDR_CAM_W1_LEN); + else + h2c->w1 = le32_encode_bits(addr_cam->addr_cam_idx, ADDR_CAM_W1_V1_IDX) | + le32_encode_bits(addr_cam->offset, ADDR_CAM_W1_V1_OFFSET) | + le32_encode_bits(addr_cam->len, ADDR_CAM_W1_V1_LEN); + + h2c->w2 = le32_encode_bits(addr_cam->valid, ADDR_CAM_W2_VALID) | + le32_encode_bits(rtwvif_link->net_type, ADDR_CAM_W2_NET_TYPE) | + le32_encode_bits(rtwvif_link->bcn_hit_cond, ADDR_CAM_W2_BCN_HIT_COND) | + le32_encode_bits(rtwvif_link->hit_rule, ADDR_CAM_W2_HIT_RULE) | + le32_encode_bits(rtwvif_link->phy_idx, ADDR_CAM_W2_BB_SEL) | + le32_encode_bits(addr_cam->addr_mask, ADDR_CAM_W2_ADDR_MASK) | + le32_encode_bits(addr_cam->mask_sel, ADDR_CAM_W2_MASK_SEL) | + le32_encode_bits(sma_hash, ADDR_CAM_W2_SMA_HASH) | + le32_encode_bits(tma_hash, ADDR_CAM_W2_TMA_HASH); + h2c->w3 = le32_encode_bits(addr_cam->bssid_cam_idx, ADDR_CAM_W3_BSSID_CAM_IDX); + h2c->w4 = le32_encode_bits(sma[0], ADDR_CAM_W4_SMA0) | + le32_encode_bits(sma[1], ADDR_CAM_W4_SMA1) | + le32_encode_bits(sma[2], ADDR_CAM_W4_SMA2) | + le32_encode_bits(sma[3], ADDR_CAM_W4_SMA3); + h2c->w5 = le32_encode_bits(sma[4], ADDR_CAM_W5_SMA4) | + le32_encode_bits(sma[5], ADDR_CAM_W5_SMA5) | + le32_encode_bits(tma[0], ADDR_CAM_W5_TMA0) | + le32_encode_bits(tma[1], ADDR_CAM_W5_TMA1); + h2c->w6 = le32_encode_bits(tma[2], ADDR_CAM_W6_TMA2) | + le32_encode_bits(tma[3], ADDR_CAM_W6_TMA3) | + le32_encode_bits(tma[4], ADDR_CAM_W6_TMA4) | + le32_encode_bits(tma[5], ADDR_CAM_W6_TMA5); + if (ver == 0) + h2c->w8 = le32_encode_bits(rtwvif_link->port, ADDR_CAM_W8_PORT_INT) | + le32_encode_bits(rtwvif_link->port, ADDR_CAM_W8_TSF_SYNC) | + le32_encode_bits(rtwvif_link->trigger, ADDR_CAM_W8_TF_TRS) | + le32_encode_bits(rtwvif_link->lsig_txop, ADDR_CAM_W8_LSIG_TXOP) | + le32_encode_bits(rtwvif_link->tgt_ind, ADDR_CAM_W8_TGT_IND) | + le32_encode_bits(rtwvif_link->frm_tgt_ind, ADDR_CAM_W8_FRM_TGT_IND) | + le32_encode_bits(mac_id, ADDR_CAM_W8_MACID); + else + h2c->w8 = le32_encode_bits(rtwvif_link->port, ADDR_CAM_W8_V1_PORT_INT) | + le32_encode_bits(rtwvif_link->port, ADDR_CAM_W8_V1_TSF_SYNC) | + le32_encode_bits(rtwvif_link->trigger, ADDR_CAM_W8_V1_TF_TRS) | + le32_encode_bits(rtwvif_link->lsig_txop, ADDR_CAM_W8_V1_LSIG_TXOP) | + le32_encode_bits(mac_id, ADDR_CAM_W8_V1_MACID); + if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA) - FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff); + h2c->w9 = le32_encode_bits(vif->cfg.aid & 0xfff, ADDR_CAM_W9_AID12); else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) - FWCMD_SET_ADDR_AID12(cmd, sta ? sta->aid & 0xfff : 0); - FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif_link->wowlan_pattern); - FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif_link->wowlan_uc); - FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif_link->wowlan_magic); - FWCMD_SET_ADDR_WAPI(cmd, addr_cam->wapi); - FWCMD_SET_ADDR_SEC_ENT_MODE(cmd, addr_cam->sec_ent_mode); - FWCMD_SET_ADDR_SEC_ENT0_KEYID(cmd, addr_cam->sec_ent_keyid[0]); - FWCMD_SET_ADDR_SEC_ENT1_KEYID(cmd, addr_cam->sec_ent_keyid[1]); - FWCMD_SET_ADDR_SEC_ENT2_KEYID(cmd, addr_cam->sec_ent_keyid[2]); - FWCMD_SET_ADDR_SEC_ENT3_KEYID(cmd, addr_cam->sec_ent_keyid[3]); - FWCMD_SET_ADDR_SEC_ENT4_KEYID(cmd, addr_cam->sec_ent_keyid[4]); - FWCMD_SET_ADDR_SEC_ENT5_KEYID(cmd, addr_cam->sec_ent_keyid[5]); - FWCMD_SET_ADDR_SEC_ENT6_KEYID(cmd, addr_cam->sec_ent_keyid[6]); - - FWCMD_SET_ADDR_SEC_ENT_VALID(cmd, addr_cam->sec_cam_map[0] & 0xff); - FWCMD_SET_ADDR_SEC_ENT0(cmd, addr_cam->sec_ent[0]); - FWCMD_SET_ADDR_SEC_ENT1(cmd, addr_cam->sec_ent[1]); - FWCMD_SET_ADDR_SEC_ENT2(cmd, addr_cam->sec_ent[2]); - FWCMD_SET_ADDR_SEC_ENT3(cmd, addr_cam->sec_ent[3]); - FWCMD_SET_ADDR_SEC_ENT4(cmd, addr_cam->sec_ent[4]); - FWCMD_SET_ADDR_SEC_ENT5(cmd, addr_cam->sec_ent[5]); - FWCMD_SET_ADDR_SEC_ENT6(cmd, addr_cam->sec_ent[6]); + h2c->w9 = le32_encode_bits(sta ? sta->aid & 0xfff : 0, ADDR_CAM_W9_AID12); + + h2c->w9 |= le32_encode_bits(rtwvif_link->wowlan_pattern, ADDR_CAM_W9_WOL_PATTERN) | + le32_encode_bits(rtwvif_link->wowlan_uc, ADDR_CAM_W9_WOL_UC) | + le32_encode_bits(rtwvif_link->wowlan_magic, ADDR_CAM_W9_WOL_MAGIC) | + le32_encode_bits(addr_cam->wapi, ADDR_CAM_W9_WAPI) | + le32_encode_bits(addr_cam->sec_ent_mode, ADDR_CAM_W9_SEC_ENT_MODE) | + le32_encode_bits(addr_cam->sec_ent_keyid[0], ADDR_CAM_W9_SEC_ENT0_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[1], ADDR_CAM_W9_SEC_ENT1_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[2], ADDR_CAM_W9_SEC_ENT2_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[3], ADDR_CAM_W9_SEC_ENT3_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[4], ADDR_CAM_W9_SEC_ENT4_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[5], ADDR_CAM_W9_SEC_ENT5_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[6], ADDR_CAM_W9_SEC_ENT6_KEYID); + h2c->w10 = le32_encode_bits(addr_cam->sec_cam_map[0] & 0xff, ADDR_CAM_W10_SEC_ENT_VALID) | + le32_encode_bits(addr_cam->sec_ent[0], ADDR_CAM_W10_SEC_ENT0) | + le32_encode_bits(addr_cam->sec_ent[1], ADDR_CAM_W10_SEC_ENT1) | + le32_encode_bits(addr_cam->sec_ent[2], ADDR_CAM_W10_SEC_ENT2); + h2c->w11 = le32_encode_bits(addr_cam->sec_ent[3], ADDR_CAM_W11_SEC_ENT3) | + le32_encode_bits(addr_cam->sec_ent[4], ADDR_CAM_W11_SEC_ENT4) | + le32_encode_bits(addr_cam->sec_ent[5], ADDR_CAM_W11_SEC_ENT5) | + le32_encode_bits(addr_cam->sec_ent[6], ADDR_CAM_W11_SEC_ENT6); rcu_read_unlock(); } diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h index 8fd2d776408e..c46b6f91bbdb 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.h +++ b/drivers/net/wireless/realtek/rtw89/cam.h @@ -12,345 +12,109 @@ #define RTW89_BSSID_MATCH_ALL GENMASK(5, 0) #define RTW89_BSSID_MATCH_5_BYTES GENMASK(4, 0) -static inline void FWCMD_SET_ADDR_IDX(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 1, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_OFFSET(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 1, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_LEN(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 1, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_VALID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, BIT(0)); -} - -static inline void FWCMD_SET_ADDR_NET_TYPE(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(2, 1)); -} - -static inline void FWCMD_SET_ADDR_BCN_HIT_COND(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(4, 3)); -} - -static inline void FWCMD_SET_ADDR_HIT_RULE(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(6, 5)); -} - -static inline void FWCMD_SET_ADDR_BB_SEL(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, BIT(7)); -} - -static inline void FWCMD_SET_ADDR_ADDR_MASK(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(13, 8)); -} - -static inline void FWCMD_SET_ADDR_MASK_SEL(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(15, 14)); -} - -static inline void FWCMD_SET_ADDR_SMA_HASH(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_TMA_HASH(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_BSSID_CAM_IDX(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 3, value, GENMASK(5, 0)); -} - -static inline void FWCMD_SET_ADDR_SMA0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 4, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_SMA1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 4, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_SMA2(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 4, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_SMA3(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 4, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_SMA4(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 5, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_SMA5(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 5, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_TMA0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 5, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_TMA1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 5, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_TMA2(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 6, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_TMA3(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 6, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_TMA4(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 6, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_TMA5(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 6, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_MACID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_PORT_INT(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(10, 8)); -} - -static inline void FWCMD_SET_ADDR_TSF_SYNC(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(13, 11)); -} - -static inline void FWCMD_SET_ADDR_TF_TRS(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, BIT(14)); -} - -static inline void FWCMD_SET_ADDR_LSIG_TXOP(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, BIT(15)); -} - -static inline void FWCMD_SET_ADDR_TGT_IND(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(26, 24)); -} - -static inline void FWCMD_SET_ADDR_FRM_TGT_IND(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(29, 27)); -} - -static inline void FWCMD_SET_ADDR_AID12(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(11, 0)); -} - -static inline void FWCMD_SET_ADDR_AID12_0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_AID12_1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(11, 8)); -} - -static inline void FWCMD_SET_ADDR_WOL_PATTERN(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, BIT(12)); -} - -static inline void FWCMD_SET_ADDR_WOL_UC(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, BIT(13)); -} - -static inline void FWCMD_SET_ADDR_WOL_MAGIC(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, BIT(14)); -} - -static inline void FWCMD_SET_ADDR_WAPI(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, BIT(15)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT_MODE(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(17, 16)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT0_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(19, 18)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT1_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(21, 20)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT2_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(23, 22)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT3_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(25, 24)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT4_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(27, 26)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT5_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(29, 28)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT6_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(31, 30)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT_VALID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 10, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 10, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 10, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT2(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 10, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT3(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 11, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT4(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 11, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT5(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 11, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT6(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 11, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_BSSID_IDX(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 12, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_BSSID_OFFSET(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 12, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_BSSID_LEN(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 12, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_BSSID_VALID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, BIT(0)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BB_SEL(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, BIT(1)); -} - -static inline void FWCMD_SET_ADDR_BSSID_MASK(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(7, 2)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSS_COLOR(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(13, 8)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSSID0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSSID1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSSID2(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 14, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSSID3(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 14, value, GENMASK(15, 8)); -} +struct rtw89_h2c_addr_cam_v0 { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; + __le32 w8; + __le32 w9; + __le32 w10; + __le32 w11; + __le32 w12; + __le32 w13; + __le32 w14; +} __packed; -static inline void FWCMD_SET_ADDR_BSSID_BSSID4(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 14, value, GENMASK(23, 16)); -} +struct rtw89_h2c_addr_cam { + struct rtw89_h2c_addr_cam_v0 v0; + __le32 w15; +} __packed; -static inline void FWCMD_SET_ADDR_BSSID_BSSID5(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 14, value, GENMASK(31, 24)); -} +#define ADDR_CAM_W1_IDX GENMASK(7, 0) +#define ADDR_CAM_W1_OFFSET GENMASK(15, 8) +#define ADDR_CAM_W1_LEN GENMASK(23, 16) +#define ADDR_CAM_W1_V1_IDX GENMASK(9, 0) +#define ADDR_CAM_W1_V1_OFFSET GENMASK(23, 16) +#define ADDR_CAM_W1_V1_LEN GENMASK(31, 24) +#define ADDR_CAM_W2_VALID BIT(0) +#define ADDR_CAM_W2_NET_TYPE GENMASK(2, 1) +#define ADDR_CAM_W2_BCN_HIT_COND GENMASK(4, 3) +#define ADDR_CAM_W2_HIT_RULE GENMASK(6, 5) +#define ADDR_CAM_W2_BB_SEL BIT(7) +#define ADDR_CAM_W2_ADDR_MASK GENMASK(13, 8) +#define ADDR_CAM_W2_MASK_SEL GENMASK(15, 14) +#define ADDR_CAM_W2_SMA_HASH GENMASK(23, 16) +#define ADDR_CAM_W2_TMA_HASH GENMASK(31, 24) +#define ADDR_CAM_W3_BSSID_CAM_IDX GENMASK(5, 0) +#define ADDR_CAM_W4_SMA0 GENMASK(7, 0) +#define ADDR_CAM_W4_SMA1 GENMASK(15, 8) +#define ADDR_CAM_W4_SMA2 GENMASK(23, 16) +#define ADDR_CAM_W4_SMA3 GENMASK(31, 24) +#define ADDR_CAM_W5_SMA4 GENMASK(7, 0) +#define ADDR_CAM_W5_SMA5 GENMASK(15, 8) +#define ADDR_CAM_W5_TMA0 GENMASK(23, 16) +#define ADDR_CAM_W5_TMA1 GENMASK(31, 24) +#define ADDR_CAM_W6_TMA2 GENMASK(7, 0) +#define ADDR_CAM_W6_TMA3 GENMASK(15, 8) +#define ADDR_CAM_W6_TMA4 GENMASK(23, 16) +#define ADDR_CAM_W6_TMA5 GENMASK(31, 24) +#define ADDR_CAM_W8_MACID GENMASK(7, 0) +#define ADDR_CAM_W8_PORT_INT GENMASK(10, 8) +#define ADDR_CAM_W8_TSF_SYNC GENMASK(13, 11) +#define ADDR_CAM_W8_TF_TRS BIT(14) +#define ADDR_CAM_W8_LSIG_TXOP BIT(15) +#define ADDR_CAM_W8_TGT_IND GENMASK(26, 24) +#define ADDR_CAM_W8_FRM_TGT_IND GENMASK(29, 27) +#define ADDR_CAM_W8_V1_MACID GENMASK(9, 0) +#define ADDR_CAM_W8_V1_PORT_INT GENMASK(18, 16) +#define ADDR_CAM_W8_V1_TSF_SYNC GENMASK(21, 19) +#define ADDR_CAM_W8_V1_TF_TRS BIT(22) +#define ADDR_CAM_W8_V1_LSIG_TXOP BIT(23) +#define ADDR_CAM_W8_V1_TB_RANGING BIT(24) +#define ADDR_CAM_W8_V1_TB_SENSING BIT(25) +#define ADDR_CAM_W8_V1_SENS_EN BIT(26) +#define ADDR_CAM_W9_AID12 GENMASK(11, 0) +#define ADDR_CAM_W9_AID12_0 GENMASK(7, 0) +#define ADDR_CAM_W9_AID12_1 GENMASK(11, 8) +#define ADDR_CAM_W9_WOL_PATTERN BIT(12) +#define ADDR_CAM_W9_WOL_UC BIT(13) +#define ADDR_CAM_W9_WOL_MAGIC BIT(14) +#define ADDR_CAM_W9_WAPI BIT(15) +#define ADDR_CAM_W9_SEC_ENT_MODE GENMASK(17, 16) +#define ADDR_CAM_W9_SEC_ENT0_KEYID GENMASK(19, 18) +#define ADDR_CAM_W9_SEC_ENT1_KEYID GENMASK(21, 20) +#define ADDR_CAM_W9_SEC_ENT2_KEYID GENMASK(23, 22) +#define ADDR_CAM_W9_SEC_ENT3_KEYID GENMASK(25, 24) +#define ADDR_CAM_W9_SEC_ENT4_KEYID GENMASK(27, 26) +#define ADDR_CAM_W9_SEC_ENT5_KEYID GENMASK(29, 28) +#define ADDR_CAM_W9_SEC_ENT6_KEYID GENMASK(31, 30) +#define ADDR_CAM_W10_SEC_ENT_VALID GENMASK(7, 0) +#define ADDR_CAM_W10_SEC_ENT0 GENMASK(15, 8) +#define ADDR_CAM_W10_SEC_ENT1 GENMASK(23, 16) +#define ADDR_CAM_W10_SEC_ENT2 GENMASK(31, 24) +#define ADDR_CAM_W11_SEC_ENT3 GENMASK(7, 0) +#define ADDR_CAM_W11_SEC_ENT4 GENMASK(15, 8) +#define ADDR_CAM_W11_SEC_ENT5 GENMASK(23, 16) +#define ADDR_CAM_W11_SEC_ENT6 GENMASK(31, 24) +#define ADDR_CAM_W12_BSSID_IDX GENMASK(7, 0) +#define ADDR_CAM_W12_BSSID_OFFSET GENMASK(15, 8) +#define ADDR_CAM_W12_BSSID_LEN GENMASK(23, 16) +#define ADDR_CAM_W13_BSSID_VALID BIT(0) +#define ADDR_CAM_W13_BSSID_BB_SEL BIT(1) +#define ADDR_CAM_W13_BSSID_MASK GENMASK(7, 2) +#define ADDR_CAM_W13_BSSID_BSS_COLOR GENMASK(13, 8) +#define ADDR_CAM_W13_BSSID_BSSID0 GENMASK(23, 16) +#define ADDR_CAM_W13_BSSID_BSSID1 GENMASK(31, 24) +#define ADDR_CAM_W14_BSSID_BSSID2 GENMASK(7, 0) +#define ADDR_CAM_W14_BSSID_BSSID3 GENMASK(15, 8) +#define ADDR_CAM_W14_BSSID_BSSID4 GENMASK(23, 16) +#define ADDR_CAM_W14_BSSID_BSSID5 GENMASK(31, 24) +#define ADDR_CAM_W15_UPD_MODE GENMASK(2, 0) struct rtw89_h2c_dctlinfo_ud_v1 { __le32 c0; @@ -552,9 +316,10 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, struct rtw89_bssid_cam_entry *bssid_cam); void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *vif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, - const u8 *scan_mac_addr, u8 *cmd); + const u8 *scan_mac_addr, + struct rtw89_h2c_addr_cam_v0 *h2c); void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, @@ -565,7 +330,8 @@ void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, struct rtw89_h2c_dctlinfo_ud_v2 *h2c); int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, u8 *cmd); + struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_addr_cam_v0 *h2c); int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 917b2adede61..0824940c91ae 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -321,6 +321,26 @@ static const struct ieee80211_supported_band rtw89_sband_6ghz = { .n_bitrates = ARRAY_SIZE(rtw89_bitrates) - 4, }; +static const struct rtw89_hw_rate_def { + enum rtw89_hw_rate ht; + enum rtw89_hw_rate vht[RTW89_NSS_NUM]; +} rtw89_hw_rate[RTW89_CHIP_GEN_NUM] = { + [RTW89_CHIP_AX] = { + .ht = RTW89_HW_RATE_MCS0, + .vht = {RTW89_HW_RATE_VHT_NSS1_MCS0, + RTW89_HW_RATE_VHT_NSS2_MCS0, + RTW89_HW_RATE_VHT_NSS3_MCS0, + RTW89_HW_RATE_VHT_NSS4_MCS0}, + }, + [RTW89_CHIP_BE] = { + .ht = RTW89_HW_RATE_V1_MCS0, + .vht = {RTW89_HW_RATE_V1_VHT_NSS1_MCS0, + RTW89_HW_RATE_V1_VHT_NSS2_MCS0, + RTW89_HW_RATE_V1_VHT_NSS3_MCS0, + RTW89_HW_RATE_V1_VHT_NSS4_MCS0}, + }, +}; + static void __rtw89_traffic_stats_accu(struct rtw89_traffic_stats *stats, struct sk_buff *skb, bool tx) { @@ -450,6 +470,22 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) __rtw89_core_set_chip_txpwr(rtwdev, chan, RTW89_PHY_1); } +static void rtw89_chip_rfk_channel_for_pure_mon_vif(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + struct rtw89_vif *rtwvif = rtwdev->pure_monitor_mode_vif; + struct rtw89_vif_link *rtwvif_link; + + if (!rtwvif) + return; + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, phy_idx); + if (!rtwvif_link) + return; + + rtw89_chip_rfk_channel(rtwdev, rtwvif_link); +} + static void __rtw89_set_channel(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_mac_idx mac_idx, @@ -478,6 +514,8 @@ static void __rtw89_set_channel(struct rtw89_dev *rtwdev, } rtw89_set_entity_state(rtwdev, phy_idx, true); + + rtw89_chip_rfk_channel_for_pure_mon_vif(rtwdev, phy_idx); } int rtw89_set_channel(struct rtw89_dev *rtwdev) @@ -759,6 +797,25 @@ u8 rtw89_core_get_ch_dma_v1(struct rtw89_dev *rtwdev, u8 qsel) } EXPORT_SYMBOL(rtw89_core_get_ch_dma_v1); +u8 rtw89_core_get_ch_dma_v2(struct rtw89_dev *rtwdev, u8 qsel) +{ + switch (qsel) { + default: + rtw89_warn(rtwdev, "Cannot map qsel to dma v2: %d\n", qsel); + fallthrough; + case RTW89_TX_QSEL_BE_0: + case RTW89_TX_QSEL_VO_0: + return RTW89_TXCH_ACH0; + case RTW89_TX_QSEL_BK_0: + case RTW89_TX_QSEL_VI_0: + return RTW89_TXCH_ACH2; + case RTW89_TX_QSEL_B0_MGMT: + case RTW89_TX_QSEL_B0_HI: + return RTW89_TXCH_CH8; + } +} +EXPORT_SYMBOL(rtw89_core_get_ch_dma_v2); + static void rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) @@ -1078,6 +1135,44 @@ notify: rtw89_mac_notify_wake(rtwdev); } +static void rtw89_core_tx_update_injection(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req, + struct ieee80211_tx_info *info) +{ + const struct rtw89_hw_rate_def *hw_rate = &rtw89_hw_rate[rtwdev->chip->chip_gen]; + enum mac80211_rate_control_flags flags = info->control.rates[0].flags; + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + const struct rtw89_chan *chan; + u8 idx = info->control.rates[0].idx; + u8 nss, mcs; + + desc_info->use_rate = true; + desc_info->dis_data_fb = true; + + if (flags & IEEE80211_TX_RC_160_MHZ_WIDTH) + desc_info->data_bw = 3; + else if (flags & IEEE80211_TX_RC_80_MHZ_WIDTH) + desc_info->data_bw = 2; + else if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + desc_info->data_bw = 1; + + if (flags & IEEE80211_TX_RC_SHORT_GI) + desc_info->gi_ltf = 1; + + if (flags & IEEE80211_TX_RC_VHT_MCS) { + nss = umin(idx >> 4, ARRAY_SIZE(hw_rate->vht) - 1); + mcs = idx & 0xf; + desc_info->data_rate = hw_rate->vht[nss] + mcs; + } else if (flags & IEEE80211_TX_RC_MCS) { + desc_info->data_rate = hw_rate->ht + idx; + } else { + chan = rtw89_chan_get(rtwdev, tx_req->rtwvif_link->chanctx_idx); + + desc_info->data_rate = idx + (chan->band_type == RTW89_BAND_2G ? + RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6); + } +} + static void rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) @@ -1087,32 +1182,38 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (void *)skb->data; struct rtw89_addr_cam_entry *addr_cam; - enum rtw89_core_tx_type tx_type; enum btc_pkt_type pkt_type; bool upd_wlan_hdr = false; bool is_bmc; u16 seq; + desc_info->pkt_size = skb->len; + + if (unlikely(tx_req->tx_type == RTW89_CORE_TX_TYPE_FWCMD)) { + rtw89_core_tx_update_h2c_info(rtwdev, tx_req); + return; + } + + tx_req->tx_type = rtw89_core_get_tx_type(rtwdev, skb); + if (tx_req->sta) desc_info->mlo = tx_req->sta->mlo; else if (tx_req->vif) desc_info->mlo = ieee80211_vif_is_mld(tx_req->vif); seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - if (tx_req->tx_type != RTW89_CORE_TX_TYPE_FWCMD) { - tx_type = rtw89_core_get_tx_type(rtwdev, skb); - tx_req->tx_type = tx_type; + addr_cam = rtw89_get_addr_cam_of(tx_req->rtwvif_link, + tx_req->rtwsta_link); + if (addr_cam->valid && desc_info->mlo) + upd_wlan_hdr = true; + + if (rtw89_is_tx_rpt_skb(rtwdev, tx_req->skb)) + rtw89_tx_rpt_init(rtwdev, tx_req); - addr_cam = rtw89_get_addr_cam_of(tx_req->rtwvif_link, - tx_req->rtwsta_link); - if (addr_cam->valid && desc_info->mlo) - upd_wlan_hdr = true; - } is_bmc = (is_broadcast_ether_addr(hdr->addr1) || is_multicast_ether_addr(hdr->addr1)); desc_info->seq = seq; - desc_info->pkt_size = skb->len; desc_info->is_bmc = is_bmc; desc_info->wd_page = true; desc_info->hiq = info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM; @@ -1129,10 +1230,12 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev, rtw89_core_tx_update_ampdu_info(rtwdev, tx_req, pkt_type); rtw89_core_tx_update_llc_hdr(rtwdev, desc_info, skb); break; - case RTW89_CORE_TX_TYPE_FWCMD: - rtw89_core_tx_update_h2c_info(rtwdev, tx_req); + default: break; } + + if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) + rtw89_core_tx_update_injection(rtwdev, tx_req, info); } static void rtw89_tx_wait_work(struct wiphy *wiphy, struct wiphy_work *work) @@ -1239,14 +1342,13 @@ static int rtw89_core_tx_write_link(struct rtw89_dev *rtwdev, tx_req.rtwvif_link = rtwvif_link; tx_req.rtwsta_link = rtwsta_link; tx_req.desc_info.sw_mld = sw_mld; + rcu_assign_pointer(skb_data->wait, wait); rtw89_traffic_stats_accu(rtwdev, rtwvif, skb, true, true); rtw89_wow_parse_akm(rtwdev, skb); rtw89_core_tx_update_desc_info(rtwdev, &tx_req); rtw89_core_tx_wake(rtwdev, &tx_req); - rcu_assign_pointer(skb_data->wait, wait); - ret = rtw89_hci_tx_write(rtwdev, &tx_req); if (ret) { rtw89_err(rtwdev, "failed to transmit skb to HCI\n"); @@ -1362,6 +1464,8 @@ static __le32 rtw89_build_txwd_body5(struct rtw89_tx_desc_info *desc_info) static __le32 rtw89_build_txwd_body7_v1(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(RTW89_TXWD_BODY7_USE_RATE_V1, desc_info->use_rate) | + FIELD_PREP(RTW89_TXWD_BODY7_DATA_BW, desc_info->data_bw) | + FIELD_PREP(RTW89_TXWD_BODY7_GI_LTF, desc_info->gi_ltf) | FIELD_PREP(RTW89_TXWD_BODY7_DATA_RATE, desc_info->data_rate); return cpu_to_le32(dword); @@ -1370,6 +1474,8 @@ static __le32 rtw89_build_txwd_body7_v1(struct rtw89_tx_desc_info *desc_info) static __le32 rtw89_build_txwd_info0(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(RTW89_TXWD_INFO0_USE_RATE, desc_info->use_rate) | + FIELD_PREP(RTW89_TXWD_INFO0_DATA_BW, desc_info->data_bw) | + FIELD_PREP(RTW89_TXWD_INFO0_GI_LTF, desc_info->gi_ltf) | FIELD_PREP(RTW89_TXWD_INFO0_DATA_RATE, desc_info->data_rate) | FIELD_PREP(RTW89_TXWD_INFO0_DATA_STBC, desc_info->stbc) | FIELD_PREP(RTW89_TXWD_INFO0_DATA_LDPC, desc_info->ldpc) | @@ -1396,7 +1502,10 @@ static __le32 rtw89_build_txwd_info1(struct rtw89_tx_desc_info *desc_info) u32 dword = FIELD_PREP(RTW89_TXWD_INFO1_MAX_AGGNUM, desc_info->ampdu_num) | FIELD_PREP(RTW89_TXWD_INFO1_A_CTRL_BSR, desc_info->a_ctrl_bsr) | FIELD_PREP(RTW89_TXWD_INFO1_DATA_RTY_LOWEST_RATE, - desc_info->data_retry_lowest_rate); + desc_info->data_retry_lowest_rate) | + FIELD_PREP(RTW89_TXWD_INFO1_DATA_TXCNT_LMT_SEL, + desc_info->tx_cnt_lmt_en) | + FIELD_PREP(RTW89_TXWD_INFO1_DATA_TXCNT_LMT, desc_info->tx_cnt_lmt); return cpu_to_le32(dword); } @@ -1420,11 +1529,19 @@ static __le32 rtw89_build_txwd_info2_v1(struct rtw89_tx_desc_info *desc_info) return cpu_to_le32(dword); } +static __le32 rtw89_build_txwd_info3(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(RTW89_TXWD_INFO3_SPE_RPT, desc_info->report); + + return cpu_to_le32(dword); +} + static __le32 rtw89_build_txwd_info4(struct rtw89_tx_desc_info *desc_info) { bool rts_en = !desc_info->is_bmc; u32 dword = FIELD_PREP(RTW89_TXWD_INFO4_RTS_EN, rts_en) | - FIELD_PREP(RTW89_TXWD_INFO4_HW_RTS_EN, 1); + FIELD_PREP(RTW89_TXWD_INFO4_HW_RTS_EN, 1) | + FIELD_PREP(RTW89_TXWD_INFO4_SW_DEFINE, desc_info->sn); return cpu_to_le32(dword); } @@ -1447,6 +1564,7 @@ void rtw89_core_fill_txdesc(struct rtw89_dev *rtwdev, txwd_info->dword0 = rtw89_build_txwd_info0(desc_info); txwd_info->dword1 = rtw89_build_txwd_info1(desc_info); txwd_info->dword2 = rtw89_build_txwd_info2(desc_info); + txwd_info->dword3 = rtw89_build_txwd_info3(desc_info); txwd_info->dword4 = rtw89_build_txwd_info4(desc_info); } @@ -1476,6 +1594,7 @@ void rtw89_core_fill_txdesc_v1(struct rtw89_dev *rtwdev, txwd_info->dword0 = rtw89_build_txwd_info0_v1(desc_info); txwd_info->dword1 = rtw89_build_txwd_info1(desc_info); txwd_info->dword2 = rtw89_build_txwd_info2_v1(desc_info); + txwd_info->dword3 = rtw89_build_txwd_info3(desc_info); txwd_info->dword4 = rtw89_build_txwd_info4(desc_info); } EXPORT_SYMBOL(rtw89_core_fill_txdesc_v1); @@ -1549,6 +1668,8 @@ static __le32 rtw89_build_txwd_body6_v2(struct rtw89_tx_desc_info *desc_info) static __le32 rtw89_build_txwd_body7_v2(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(BE_TXD_BODY7_USERATE_SEL, desc_info->use_rate) | + FIELD_PREP(BE_TXD_BODY7_DATA_BW, desc_info->data_bw) | + FIELD_PREP(BE_TXD_BODY7_GI_LTF, desc_info->gi_ltf) | FIELD_PREP(BE_TXD_BODY7_DATA_ER, desc_info->er_cap) | FIELD_PREP(BE_TXD_BODY7_DATA_BW_ER, 0) | FIELD_PREP(BE_TXD_BODY7_DATARATE, desc_info->data_rate); @@ -1561,7 +1682,10 @@ static __le32 rtw89_build_txwd_info0_v2(struct rtw89_tx_desc_info *desc_info) u32 dword = FIELD_PREP(BE_TXD_INFO0_DATA_STBC, desc_info->stbc) | FIELD_PREP(BE_TXD_INFO0_DATA_LDPC, desc_info->ldpc) | FIELD_PREP(BE_TXD_INFO0_DISDATAFB, desc_info->dis_data_fb) | - FIELD_PREP(BE_TXD_INFO0_MULTIPORT_ID, desc_info->port); + FIELD_PREP(BE_TXD_INFO0_MULTIPORT_ID, desc_info->port) | + FIELD_PREP(BE_TXD_INFO0_DATA_TXCNT_LMT_SEL, + desc_info->tx_cnt_lmt_en) | + FIELD_PREP(BE_TXD_INFO0_DATA_TXCNT_LMT, desc_info->tx_cnt_lmt); return cpu_to_le32(dword); } @@ -1571,7 +1695,8 @@ static __le32 rtw89_build_txwd_info1_v2(struct rtw89_tx_desc_info *desc_info) u32 dword = FIELD_PREP(BE_TXD_INFO1_MAX_AGG_NUM, desc_info->ampdu_num) | FIELD_PREP(BE_TXD_INFO1_A_CTRL_BSR, desc_info->a_ctrl_bsr) | FIELD_PREP(BE_TXD_INFO1_DATA_RTY_LOWEST_RATE, - desc_info->data_retry_lowest_rate); + desc_info->data_retry_lowest_rate) | + FIELD_PREP(BE_TXD_INFO1_SW_DEFINE, desc_info->sn); return cpu_to_le32(dword); } @@ -1580,7 +1705,8 @@ static __le32 rtw89_build_txwd_info2_v2(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(BE_TXD_INFO2_AMPDU_DENSITY, desc_info->ampdu_density) | FIELD_PREP(BE_TXD_INFO2_FORCE_KEY_EN, desc_info->sec_en) | - FIELD_PREP(BE_TXD_INFO2_SEC_CAM_IDX, desc_info->sec_cam_idx); + FIELD_PREP(BE_TXD_INFO2_SEC_CAM_IDX, desc_info->sec_cam_idx) | + FIELD_PREP(BE_TXD_INFO2_SPE_RPT_V1, desc_info->report); return cpu_to_le32(dword); } @@ -1708,9 +1834,13 @@ static int rtw89_core_rx_process_mac_ppdu(struct rtw89_dev *rtwdev, /* For WiFi 7 chips, RXWD.mac_id of PPDU status is not set * by hardware, so update mac_id by rxinfo_user[].mac_id. */ - if (chip_gen == RTW89_CHIP_BE) + if (chip->chip_id == RTL8922A) phy_ppdu->mac_id = le32_get_bits(user->w0, RTW89_RXINFO_USER_MACID); + else if (chip->chip_id == RTL8922D) + phy_ppdu->mac_id = + le32_get_bits(user->w0, RTW89_RXINFO_USER_MACID_V1); + phy_ppdu->has_data = le32_get_bits(user->w0, RTW89_RXINFO_USER_DATA); phy_ppdu->has_bcn = @@ -3632,12 +3762,10 @@ void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta) { struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); - struct sk_buff *skb, *tmp; + struct sk_buff *skb; - skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { - skb_unlink(skb, &rtwsta->roc_queue); + while ((skb = skb_dequeue(&rtwsta->roc_queue))) dev_kfree_skb_any(skb); - } } static void rtw89_core_stop_tx_ba_session(struct rtw89_dev *rtwdev, @@ -3881,8 +4009,8 @@ static void rtw89_core_sta_pending_tx_iter(void *data, 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; + struct sk_buff *skb; int qsel, ret; rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) @@ -3895,9 +4023,7 @@ bottom: if (skb_queue_len(&rtwsta->roc_queue) == 0) return; - skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { - skb_unlink(skb, &rtwsta->roc_queue); - + while ((skb = skb_dequeue(&rtwsta->roc_queue))) { ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel); if (ret) { rtw89_warn(rtwdev, "pending tx failed with %d\n", ret); @@ -4047,12 +4173,10 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) 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->roc; struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *tmp_vif; - u32 reg; int ret; lockdep_assert_wiphy(hw->wiphy); @@ -4069,8 +4193,7 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) return; } - reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); - rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, rtwvif_link->mac_idx, rtwdev->hal.rx_fltr); roc->state = RTW89_ROC_IDLE; rtw89_config_roc_chandef(rtwdev, rtwvif_link, NULL); @@ -4701,7 +4824,8 @@ int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, } /* update cam aid mac_id net_type */ - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_CON_DISCONN); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -4775,7 +4899,8 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, } /* update cam aid mac_id net_type */ - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_CON_DISCONN); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -5493,10 +5618,22 @@ EXPORT_SYMBOL(rtw89_check_quirks); int rtw89_core_start(struct rtw89_dev *rtwdev) { + bool no_bbmcu = !rtwdev->chip->bbmcu_nr; int ret; + ret = rtw89_mac_preinit(rtwdev); + if (ret) { + rtw89_err(rtwdev, "mac preinit fail, ret: %d\n", ret); + return ret; + } + + if (no_bbmcu) + rtw89_chip_bb_preinit(rtwdev); + rtw89_phy_init_bb_afe(rtwdev); + /* above do preinit before downloading firmware */ + ret = rtw89_mac_init(rtwdev); if (ret) { rtw89_err(rtwdev, "mac init fail, ret:%d\n", ret); @@ -5542,6 +5679,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.log.enable); rtw89_fw_h2c_init_ba_cam(rtwdev); rtw89_tas_fw_timer_enable(rtwdev, true); + rtwdev->ps_hang_cnt = 0; return 0; } @@ -5829,6 +5967,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) wiphy_work_init(&rtwdev->cancel_6ghz_probe_work, rtw89_cancel_6ghz_probe_work); INIT_WORK(&rtwdev->load_firmware_work, rtw89_load_firmware_work); + spin_lock_init(&rtwdev->tx_rpt.skb_lock); skb_queue_head_init(&rtwdev->c2h_queue); rtw89_core_ppdu_sts_init(rtwdev); rtw89_traffic_stats_init(rtwdev, &rtwdev->stats); @@ -5893,7 +6032,8 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv rtw89_phy_config_edcca(rtwdev, bb, true); rtw89_tas_scan(rtwdev, true); - rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr, + RTW89_ROLE_INFO_CHANGE); } void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, @@ -5913,7 +6053,8 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, rcu_read_unlock(); - rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, + RTW89_ROLE_INFO_CHANGE); rtw89_chip_rfk_scan(rtwdev, rtwvif_link, false); rtw89_btc_ntfy_scan_finish(rtwdev, rtwvif_link->phy_idx); @@ -6014,7 +6155,7 @@ int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); u16 usable_links = ieee80211_vif_usable_links(vif); u16 active_links = vif->active_links; - struct rtw89_vif_link *target, *cur; + struct rtw89_vif_link *target; int ret; lockdep_assert_wiphy(rtwdev->hw->wiphy); @@ -6040,11 +6181,9 @@ int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ieee80211_stop_queues(rtwdev->hw); flush_work(&rtwdev->txq_work); - cur = rtw89_get_designated_link(rtwvif); - - ret = ieee80211_set_active_links(vif, active_links | BIT(link_id)); + ret = ieee80211_set_active_links(vif, BIT(link_id)); if (ret) { - rtw89_err(rtwdev, "%s: failed to activate link id %u\n", + rtw89_err(rtwdev, "%s: failed to work on link id %u\n", __func__, link_id); goto wake_queue; } @@ -6059,16 +6198,6 @@ int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, goto wake_queue; } - if (likely(cur)) - rtw89_fw_h2c_mlo_link_cfg(rtwdev, cur, false); - - rtw89_fw_h2c_mlo_link_cfg(rtwdev, target, true); - - ret = ieee80211_set_active_links(vif, BIT(link_id)); - if (ret) - rtw89_err(rtwdev, "%s: failed to inactivate links 0x%x\n", - __func__, active_links); - rtw89_chip_rfk_channel(rtwdev, target); rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR; diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 928c8c84c964..a9cb47ea0b93 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -15,6 +15,7 @@ struct rtw89_dev; struct rtw89_pci_info; +struct rtw89_usb_info; struct rtw89_mac_gen_def; struct rtw89_phy_gen_def; struct rtw89_fw_blacklist; @@ -38,10 +39,13 @@ extern const struct ieee80211_ops rtw89_ops; #define RFREG_MASK 0xfffff #define INV_RF_DATA 0xffffffff #define BYPASS_CR_DATA 0xbabecafe +#define RTW89_R32_EA 0xEAEAEAEA +#define RTW89_R32_DEAD 0xDEADBEEF #define RTW89_TRACK_WORK_PERIOD round_jiffies_relative(HZ * 2) #define RTW89_TRACK_PS_WORK_PERIOD msecs_to_jiffies(100) #define RTW89_FORBID_BA_TIMER round_jiffies_relative(HZ * 4) +#define RTW89_PS_HANG_MAX_CNT 3 #define CFO_TRACK_MAX_USER 64 #define MAX_RSSI 110 #define RSSI_FACTOR 1 @@ -151,6 +155,7 @@ enum rtw89_core_chip_id { RTL8852C, RTL8851B, RTL8922A, + RTL8922D, }; enum rtw89_chip_gen { @@ -1167,6 +1172,10 @@ struct rtw89_tx_desc_info { u8 ampdu_density; u8 ampdu_num; bool sec_en; + bool report; + bool tx_cnt_lmt_en; + u8 sn: 4; + u8 tx_cnt_lmt: 6; u8 addr_info_nr; u8 sec_keyid; u8 sec_type; @@ -1174,6 +1183,8 @@ struct rtw89_tx_desc_info { u8 sec_seq[6]; u16 data_rate; u16 data_retry_lowest_rate; + u8 data_bw; + u8 gi_ltf; bool fw_dl; u16 seq; bool a_ctrl_bsr; @@ -3374,11 +3385,18 @@ struct rtw89_ra_info { u8 cr_tbl_sel:1; u8 fix_giltf_en:1; u8 fix_giltf:3; - u8 rsvd2:1; + u8 partial_bw_er:1; u8 csi_mcs_ss_idx; u8 csi_mode:2; u8 csi_gi_ltf:3; u8 csi_bw:3; + /* after v1 */ + u8 is_noisy:1; + u8 psra_en:1; + u8 rsvd0:1; + u8 macid_msb:2; + u8 band:2; /* enum rtw89_band */ + u8 is_new_dbgreg:1; }; #define RTW89_PPDU_MAC_INFO_USR_SIZE 4 @@ -3507,6 +3525,20 @@ struct rtw89_phy_rate_pattern { bool enable; }; +#define RTW89_TX_DONE 0x0 +#define RTW89_TX_RETRY_LIMIT 0x1 +#define RTW89_TX_LIFE_TIME 0x2 +#define RTW89_TX_MACID_DROP 0x3 + +#define RTW89_MAX_TX_RPTS 16 +#define RTW89_MAX_TX_RPTS_MASK (RTW89_MAX_TX_RPTS - 1) +struct rtw89_tx_rpt { + struct sk_buff *skbs[RTW89_MAX_TX_RPTS]; + /* protect skbs array access/modification */ + spinlock_t skb_lock; + atomic_t sn; +}; + #define RTW89_TX_WAIT_WORK_TIMEOUT msecs_to_jiffies(500) struct rtw89_tx_wait_info { struct rcu_head rcu_head; @@ -3518,6 +3550,8 @@ struct rtw89_tx_wait_info { struct rtw89_tx_skb_data { struct rtw89_tx_wait_info __rcu *wait; + u8 tx_rpt_sn; + u8 tx_pkt_cnt_lmt; u8 hci_priv[]; }; @@ -3652,6 +3686,8 @@ struct rtw89_hci_ops { void (*write16)(struct rtw89_dev *rtwdev, u32 addr, u16 data); void (*write32)(struct rtw89_dev *rtwdev, u32 addr, u32 data); + u32 (*read32_pci_cfg)(struct rtw89_dev *rtwdev, u32 addr); + int (*mac_pre_init)(struct rtw89_dev *rtwdev); int (*mac_pre_deinit)(struct rtw89_dev *rtwdev); int (*mac_post_init)(struct rtw89_dev *rtwdev); @@ -3687,6 +3723,7 @@ struct rtw89_hci_info { u32 rpwm_addr; u32 cpwm_addr; bool paused; + bool tx_rpt_enabled; }; struct rtw89_chip_ops { @@ -3763,7 +3800,7 @@ struct rtw89_chip_ops { void (*fill_txdesc_fwcmd)(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, void *txdesc); - u8 (*get_ch_dma)(struct rtw89_dev *rtwdev, u8 qsel); + u8 (*get_ch_dma[RTW89_HCI_TYPE_NUM])(struct rtw89_dev *rtwdev, u8 qsel); int (*cfg_ctrl_path)(struct rtw89_dev *rtwdev, bool wl); int (*mac_cfg_gnt)(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex_gnt *gnt_cfg); @@ -4422,6 +4459,7 @@ struct rtw89_chip_info { u8 bacam_num; u8 bacam_dynamic_num; enum rtw89_bacam_ver bacam_ver; + u8 addrcam_ver; u8 ppdu_max_usr; u8 sec_ctrl_efuse_size; @@ -4513,6 +4551,7 @@ struct rtw89_chip_variant { union rtw89_bus_info { const struct rtw89_pci_info *pci; + const struct rtw89_usb_info *usb; }; struct rtw89_driver_info { @@ -4640,6 +4679,7 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_RFK_NTFY_MCC_V0, RTW89_FW_FEATURE_LPS_DACK_BY_C2H_REG, RTW89_FW_FEATURE_BEACON_TRACKING, + RTW89_FW_FEATURE_ADDR_CAM_V0, }; struct rtw89_fw_suit { @@ -4700,6 +4740,7 @@ struct rtw89_fw_elm_info { struct rtw89_phy_rfk_log_fmt *rfk_log_fmt; const struct rtw89_regd_data *regd; const struct rtw89_fw_element_hdr *afe; + const struct rtw89_fw_element_hdr *diag_mac; }; enum rtw89_fw_mss_dev_type { @@ -5449,6 +5490,8 @@ struct rtw89_regd_ctrl { struct rtw89_regulatory_info { struct rtw89_regd_ctrl ctrl; const struct rtw89_regd *regd; + bool programmed; + enum rtw89_reg_6ghz_power reg_6ghz_power; struct rtw89_reg_6ghz_tpe reg_6ghz_tpe; bool txpwr_uk_follow_etsi; @@ -5933,6 +5976,7 @@ struct rtw89_mcc_info { enum rtw89_mlo_mode { RTW89_MLO_MODE_MLSR = 0, + RTW89_MLO_MODE_EMLSR = 1, NUM_OF_RTW89_MLO_MODE, }; @@ -6006,6 +6050,8 @@ struct rtw89_dev { struct list_head tx_waits; struct wiphy_delayed_work tx_wait_work; + struct rtw89_tx_rpt tx_rpt; + struct rtw89_cam_info cam_info; struct sk_buff_head c2h_queue; @@ -6079,6 +6125,7 @@ struct rtw89_dev { struct rtw89_btc btc; enum rtw89_ps_mode ps_mode; bool lps_enabled; + u8 ps_hang_cnt; struct rtw89_wow_param wow; @@ -6088,6 +6135,7 @@ struct rtw89_dev { int napi_budget_countdown; struct rtw89_debugfs *debugfs; + struct rtw89_vif *pure_monitor_mode_vif; /* HCI related data, keep last */ u8 priv[] __aligned(sizeof(void *)); @@ -6097,6 +6145,12 @@ struct rtw89_link_conf_container { struct ieee80211_bss_conf *link_conf[IEEE80211_MLD_MAX_NUM_LINKS]; }; +struct rtw89_vif_ml_trans { + u16 mediate_links; + u16 links_to_del; + u16 links_to_add; +}; + #define RTW89_VIF_IDLE_LINK_ID 0 struct rtw89_vif { @@ -6119,6 +6173,7 @@ struct rtw89_vif { bool offchan; enum rtw89_mlo_mode mlo_mode; + struct rtw89_vif_ml_trans ml_trans; struct list_head dlink_pool; u8 links_inst_valid_num; @@ -6291,6 +6346,7 @@ static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev, static inline void rtw89_hci_reset(struct rtw89_dev *rtwdev) { rtwdev->hci.ops->reset(rtwdev); + /* hci.ops->reset must complete all pending TX wait SKBs */ rtw89_tx_wait_list_clear(rtwdev); } @@ -6620,6 +6676,15 @@ rtw89_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, mutex_unlock(&rtwdev->rf_mutex); } +static inline u32 rtw89_read32_pci_cfg(struct rtw89_dev *rtwdev, u32 addr) +{ + if (rtwdev->hci.type != RTW89_HCI_TYPE_PCIE || + !rtwdev->hci.ops->read32_pci_cfg) + return RTW89_R32_EA; + + return rtwdev->hci.ops->read32_pci_cfg(rtwdev, addr); +} + static inline struct ieee80211_txq *rtw89_txq_to_txq(struct rtw89_txq *rtwtxq) { void *p = rtwtxq; @@ -6984,12 +7049,17 @@ static inline void rtw89_chip_rfk_hw_init(struct rtw89_dev *rtwdev) } static inline -void rtw89_chip_bb_preinit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +void rtw89_chip_bb_preinit(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; - if (chip->ops->bb_preinit) - chip->ops->bb_preinit(rtwdev, phy_idx); + if (!chip->ops->bb_preinit) + return; + + chip->ops->bb_preinit(rtwdev, RTW89_PHY_0); + + if (rtwdev->dbcc_en) + chip->ops->bb_preinit(rtwdev, RTW89_PHY_1); } static inline @@ -7241,7 +7311,7 @@ u8 rtw89_chip_get_ch_dma(struct rtw89_dev *rtwdev, u8 qsel) { const struct rtw89_chip_info *chip = rtwdev->chip; - return chip->ops->get_ch_dma(rtwdev, qsel); + return chip->ops->get_ch_dma[rtwdev->hci.type](rtwdev, qsel); } static inline @@ -7372,27 +7442,28 @@ static inline struct sk_buff *rtw89_alloc_skb_for_rx(struct rtw89_dev *rtwdev, return dev_alloc_skb(length); } +static inline bool rtw89_core_is_tx_wait(struct rtw89_dev *rtwdev, + struct rtw89_tx_skb_data *skb_data) +{ + return rcu_access_pointer(skb_data->wait); +} + static inline bool rtw89_core_tx_wait_complete(struct rtw89_dev *rtwdev, struct rtw89_tx_skb_data *skb_data, - bool tx_done) + u8 tx_status) { struct rtw89_tx_wait_info *wait; - bool ret = false; - rcu_read_lock(); + guard(rcu)(); wait = rcu_dereference(skb_data->wait); if (!wait) - goto out; + return false; - ret = true; - wait->tx_done = tx_done; + wait->tx_done = tx_status == RTW89_TX_DONE; /* Don't access skb anymore after completion */ complete_all(&wait->completion); - -out: - rcu_read_unlock(); - return ret; + return true; } static inline bool rtw89_is_mlo_1_1(struct rtw89_dev *rtwdev) @@ -7495,6 +7566,7 @@ void rtw89_core_fill_txdesc_fwcmd_v2(struct rtw89_dev *rtwdev, void *txdesc); u8 rtw89_core_get_ch_dma(struct rtw89_dev *rtwdev, u8 qsel); u8 rtw89_core_get_ch_dma_v1(struct rtw89_dev *rtwdev, u8 qsel); +u8 rtw89_core_get_ch_dma_v2(struct rtw89_dev *rtwdev, u8 qsel); void rtw89_core_rx(struct rtw89_dev *rtwdev, struct rtw89_rx_desc_info *desc_info, struct sk_buff *skb); diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 3dc7981c510f..1264c2f82600 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -87,6 +87,7 @@ struct rtw89_debugfs { struct rtw89_debugfs_priv disable_dm; struct rtw89_debugfs_priv mlo_mode; struct rtw89_debugfs_priv beacon_info; + struct rtw89_debugfs_priv diag_mac; }; struct rtw89_debugfs_iter_data { @@ -4361,6 +4362,302 @@ rtw89_debug_priv_mlo_mode_set(struct rtw89_dev *rtwdev, return count; } +enum __diag_mac_cmd { + __CMD_EQUALV, + __CMD_EQUALO, + __CMD_NEQUALV, + __CMD_NEQUALO, + __CMD_SETEQUALV, + __CMD_SETEQUALO, + __CMD_CMPWCR, + __CMD_CMPWWD, + __CMD_NEQ_CMPWCR, + __CMD_NEQ_CMPWWD, + __CMD_INCREMENT, + __CMD_MESSAGE, +}; + +enum __diag_mac_io { + __IO_NORMAL, + __IO_NORMAL_PCIE, + __IO_NORMAL_USB, + __IO_NORMAL_SDIO, + __IO_PCIE_CFG, + __IO_SDIO_CCCR, +}; + +struct __diag_mac_rule_header { + u8 sheet; + u8 cmd; + u8 seq_major; + u8 seq_minor; + u8 io_band; + #define __DIAG_MAC_IO GENMASK(3, 0) + #define __DIAG_MAC_N_BAND BIT(4) + #define __DIAG_MAC_HAS_BAND BIT(5) + u8 len; /* include header. Unit: 4 bytes */ + u8 rsvd[2]; +} __packed; + +struct __diag_mac_rule_equal { + struct __diag_mac_rule_header header; + __le32 addr; + __le32 addr_name_offset; + __le32 mask; + __le32 val; + __le32 msg_offset; + u8 rsvd[4]; +} __packed; + +struct __diag_mac_rule_increment { + struct __diag_mac_rule_header header; + __le32 addr; + __le32 addr_name_offset; + __le32 mask; + __le16 sel; + __le16 delay; + __le32 msg_offset; + u8 rsvd[4]; +} __packed; + +struct __diag_mac_msg_buf { + __le16 len; + char string[]; +} __packed; + +static ssize_t rtw89_mac_diag_do_equalv(struct rtw89_dev *rtwdev, + char *buf, size_t bufsz, + const struct __diag_mac_rule_equal *r, + const void *msg_start, + u64 *positive_bmp) +{ + const struct __diag_mac_msg_buf *name = msg_start + + le32_to_cpu(r->addr_name_offset); + const struct __diag_mac_msg_buf *msg = msg_start + + le32_to_cpu(r->msg_offset); + bool want_eq = r->header.cmd == __CMD_EQUALV; + char *p = buf, *end = buf + bufsz; + bool equal = false; + u32 val; + + *positive_bmp <<= 1; + + if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG) + val = rtw89_read32_pci_cfg(rtwdev, le32_to_cpu(r->addr)); + else + val = rtw89_read32(rtwdev, le32_to_cpu(r->addr)); + + if ((val & le32_to_cpu(r->mask)) == le32_to_cpu(r->val)) + equal = true; + + if (want_eq == equal) { + *positive_bmp |= BIT(0); + return p - buf; + } + + p += scnprintf(p, end - p, "sheet: %d, cmd: %d, Reg: %.*s => %x, %.*s\n", + r->header.sheet, r->header.cmd, le16_to_cpu(name->len), + name->string, val, le16_to_cpu(msg->len), msg->string); + + return p - buf; +} + +static ssize_t rtw89_mac_diag_do_increment(struct rtw89_dev *rtwdev, + char *buf, size_t bufsz, + const struct __diag_mac_rule_increment *r, + const void *msg_start, + u64 *positive_bmp) +{ + const struct __diag_mac_msg_buf *name = msg_start + + le32_to_cpu(r->addr_name_offset); + const struct __diag_mac_msg_buf *msg = msg_start + + le32_to_cpu(r->msg_offset); + char *p = buf, *end = buf + bufsz; + u32 addr = le32_to_cpu(r->addr); + u32 mask = le32_to_cpu(r->mask); + u16 sel = le16_to_cpu(r->sel); + u32 val1, val2; + + *positive_bmp <<= 1; + + rtw89_write32(rtwdev, addr, sel); + + if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG) + val1 = rtw89_read32_pci_cfg(rtwdev, addr); + else + val1 = rtw89_read32(rtwdev, addr); + + mdelay(le16_to_cpu(r->delay)); + + if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG) + val2 = rtw89_read32_pci_cfg(rtwdev, addr); + else + val2 = rtw89_read32(rtwdev, addr); + + if ((val2 & mask) > (val1 & mask)) { + *positive_bmp |= BIT(0); + return p - buf; + } + + p += scnprintf(p, end - p, "sheet: %d, cmd: %d, Reg: %.*s [%d]=> %x, %.*s\n", + r->header.sheet, r->header.cmd, le16_to_cpu(name->len), + name->string, le16_to_cpu(r->sel), val1, + le16_to_cpu(msg->len), msg->string); + + return p - buf; +} + +static bool rtw89_mac_diag_match_hci(struct rtw89_dev *rtwdev, + const struct __diag_mac_rule_header *rh) +{ + switch (u8_get_bits(rh->io_band, __DIAG_MAC_IO)) { + case __IO_NORMAL: + default: + return true; + case __IO_NORMAL_PCIE: + case __IO_PCIE_CFG: + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + return true; + break; + case __IO_NORMAL_USB: + if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) + return true; + break; + case __IO_NORMAL_SDIO: + case __IO_SDIO_CCCR: + if (rtwdev->hci.type == RTW89_HCI_TYPE_SDIO) + return true; + break; + } + + return false; +} + +static bool rtw89_mac_diag_match_band(struct rtw89_dev *rtwdev, + const struct __diag_mac_rule_header *rh) +{ + u8 active_bands; + bool has_band; + u8 band; + + has_band = u8_get_bits(rh->io_band, __DIAG_MAC_HAS_BAND); + if (!has_band) + return true; + + band = u8_get_bits(rh->io_band, __DIAG_MAC_N_BAND); + active_bands = rtw89_get_active_phy_bitmap(rtwdev); + + if (active_bands & BIT(band)) + return true; + + return false; +} + +static ssize_t rtw89_mac_diag_iter_all(struct rtw89_dev *rtwdev, + char *buf, size_t bufsz) +{ + const struct rtw89_fw_element_hdr *elm = rtwdev->fw.elm_info.diag_mac; + u32 n_plains = 0, n_rules = 0, n_positive = 0, n_ignore = 0; + char *p = buf, *end = buf + bufsz, *p_rewind; + const void *rule, *rule_end; + u32 elm_size, rule_size; + const void *msg_start; + u64 positive_bmp = 0; + u8 prev_sheet = 0; + u8 prev_seq = 0; + int limit; + + if (!elm) { + p += scnprintf(p, end - p, "No diag_mac entry\n"); + goto out; + } + + rule_size = le32_to_cpu(elm->u.diag_mac.rule_size); + elm_size = le32_to_cpu(elm->size); + + if (ALIGN(rule_size, 16) > elm_size) { + p += scnprintf(p, end - p, "rule size (%u) exceed elm_size (%u)\n", + ALIGN(rule_size, 16), elm_size); + goto out; + } + + rule = &elm->u.diag_mac.rules_and_msgs[0]; + rule_end = &elm->u.diag_mac.rules_and_msgs[rule_size]; + msg_start = &elm->u.diag_mac.rules_and_msgs[ALIGN(rule_size, 16)]; + + for (limit = 0; limit < 5000 && rule < rule_end; limit++) { + const struct __diag_mac_rule_header *rh = rule; + u8 sheet = rh->sheet; + u8 seq = rh->seq_major; + + if (!rtw89_mac_diag_match_hci(rtwdev, rh) || + !rtw89_mac_diag_match_band(rtwdev, rh)) { + n_ignore++; + goto next; + } + + if (!seq || prev_sheet != sheet || prev_seq != seq) { + if (positive_bmp) { + n_positive++; + /* + * discard output for negative results if one in + * a sequence set is positive. + */ + if (p_rewind) + p = p_rewind; + } + p_rewind = seq ? p : NULL; + positive_bmp = 0; + n_rules++; + } + + switch (rh->cmd) { + case __CMD_EQUALV: + case __CMD_NEQUALV: + p += rtw89_mac_diag_do_equalv(rtwdev, p, end - p, rule, + msg_start, &positive_bmp); + break; + case __CMD_INCREMENT: + p += rtw89_mac_diag_do_increment(rtwdev, p, end - p, rule, + msg_start, &positive_bmp); + break; + default: + p += scnprintf(p, end - p, "unknown rule cmd %u\n", rh->cmd); + break; + } + +next: + n_plains++; + rule += rh->len * 4; + prev_seq = seq; + prev_sheet = sheet; + } + + if (positive_bmp) { + n_positive++; + if (p_rewind) + p = p_rewind; + } + + p += scnprintf(p, end - p, "\nPlain(Ignore)/Rules/Positive: %u(%u)/%u/%u\n", + n_plains, n_ignore, n_rules, n_positive); + +out: + return p - buf; +} + +static ssize_t +rtw89_debug_priv_diag_mac_get(struct rtw89_dev *rtwdev, + struct rtw89_debugfs_priv *debugfs_priv, + char *buf, size_t bufsz) +{ + lockdep_assert_wiphy(rtwdev->hw->wiphy); + + rtw89_leave_lps(rtwdev); + + return rtw89_mac_diag_iter_all(rtwdev, buf, bufsz); +} + static ssize_t rtw89_debug_priv_beacon_info_get(struct rtw89_dev *rtwdev, struct rtw89_debugfs_priv *debugfs_priv, @@ -4478,6 +4775,7 @@ static const struct rtw89_debugfs rtw89_debugfs_templ = { .disable_dm = rtw89_debug_priv_set_and_get(disable_dm, RWLOCK), .mlo_mode = rtw89_debug_priv_set_and_get(mlo_mode, RWLOCK), .beacon_info = rtw89_debug_priv_get(beacon_info), + .diag_mac = rtw89_debug_priv_get(diag_mac, RSIZE_16K, RLOCK), }; #define rtw89_debugfs_add(name, mode, fopname, parent) \ @@ -4524,6 +4822,7 @@ void rtw89_debugfs_add_sec1(struct rtw89_dev *rtwdev, struct dentry *debugfs_top rtw89_debugfs_add_rw(disable_dm); rtw89_debugfs_add_rw(mlo_mode); rtw89_debugfs_add_r(beacon_info); + rtw89_debugfs_add_r(diag_mac); } void rtw89_debugfs_init(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 080c4f8a655a..7b9d9989e517 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -161,6 +161,11 @@ static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 le info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_W7_DYN_HDR); info->idmem_share_mode = le32_get_bits(fw_hdr->w7, FW_HDR_W7_IDMEM_SHARE_MODE); + if (chip->chip_gen == RTW89_CHIP_AX) + info->part_size = FWDL_SECTION_PER_PKT_LEN; + else + info->part_size = le32_get_bits(fw_hdr->w7, FW_HDR_W7_PART_SIZE); + if (info->dynamic_hdr_en) { info->hdr_len = le32_get_bits(fw_hdr->w3, FW_HDR_W3_LEN); info->dynamic_hdr_len = info->hdr_len - base_hdr_len; @@ -439,6 +444,7 @@ static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 le struct rtw89_fw_bin_info *info) { const struct rtw89_fw_hdr_v1 *fw_hdr = (const struct rtw89_fw_hdr_v1 *)fw; + const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_fw_hdr_section_info *section_info; const struct rtw89_fw_dynhdr_hdr *fwdynhdr; const struct rtw89_fw_hdr_section_v1 *section; @@ -455,6 +461,11 @@ static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 le info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_DYN_HDR); info->idmem_share_mode = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_IDMEM_SHARE_MODE); + if (chip->chip_gen == RTW89_CHIP_AX) + info->part_size = FWDL_SECTION_PER_PKT_LEN; + else + info->part_size = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_PART_SIZE); + if (info->dynamic_hdr_en) { info->hdr_len = le32_get_bits(fw_hdr->w5, FW_HDR_V1_W5_HDR_SIZE); info->dynamic_hdr_len = info->hdr_len - base_hdr_len; @@ -870,6 +881,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 76, 0, LPS_DACK_BY_C2H_REG), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 79, 0, CRASH_TRIGGER_TYPE_1), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 80, 0, BEACON_TRACKING), + __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 84, 0, ADDR_CAM_V0), }; static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw, @@ -1298,6 +1310,18 @@ int rtw89_build_afe_pwr_seq_from_elm(struct rtw89_dev *rtwdev, return 0; } +static +int rtw89_recognize_diag_mac_from_elm(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, + const union rtw89_fw_element_arg arg) +{ + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; + + elm_info->diag_mac = elm; + + return 0; +} + static const struct rtw89_fw_element_handler __fw_element_handlers[] = { [RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm, { .fw_type = RTW89_FW_BBMCU0 }, NULL}, @@ -1386,6 +1410,9 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = { [RTW89_FW_ELEMENT_ID_AFE_PWR_SEQ] = { rtw89_build_afe_pwr_seq_from_elm, {}, "AFE", }, + [RTW89_FW_ELEMENT_ID_DIAG_MAC] = { + rtw89_recognize_diag_mac_from_elm, {}, NULL, + }, }; int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev) @@ -1501,8 +1528,7 @@ static u32 __rtw89_fw_download_tweak_hdr_v0(struct rtw89_dev *rtwdev, struct rtw89_fw_hdr_section *section; int i; - le32p_replace_bits(&fw_hdr->w7, FWDL_SECTION_PER_PKT_LEN, - FW_HDR_W7_PART_SIZE); + le32p_replace_bits(&fw_hdr->w7, info->part_size, FW_HDR_W7_PART_SIZE); for (i = 0; i < info->section_num; i++) { section_info = &info->section_info[i]; @@ -1527,8 +1553,7 @@ static u32 __rtw89_fw_download_tweak_hdr_v1(struct rtw89_dev *rtwdev, u8 dst_sec_idx = 0; u8 sec_idx; - le32p_replace_bits(&fw_hdr->w7, FWDL_SECTION_PER_PKT_LEN, - FW_HDR_V1_W7_PART_SIZE); + le32p_replace_bits(&fw_hdr->w7, info->part_size, FW_HDR_V1_W7_PART_SIZE); for (sec_idx = 0; sec_idx < info->section_num; sec_idx++) { section_info = &info->section_info[sec_idx]; @@ -1630,7 +1655,8 @@ static int rtw89_fw_download_hdr(struct rtw89_dev *rtwdev, } static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev, - struct rtw89_fw_hdr_section_info *info) + struct rtw89_fw_hdr_section_info *info, + u32 part_size) { struct sk_buff *skb; const u8 *section = info->addr; @@ -1651,20 +1677,17 @@ static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev, } if (info->key_addr && info->key_len) { - if (residue_len > FWDL_SECTION_PER_PKT_LEN || info->len < info->key_len) + if (residue_len > part_size || info->len < info->key_len) rtw89_warn(rtwdev, "ignore to copy key data because of len %d, %d, %d, %d\n", - info->len, FWDL_SECTION_PER_PKT_LEN, + info->len, part_size, info->key_len, residue_len); else copy_key = true; } while (residue_len) { - if (residue_len >= FWDL_SECTION_PER_PKT_LEN) - pkt_len = FWDL_SECTION_PER_PKT_LEN; - else - pkt_len = residue_len; + pkt_len = min(residue_len, part_size); skb = rtw89_fw_h2c_alloc_skb_no_hdr(rtwdev, pkt_len); if (!skb) { @@ -1719,7 +1742,7 @@ static int rtw89_fw_download_main(struct rtw89_dev *rtwdev, int ret; while (section_num--) { - ret = __rtw89_fw_download_main(rtwdev, section_info); + ret = __rtw89_fw_download_main(rtwdev, section_info, info->part_size); if (ret) return ret; section_info++; @@ -2110,28 +2133,48 @@ plain_log: } -#define H2C_CAM_LEN 60 int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr) + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, + enum rtw89_upd_mode upd_mode) { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_h2c_addr_cam_v0 *h2c_v0; + struct rtw89_h2c_addr_cam *h2c; + u32 len = sizeof(*h2c); struct sk_buff *skb; + u8 ver = U8_MAX; int ret; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CAM_LEN); + if (RTW89_CHK_FW_FEATURE(ADDR_CAM_V0, &rtwdev->fw) || + chip->chip_gen == RTW89_CHIP_AX) { + len = sizeof(*h2c_v0); + ver = 0; + } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); return -ENOMEM; } - skb_put(skb, H2C_CAM_LEN); - rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link, scan_mac_addr, - skb->data); - rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, skb->data); + skb_put(skb, len); + h2c_v0 = (struct rtw89_h2c_addr_cam_v0 *)skb->data; + + rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link, + scan_mac_addr, h2c_v0); + rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, h2c_v0); + + if (ver == 0) + goto hdr; + h2c = (struct rtw89_h2c_addr_cam *)skb->data; + h2c->w15 = le32_encode_bits(upd_mode, ADDR_CAM_W15_UPD_MODE); + +hdr: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_ADDR_CAM_UPDATE, H2C_FUNC_MAC_ADDR_CAM_UPD, 0, 1, - H2C_CAM_LEN); + len); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { @@ -3165,6 +3208,7 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, SET_CMC_TBL_ANTSEL_C(skb->data, 0); SET_CMC_TBL_ANTSEL_D(skb->data, 0); } + SET_CMC_TBL_MGQ_RPT_EN(skb->data, rtwdev->hci.tx_rpt_enabled); SET_CMC_TBL_DOPPLER_CTRL(skb->data, 0); SET_CMC_TBL_TXPWR_TOLERENCE(skb->data, 0); if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) @@ -3210,7 +3254,8 @@ int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, h2c->c0 = le32_encode_bits(mac_id, CCTLINFO_G7_C0_MACID) | le32_encode_bits(1, CCTLINFO_G7_C0_OP); - h2c->w0 = le32_encode_bits(4, CCTLINFO_G7_W0_DATARATE); + h2c->w0 = le32_encode_bits(4, CCTLINFO_G7_W0_DATARATE) | + le32_encode_bits(rtwdev->hci.tx_rpt_enabled, CCTLINFO_G7_W0_MGQ_RPT_EN); h2c->m0 = cpu_to_le32(CCTLINFO_G7_W0_ALL); h2c->w1 = le32_encode_bits(4, CCTLINFO_G7_W1_DATA_RTY_LOWEST_RATE) | @@ -4715,13 +4760,16 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi struct rtw89_h2c_ra_v1 *h2c_v1; struct rtw89_h2c_ra *h2c; u32 len = sizeof(*h2c); - bool format_v1 = false; struct sk_buff *skb; + u8 ver = U8_MAX; int ret; - if (chip->chip_gen == RTW89_CHIP_BE) { + if (chip->chip_gen == RTW89_CHIP_AX) { + len = sizeof(*h2c); + ver = 0; + } else { len = sizeof(*h2c_v1); - format_v1 = true; + ver = 1; } skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); @@ -4753,16 +4801,8 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi h2c->w3 = le32_encode_bits(ra->fix_giltf_en, RTW89_H2C_RA_W3_FIX_GILTF_EN) | le32_encode_bits(ra->fix_giltf, RTW89_H2C_RA_W3_FIX_GILTF); - if (!format_v1) - goto csi; - - h2c_v1 = (struct rtw89_h2c_ra_v1 *)h2c; - h2c_v1->w4 = le32_encode_bits(ra->mode_ctrl, RTW89_H2C_RA_V1_W4_MODE_EHT) | - le32_encode_bits(ra->bw_cap, RTW89_H2C_RA_V1_W4_BW_EHT); - -csi: - if (!csi) - goto done; + if (!csi || ver >= 1) + goto next_v1; h2c->w2 |= le32_encode_bits(1, RTW89_H2C_RA_W2_BFEE_CSI_CTL); h2c->w3 |= le32_encode_bits(ra->band_num, RTW89_H2C_RA_W3_BAND_NUM) | @@ -4774,6 +4814,18 @@ csi: le32_encode_bits(ra->csi_gi_ltf, RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF) | le32_encode_bits(ra->csi_bw, RTW89_H2C_RA_W3_FIXED_CSI_BW); +next_v1: + if (ver < 1) + goto done; + + h2c->w3 |= le32_encode_bits(ra->partial_bw_er, + RTW89_H2C_RA_V1_W3_PARTIAL_BW_SU_ER) | + le32_encode_bits(ra->band, RTW89_H2C_RA_V1_W3_BAND); + + h2c_v1 = (struct rtw89_h2c_ra_v1 *)h2c; + h2c_v1->w4 = le32_encode_bits(ra->mode_ctrl, RTW89_H2C_RA_V1_W4_MODE_EHT) | + le32_encode_bits(ra->bw_cap, RTW89_H2C_RA_V1_W4_BW_EHT); + done: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RA, @@ -6891,11 +6943,18 @@ void rtw89_fw_c2h_work(struct wiphy *wiphy, struct wiphy_work *work) struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, c2h_work); struct sk_buff *skb, *tmp; + struct sk_buff_head c2hq; + unsigned long flags; lockdep_assert_wiphy(rtwdev->hw->wiphy); - skb_queue_walk_safe(&rtwdev->c2h_queue, skb, tmp) { - skb_unlink(skb, &rtwdev->c2h_queue); + __skb_queue_head_init(&c2hq); + + spin_lock_irqsave(&rtwdev->c2h_queue.lock, flags); + skb_queue_splice_init(&rtwdev->c2h_queue, &c2hq); + spin_unlock_irqrestore(&rtwdev->c2h_queue.lock, flags); + + skb_queue_walk_safe(&c2hq, skb, tmp) { rtw89_fw_c2h_cmd_handle(rtwdev, skb); dev_kfree_skb_any(skb); } @@ -6905,17 +6964,19 @@ void rtw89_fw_c2h_purge_obsoleted_scan_events(struct rtw89_dev *rtwdev) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct sk_buff *skb, *tmp; - int limit; + struct sk_buff_head c2hq; + unsigned long flags; lockdep_assert_wiphy(rtwdev->hw->wiphy); - limit = skb_queue_len(&rtwdev->c2h_queue); + __skb_queue_head_init(&c2hq); - skb_queue_walk_safe(&rtwdev->c2h_queue, skb, tmp) { - struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb); + spin_lock_irqsave(&rtwdev->c2h_queue.lock, flags); + skb_queue_splice_init(&rtwdev->c2h_queue, &c2hq); + spin_unlock_irqrestore(&rtwdev->c2h_queue.lock, flags); - if (--limit < 0) - return; + skb_queue_walk_safe(&c2hq, skb, tmp) { + struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb); if (!attr->is_scan_event || attr->scan_seq == scan_info->seq) continue; @@ -6924,9 +6985,13 @@ void rtw89_fw_c2h_purge_obsoleted_scan_events(struct rtw89_dev *rtwdev) "purge obsoleted scan event with seq=%d (cur=%d)\n", attr->scan_seq, scan_info->seq); - skb_unlink(skb, &rtwdev->c2h_queue); + __skb_unlink(skb, &c2hq); dev_kfree_skb_any(skb); } + + spin_lock_irqsave(&rtwdev->c2h_queue.lock, flags); + skb_queue_splice(&c2hq, &rtwdev->c2h_queue); + spin_unlock_irqrestore(&rtwdev->c2h_queue.lock, flags); } static int rtw89_fw_write_h2c_reg(struct rtw89_dev *rtwdev, @@ -7781,15 +7846,23 @@ int rtw89_hw_scan_prep_chan_list_be(struct rtw89_dev *rtwdev, struct ieee80211_channel *channel; struct list_head chan_list; enum rtw89_chan_type type; + bool chan_by_rnr; bool random_seq; int ret; u32 idx; random_seq = !!(req->flags & NL80211_SCAN_FLAG_RANDOM_SN); + chan_by_rnr = rtwdev->chip->support_rnr && + (req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ); INIT_LIST_HEAD(&chan_list); for (idx = 0; idx < req->n_channels; idx++) { channel = req->channels[idx]; + + if (channel->band == NL80211_BAND_6GHZ && + !cfg80211_channel_is_psc(channel) && chan_by_rnr) + continue; + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); if (!ch_info) { ret = -ENOMEM; @@ -8037,7 +8110,6 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct ieee80211_scan_request *scan_req) { - const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); struct cfg80211_scan_request *req = &scan_req->req; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, @@ -8049,7 +8121,6 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, }; u32 rx_fltr = rtwdev->hal.rx_fltr; u8 mac_addr[ETH_ALEN]; - u32 reg; int ret; /* clone op and keep it during scan */ @@ -8089,8 +8160,7 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, rx_fltr &= ~B_AX_A_BC; rx_fltr &= ~B_AX_A_A1_MATCH; - reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); - rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, rtwvif_link->mac_idx, rx_fltr); rtw89_chanctx_pause(rtwdev, &pause_parm); rtw89_phy_dig_suspend(rtwdev); @@ -8108,20 +8178,17 @@ struct rtw89_hw_scan_complete_cb_data { static int rtw89_hw_scan_complete_cb(struct rtw89_dev *rtwdev, void *data) { - const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); struct rtw89_hw_scan_complete_cb_data *cb_data = data; struct rtw89_vif_link *rtwvif_link = cb_data->rtwvif_link; struct cfg80211_scan_info info = { .aborted = cb_data->aborted, }; - u32 reg; if (!rtwvif_link) return -EINVAL; - reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); - rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, rtwvif_link->mac_idx, rtwdev->hal.rx_fltr); rtw89_core_scan_complete(rtwdev, rtwvif_link, true); ieee80211_scan_completed(rtwdev->hw, &info); diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index ddebf7972068..cedb4a47a769 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -297,6 +297,7 @@ struct rtw89_fw_hdr_section_info { struct rtw89_fw_bin_info { u8 section_num; + u32 part_size; u32 hdr_len; bool dynamic_hdr_en; u32 dynamic_hdr_len; @@ -446,6 +447,13 @@ struct rtw89_h2c_ra { #define RTW89_H2C_RA_W3_FIXED_CSI_MODE GENMASK(25, 24) #define RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF GENMASK(28, 26) #define RTW89_H2C_RA_W3_FIXED_CSI_BW GENMASK(31, 29) +#define RTW89_H2C_RA_V1_W3_PARTIAL_BW_SU_ER BIT(15) +#define RTW89_H2C_RA_V1_W3_FIXED_CSI_RATE_L GENMASK(23, 16) +#define RTW89_H2C_RA_V1_W3_IS_NOISY BIT(24) +#define RTW89_H2C_RA_V1_W3_PSRA_EN BIT(25) +#define RTW89_H2C_RA_V1_W3_MACID_MSB GENMASK(28, 27) +#define RTW89_H2C_RA_V1_W3_BAND GENMASK(30, 29) +#define RTW89_H2C_RA_V1_W3_NEW_DBGREG BIT(31) struct rtw89_h2c_ra_v1 { struct rtw89_h2c_ra v0; @@ -3647,6 +3655,15 @@ struct rtw89_fw_c2h_log_fmt { #define RTW89_C2H_FW_LOG_SIGNATURE 0xA5A5 #define RTW89_C2H_FW_LOG_STR_BUF_SIZE 512 +struct rtw89_c2h_bcn_upd_done { + struct rtw89_c2h_hdr hdr; + __le32 w2; +} __packed; + +#define RTW89_C2H_BCN_UPD_DONE_W2_PORT GENMASK(2, 0) +#define RTW89_C2H_BCN_UPD_DONE_W2_MBSSID GENMASK(6, 3) +#define RTW89_C2H_BCN_UPD_DONE_W2_BAND_IDX BIT(7) + struct rtw89_c2h_mac_bcnfltr_rpt { __le32 w0; __le32 w1; @@ -3747,6 +3764,47 @@ struct rtw89_c2h_scanofld { #define RTW89_GET_MAC_C2H_MCC_REQ_ACK_H2C_FUNC(c2h) \ le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(15, 8)) +struct rtw89_c2h_mac_tx_rpt { + struct rtw89_c2h_hdr hdr; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; +} __packed; + +#define RTW89_C2H_MAC_TX_RPT_W2_TX_STATE GENMASK(7, 6) +#define RTW89_C2H_MAC_TX_RPT_W2_SW_DEFINE GENMASK(11, 8) +#define RTW89_C2H_MAC_TX_RPT_W5_DATA_TX_CNT GENMASK(13, 8) +#define RTW89_C2H_MAC_TX_RPT_W5_DATA_TX_CNT_V1 GENMASK(15, 10) + +struct rtw89_c2h_mac_tx_rpt_v2 { + struct rtw89_c2h_hdr hdr; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; + __le32 w8; + __le32 w9; + __le32 w10; + __le32 w11; + __le32 w12; + __le32 w13; + __le32 w14; + __le32 w15; + __le32 w16; + __le32 w17; + __le32 w18; + __le32 w19; +} __packed; + +#define RTW89_C2H_MAC_TX_RPT_W12_TX_STATE_V2 GENMASK(9, 8) +#define RTW89_C2H_MAC_TX_RPT_W12_SW_DEFINE_V2 GENMASK(15, 12) +#define RTW89_C2H_MAC_TX_RPT_W14_DATA_TX_CNT_V2 GENMASK(15, 10) + struct rtw89_mac_mcc_tsf_rpt { u32 macid_x; u32 macid_y; @@ -3985,6 +4043,7 @@ enum rtw89_fw_element_id { RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_5GHZ = 25, RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_6GHZ = 26, RTW89_FW_ELEMENT_ID_AFE_PWR_SEQ = 27, + RTW89_FW_ELEMENT_ID_DIAG_MAC = 28, RTW89_FW_ELEMENT_ID_NUM, }; @@ -4162,6 +4221,11 @@ struct rtw89_fw_element_hdr { __le32 val; } __packed infos[]; } __packed afe; + struct { + __le32 rule_size; + u8 rsvd[4]; + u8 rules_and_msgs[]; + } __packed diag_mac; struct __rtw89_fw_txpwr_element txpwr; struct __rtw89_fw_regd_element regd; } __packed u; @@ -4823,7 +4887,8 @@ int rtw89_fw_h2c_tbtt_tuning(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 offset); int rtw89_fw_h2c_pwr_lvl(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif, - struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr); + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, + enum rtw89_upd_mode upd_mode); int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link); diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index fd11b8fb3c89..d78fbe73e365 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -12,6 +12,7 @@ #include "phy.h" #include "ps.h" #include "reg.h" +#include "ser.h" #include "util.h" static const u32 rtw89_mac_mem_base_addrs_ax[RTW89_MAC_MEM_NUM] = { @@ -1294,11 +1295,26 @@ static int rtw89_mac_sub_pwr_seq(struct rtw89_dev *rtwdev, u8 cv_msk, static int rtw89_mac_pwr_seq(struct rtw89_dev *rtwdev, const struct rtw89_pwr_cfg * const *cfg_seq) { + u8 intf_msk; int ret; + switch (rtwdev->hci.type) { + case RTW89_HCI_TYPE_PCIE: + intf_msk = PWR_INTF_MSK_PCIE; + break; + case RTW89_HCI_TYPE_USB: + intf_msk = PWR_INTF_MSK_USB; + break; + case RTW89_HCI_TYPE_SDIO: + intf_msk = PWR_INTF_MSK_SDIO; + break; + default: + return -EOPNOTSUPP; + } + for (; *cfg_seq; cfg_seq++) { ret = rtw89_mac_sub_pwr_seq(rtwdev, BIT(rtwdev->hal.cv), - PWR_INTF_MSK_PCIE, *cfg_seq); + intf_msk, *cfg_seq); if (ret) return -EBUSY; } @@ -1423,13 +1439,15 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter) if (!ret) break; - if (i == RPWM_TRY_CNT - 1) + if (i == RPWM_TRY_CNT - 1) { rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n", enter ? "entering" : "leaving"); - else + rtw89_ser_notify(rtwdev, MAC_AX_ERR_ASSERTION); + } else { rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "%d time firmware failed to ack for %s ps mode\n", i + 1, enter ? "entering" : "leaving"); + } } } @@ -1651,6 +1669,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = { /* PCIE 64 */ .wde_size0 = {RTW89_WDE_PG_64, 4095, 1,}, .wde_size0_v1 = {RTW89_WDE_PG_64, 3328, 0, 0,}, + /* 8852A USB */ + .wde_size1 = {RTW89_WDE_PG_64, 768, 0,}, /* DLFW */ .wde_size4 = {RTW89_WDE_PG_64, 0, 4096,}, .wde_size4_v1 = {RTW89_WDE_PG_64, 0, 3328, 0,}, @@ -1660,6 +1680,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .wde_size7 = {RTW89_WDE_PG_64, 510, 2,}, /* DLFW */ .wde_size9 = {RTW89_WDE_PG_64, 0, 1024,}, + /* 8852C USB3.0 */ + .wde_size17 = {RTW89_WDE_PG_64, 354, 30,}, /* 8852C DLFW */ .wde_size18 = {RTW89_WDE_PG_64, 0, 2048,}, /* 8852C PCIE SCC */ @@ -1667,9 +1689,13 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .wde_size23 = {RTW89_WDE_PG_64, 1022, 2,}, /* 8852B USB2.0/USB3.0 SCC */ .wde_size25 = {RTW89_WDE_PG_64, 162, 94,}, + /* 8852C USB2.0 */ + .wde_size31 = {RTW89_WDE_PG_64, 384, 0,}, /* PCIE */ .ple_size0 = {RTW89_PLE_PG_128, 1520, 16,}, .ple_size0_v1 = {RTW89_PLE_PG_128, 2688, 240, 212992,}, + /* 8852A USB */ + .ple_size1 = {RTW89_PLE_PG_128, 3184, 16,}, .ple_size3_v1 = {RTW89_PLE_PG_128, 2928, 0, 212992,}, /* DLFW */ .ple_size4 = {RTW89_PLE_PG_128, 64, 1472,}, @@ -1678,6 +1704,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = { /* DLFW */ .ple_size8 = {RTW89_PLE_PG_128, 64, 960,}, .ple_size9 = {RTW89_PLE_PG_128, 2288, 16,}, + /* 8852C USB */ + .ple_size17 = {RTW89_PLE_PG_128, 3368, 24,}, /* 8852C DLFW */ .ple_size18 = {RTW89_PLE_PG_128, 2544, 16,}, /* 8852C PCIE SCC */ @@ -1686,15 +1714,21 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .ple_size32 = {RTW89_PLE_PG_128, 620, 20,}, /* 8852B USB3.0 SCC */ .ple_size33 = {RTW89_PLE_PG_128, 632, 8,}, + /* 8852C USB2.0 */ + .ple_size34 = {RTW89_PLE_PG_128, 3374, 18,}, /* PCIE 64 */ .wde_qt0 = {3792, 196, 0, 107,}, .wde_qt0_v1 = {3302, 6, 0, 20,}, + /* 8852A USB */ + .wde_qt1 = {512, 196, 0, 60,}, /* DLFW */ .wde_qt4 = {0, 0, 0, 0,}, /* PCIE 64 */ .wde_qt6 = {448, 48, 0, 16,}, /* 8852B PCIE SCC */ .wde_qt7 = {446, 48, 0, 16,}, + /* 8852C USB3.0 */ + .wde_qt16 = {344, 2, 0, 8,}, /* 8852C DLFW */ .wde_qt17 = {0, 0, 0, 0,}, /* 8852C PCIE SCC */ @@ -1702,6 +1736,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .wde_qt23 = {958, 48, 0, 16,}, /* 8852B USB2.0/USB3.0 SCC */ .wde_qt25 = {152, 2, 0, 8,}, + /* 8852C USB2.0 */ + .wde_qt31 = {338, 6, 0, 40,}, .ple_qt0 = {320, 320, 32, 16, 13, 13, 292, 292, 64, 18, 1, 4, 0,}, .ple_qt1 = {320, 320, 32, 16, 1316, 1316, 1595, 1595, 1367, 1321, 1, 1307, 0,}, /* PCIE SCC */ @@ -1713,6 +1749,13 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .ple_qt13 = {0, 0, 16, 48, 0, 0, 0, 0, 0, 0, 0,}, /* PCIE 64 */ .ple_qt18 = {147, 0, 16, 20, 17, 13, 89, 0, 32, 14, 8, 0,}, + /* 8852A USB SCC */ + .ple_qt25 = {1536, 0, 16, 48, 13, 13, 360, 0, 32, 40, 8, 0,}, + .ple_qt26 = {2654, 0, 1134, 48, 64, 13, 1478, 0, 64, 128, 120, 0,}, + /* USB 52C USB3.0 */ + .ple_qt42 = {1068, 0, 16, 48, 4, 13, 178, 0, 16, 1, 8, 16, 0,}, + /* USB 52C USB3.0 */ + .ple_qt43 = {3068, 0, 32, 48, 4, 13, 178, 0, 16, 1, 8, 16, 0,}, /* DLFW 52C */ .ple_qt44 = {0, 0, 16, 256, 0, 0, 0, 0, 0, 0, 0, 0,}, /* DLFW 52C */ @@ -1732,6 +1775,10 @@ const struct rtw89_mac_size_set rtw89_mac_size = { /* USB3.0 52B 92K */ .ple_qt74 = {286, 0, 16, 48, 4, 13, 178, 0, 32, 14, 8, 0, 0,}, .ple_qt75 = {286, 0, 32, 48, 37, 13, 211, 0, 65, 14, 24, 0, 0,}, + /* USB2.0 52C */ + .ple_qt78 = {1560, 0, 16, 48, 13, 13, 390, 0, 32, 38, 8, 16, 0,}, + /* USB2.0 52C */ + .ple_qt79 = {1560, 0, 32, 48, 1253, 13, 1630, 0, 1272, 38, 120, 1256, 0,}, /* 8852A PCIE WOW */ .ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,}, /* 8852B PCIE WOW */ @@ -2324,7 +2371,8 @@ static int sec_eng_init_ax(struct rtw89_dev *rtwdev) if (chip->chip_id == RTL8852C) val |= B_AX_UC_MGNT_DEC; if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B || - chip->chip_id == RTL8851B) + chip->chip_id == RTL8851B || + (chip->chip_id == RTL8852C && rtwdev->hci.type == RTW89_HCI_TYPE_USB)) val &= ~B_AX_TX_PARTIAL_MODE; rtw89_write32(rtwdev, R_AX_SEC_ENG_CTRL, val); @@ -2495,6 +2543,20 @@ static int rtw89_mac_typ_fltr_opt_ax(struct rtw89_dev *rtwdev, return 0; } +void rtw89_mac_set_rx_fltr(struct rtw89_dev *rtwdev, u8 mac_idx, u32 rx_fltr) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + u32 reg; + u32 val; + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, mac_idx); + + val = rtw89_read32(rtwdev, reg); + /* B_AX_RX_FLTR_CFG_MASK is not a consecutive bit mask */ + val = (val & ~B_AX_RX_FLTR_CFG_MASK) | (rx_fltr & B_AX_RX_FLTR_CFG_MASK); + rtw89_write32(rtwdev, reg, val); +} + static int rx_fltr_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx) { int ret, i; @@ -3980,8 +4042,15 @@ static void rtw89_mac_dmac_func_pre_en_ax(struct rtw89_dev *rtwdev) val = rtw89_read32(rtwdev, R_AX_HAXI_INIT_CFG1); val &= ~(B_AX_DMA_MODE_MASK | B_AX_STOP_AXI_MST); - val |= FIELD_PREP(B_AX_DMA_MODE_MASK, DMA_MOD_PCIE_1B) | - B_AX_TXHCI_EN_V1 | B_AX_RXHCI_EN_V1; + val |= B_AX_TXHCI_EN_V1 | B_AX_RXHCI_EN_V1; + + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + val |= FIELD_PREP(B_AX_DMA_MODE_MASK, DMA_MOD_PCIE_1B); + else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) + val |= FIELD_PREP(B_AX_DMA_MODE_MASK, DMA_MOD_USB); + else + val |= FIELD_PREP(B_AX_DMA_MODE_MASK, DMA_MOD_SDIO); + rtw89_write32(rtwdev, R_AX_HAXI_INIT_CFG1, val); rtw89_write32_clr(rtwdev, R_AX_HAXI_DMA_STOP1, @@ -4049,9 +4118,12 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb) rtw89_mac_ctrl_hci_dma_trx(rtwdev, true); if (include_bb) { - rtw89_chip_bb_preinit(rtwdev, RTW89_PHY_0); - if (rtwdev->dbcc_en) - rtw89_chip_bb_preinit(rtwdev, RTW89_PHY_1); + /* Only call BB preinit including configuration of BB MCU for + * the chips which need to download BB MCU firmware. Otherwise, + * calling preinit later to prevent touching registers affecting + * download firmware. + */ + rtw89_chip_bb_preinit(rtwdev); } ret = rtw89_mac_dmac_pre_init(rtwdev); @@ -4071,17 +4143,24 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb) return 0; } -int rtw89_mac_init(struct rtw89_dev *rtwdev) +int rtw89_mac_preinit(struct rtw89_dev *rtwdev) { - const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; - const struct rtw89_chip_info *chip = rtwdev->chip; - bool include_bb = !!chip->bbmcu_nr; int ret; ret = rtw89_mac_pwr_on(rtwdev); if (ret) return ret; + return 0; +} + +int rtw89_mac_init(struct rtw89_dev *rtwdev) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_chip_info *chip = rtwdev->chip; + bool include_bb = !!chip->bbmcu_nr; + int ret; + ret = rtw89_mac_partial_init(rtwdev, include_bb); if (ret) goto fail; @@ -4770,7 +4849,7 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l if (ret) return ret; - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_CREATE); if (ret) return ret; @@ -4795,7 +4874,7 @@ int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif rtw89_cam_deinit(rtwdev, rtwvif_link); - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_REMOVE); if (ret) return ret; @@ -5244,8 +5323,19 @@ rtw89_mac_c2h_bcn_cnt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) } static void -rtw89_mac_c2h_bcn_upd_done(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +rtw89_mac_c2h_bcn_upd_done(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len) { + const struct rtw89_c2h_bcn_upd_done *c2h = + (const struct rtw89_c2h_bcn_upd_done *)skb_c2h->data; + u8 band, port, mbssid; + + port = le32_get_bits(c2h->w2, RTW89_C2H_BCN_UPD_DONE_W2_PORT); + mbssid = le32_get_bits(c2h->w2, RTW89_C2H_BCN_UPD_DONE_W2_MBSSID); + band = le32_get_bits(c2h->w2, RTW89_C2H_BCN_UPD_DONE_W2_BAND_IDX); + + rtw89_debug(rtwdev, RTW89_DBG_FW, + "BCN update done on port:%d mbssid:%d band:%d\n", + port, mbssid, band); } static void @@ -5458,6 +5548,72 @@ rtw89_mac_c2h_mcc_status_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 } static void +rtw89_mac_c2h_tx_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +{ + struct rtw89_tx_rpt *tx_rpt = &rtwdev->tx_rpt; + struct rtw89_tx_skb_data *skb_data; + u8 sw_define, tx_status, txcnt; + struct sk_buff *skb; + + if (rtwdev->chip->chip_id == RTL8922A) { + const struct rtw89_c2h_mac_tx_rpt_v2 *rpt_v2; + + rpt_v2 = (const struct rtw89_c2h_mac_tx_rpt_v2 *)c2h->data; + sw_define = le32_get_bits(rpt_v2->w12, + RTW89_C2H_MAC_TX_RPT_W12_SW_DEFINE_V2); + tx_status = le32_get_bits(rpt_v2->w12, + RTW89_C2H_MAC_TX_RPT_W12_TX_STATE_V2); + txcnt = le32_get_bits(rpt_v2->w14, + RTW89_C2H_MAC_TX_RPT_W14_DATA_TX_CNT_V2); + } else { + const struct rtw89_c2h_mac_tx_rpt *rpt; + + rpt = (const struct rtw89_c2h_mac_tx_rpt *)c2h->data; + sw_define = le32_get_bits(rpt->w2, RTW89_C2H_MAC_TX_RPT_W2_SW_DEFINE); + tx_status = le32_get_bits(rpt->w2, RTW89_C2H_MAC_TX_RPT_W2_TX_STATE); + if (rtwdev->chip->chip_id == RTL8852C) + txcnt = le32_get_bits(rpt->w5, + RTW89_C2H_MAC_TX_RPT_W5_DATA_TX_CNT_V1); + else + txcnt = le32_get_bits(rpt->w5, + RTW89_C2H_MAC_TX_RPT_W5_DATA_TX_CNT); + } + + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "C2H TX RPT: sn %d, tx_status %d, txcnt %d\n", + sw_define, tx_status, txcnt); + + /* claim sw_define is not over size of tx_rpt->skbs[] */ + static_assert(hweight32(RTW89_MAX_TX_RPTS_MASK) == + hweight32(RTW89_C2H_MAC_TX_RPT_W12_SW_DEFINE_V2) && + hweight32(RTW89_MAX_TX_RPTS_MASK) == + hweight32(RTW89_C2H_MAC_TX_RPT_W2_SW_DEFINE)); + + scoped_guard(spinlock_irqsave, &tx_rpt->skb_lock) { + skb = tx_rpt->skbs[sw_define]; + + /* skip if no skb (normally shouldn't happen) */ + if (!skb) { + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "C2H TX RPT: no skb found in queue\n"); + return; + } + + skb_data = RTW89_TX_SKB_CB(skb); + + /* skip if TX attempt has failed and retry limit has not been + * reached yet + */ + if (tx_status != RTW89_TX_DONE && + txcnt != skb_data->tx_pkt_cnt_lmt) + return; + + tx_rpt->skbs[sw_define] = NULL; + rtw89_tx_rpt_tx_status(rtwdev, skb, tx_status); + } +} + +static void rtw89_mac_c2h_mrc_tsf_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { struct rtw89_wait_info *wait = &rtwdev->mcc.wait; @@ -5692,6 +5848,12 @@ void (* const rtw89_mac_c2h_mcc_handler[])(struct rtw89_dev *rtwdev, }; static +void (* const rtw89_mac_c2h_misc_handler[])(struct rtw89_dev *rtwdev, + struct sk_buff *c2h, u32 len) = { + [RTW89_MAC_C2H_FUNC_TX_REPORT] = rtw89_mac_c2h_tx_rpt, +}; + +static void (* const rtw89_mac_c2h_mlo_handler[])(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) = { [RTW89_MAC_C2H_FUNC_MLO_GET_TBL] = NULL, @@ -5777,6 +5939,8 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h, } case RTW89_MAC_C2H_CLASS_MCC: return true; + case RTW89_MAC_C2H_CLASS_MISC: + return true; case RTW89_MAC_C2H_CLASS_MLO: return true; case RTW89_MAC_C2H_CLASS_MRC: @@ -5812,6 +5976,10 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MCC) handler = rtw89_mac_c2h_mcc_handler[func]; break; + case RTW89_MAC_C2H_CLASS_MISC: + if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MISC) + handler = rtw89_mac_c2h_misc_handler[func]; + break; case RTW89_MAC_C2H_CLASS_MLO: if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MLO) handler = rtw89_mac_c2h_mlo_handler[func]; diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 25fe5e5c8a97..0007229d6753 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -432,6 +432,12 @@ enum rtw89_mac_c2h_mcc_func { NUM_OF_RTW89_MAC_C2H_FUNC_MCC, }; +enum rtw89_mac_c2h_misc_func { + RTW89_MAC_C2H_FUNC_TX_REPORT = 1, + + NUM_OF_RTW89_MAC_C2H_FUNC_MISC, +}; + enum rtw89_mac_c2h_mlo_func { RTW89_MAC_C2H_FUNC_MLO_GET_TBL = 0x0, RTW89_MAC_C2H_FUNC_MLO_EMLSR_TRANS_DONE = 0x1, @@ -470,6 +476,7 @@ enum rtw89_mac_c2h_class { RTW89_MAC_C2H_CLASS_WOW = 0x3, RTW89_MAC_C2H_CLASS_MCC = 0x4, RTW89_MAC_C2H_CLASS_FWDBG = 0x5, + RTW89_MAC_C2H_CLASS_MISC = 0x9, RTW89_MAC_C2H_CLASS_MLO = 0xc, RTW89_MAC_C2H_CLASS_MRC = 0xe, RTW89_MAC_C2H_CLASS_AP = 0x18, @@ -574,8 +581,6 @@ enum rtw89_mac_bf_rrsc_rate { RTW89_MAC_BF_RRSC_MAX = 32 }; -#define RTW89_R32_EA 0xEAEAEAEA -#define RTW89_R32_DEAD 0xDEADBEEF #define MAC_REG_POOL_COUNT 10 #define ACCESS_CMAC(_addr) \ ({typeof(_addr) __addr = (_addr); \ @@ -917,36 +922,45 @@ struct rtw89_mac_size_set { const struct rtw89_hfc_prec_cfg hfc_prec_cfg_c0; const struct rtw89_hfc_prec_cfg hfc_prec_cfg_c2; const struct rtw89_dle_size wde_size0; + const struct rtw89_dle_size wde_size1; const struct rtw89_dle_size wde_size0_v1; const struct rtw89_dle_size wde_size4; const struct rtw89_dle_size wde_size4_v1; const struct rtw89_dle_size wde_size6; const struct rtw89_dle_size wde_size7; const struct rtw89_dle_size wde_size9; + const struct rtw89_dle_size wde_size17; const struct rtw89_dle_size wde_size18; const struct rtw89_dle_size wde_size19; const struct rtw89_dle_size wde_size23; const struct rtw89_dle_size wde_size25; + const struct rtw89_dle_size wde_size31; const struct rtw89_dle_size ple_size0; + const struct rtw89_dle_size ple_size1; const struct rtw89_dle_size ple_size0_v1; const struct rtw89_dle_size ple_size3_v1; const struct rtw89_dle_size ple_size4; const struct rtw89_dle_size ple_size6; const struct rtw89_dle_size ple_size8; const struct rtw89_dle_size ple_size9; + const struct rtw89_dle_size ple_size17; const struct rtw89_dle_size ple_size18; const struct rtw89_dle_size ple_size19; const struct rtw89_dle_size ple_size32; const struct rtw89_dle_size ple_size33; + const struct rtw89_dle_size ple_size34; const struct rtw89_wde_quota wde_qt0; + const struct rtw89_wde_quota wde_qt1; const struct rtw89_wde_quota wde_qt0_v1; const struct rtw89_wde_quota wde_qt4; const struct rtw89_wde_quota wde_qt6; const struct rtw89_wde_quota wde_qt7; + const struct rtw89_wde_quota wde_qt16; const struct rtw89_wde_quota wde_qt17; const struct rtw89_wde_quota wde_qt18; const struct rtw89_wde_quota wde_qt23; const struct rtw89_wde_quota wde_qt25; + const struct rtw89_wde_quota wde_qt31; const struct rtw89_ple_quota ple_qt0; const struct rtw89_ple_quota ple_qt1; const struct rtw89_ple_quota ple_qt4; @@ -954,6 +968,10 @@ struct rtw89_mac_size_set { const struct rtw89_ple_quota ple_qt9; const struct rtw89_ple_quota ple_qt13; const struct rtw89_ple_quota ple_qt18; + const struct rtw89_ple_quota ple_qt25; + const struct rtw89_ple_quota ple_qt26; + const struct rtw89_ple_quota ple_qt42; + const struct rtw89_ple_quota ple_qt43; const struct rtw89_ple_quota ple_qt44; const struct rtw89_ple_quota ple_qt45; const struct rtw89_ple_quota ple_qt46; @@ -965,6 +983,8 @@ struct rtw89_mac_size_set { const struct rtw89_ple_quota ple_qt73; const struct rtw89_ple_quota ple_qt74; const struct rtw89_ple_quota ple_qt75; + const struct rtw89_ple_quota ple_qt78; + const struct rtw89_ple_quota ple_qt79; const struct rtw89_ple_quota ple_qt_52a_wow; const struct rtw89_ple_quota ple_qt_52b_wow; const struct rtw89_ple_quota ple_qt_52bt_wow; @@ -1181,6 +1201,7 @@ rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev); void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev); int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb); +int rtw89_mac_preinit(struct rtw89_dev *rtwdev); int rtw89_mac_init(struct rtw89_dev *rtwdev); int rtw89_mac_dle_init(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode, enum rtw89_qta_mode ext_mode); @@ -1319,6 +1340,7 @@ int rtw89_mac_cfg_ppdu_status_bands(struct rtw89_dev *rtwdev, bool enable) return rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_1, enable); } +void rtw89_mac_set_rx_fltr(struct rtw89_dev *rtwdev, u8 mac_idx, u32 rx_fltr); void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev); void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop); int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex *coex); @@ -1609,4 +1631,92 @@ int rtw89_mac_scan_offload(struct rtw89_dev *rtwdev, return ret; } + +static inline +void rtw89_tx_rpt_init(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) +{ + struct rtw89_tx_rpt *tx_rpt = &rtwdev->tx_rpt; + + if (!rtwdev->hci.tx_rpt_enabled) + return; + + tx_req->desc_info.report = true; + /* firmware maintains a 4-bit sequence number */ + tx_req->desc_info.sn = atomic_inc_return(&tx_rpt->sn) & + RTW89_MAX_TX_RPTS_MASK; + tx_req->desc_info.tx_cnt_lmt_en = true; + tx_req->desc_info.tx_cnt_lmt = 8; +} + +static inline +bool rtw89_is_tx_rpt_skb(struct rtw89_dev *rtwdev, struct sk_buff *skb) +{ + struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + return rtw89_core_is_tx_wait(rtwdev, skb_data) || + (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS); +} + +static inline +void rtw89_tx_rpt_tx_status(struct rtw89_dev *rtwdev, struct sk_buff *skb, + u8 tx_status) +{ + struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); + struct ieee80211_tx_info *info; + + if (rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status)) + return; + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + + if (tx_status == RTW89_TX_DONE) + info->flags |= IEEE80211_TX_STAT_ACK; + else + info->flags &= ~IEEE80211_TX_STAT_ACK; + + ieee80211_tx_status_irqsafe(rtwdev->hw, skb); +} + +static inline +void rtw89_tx_rpt_skb_add(struct rtw89_dev *rtwdev, struct sk_buff *skb) +{ + struct rtw89_tx_rpt *tx_rpt = &rtwdev->tx_rpt; + struct rtw89_tx_skb_data *skb_data; + u8 idx; + + skb_data = RTW89_TX_SKB_CB(skb); + idx = skb_data->tx_rpt_sn; + + scoped_guard(spinlock_irqsave, &tx_rpt->skb_lock) { + /* if skb having the similar seq number is still in the queue, + * this means the queue is overflowed - it isn't normal and + * should indicate firmware doesn't provide TX reports in time; + * report the old skb as dropped, we can't do much more here + */ + if (tx_rpt->skbs[idx]) + rtw89_tx_rpt_tx_status(rtwdev, tx_rpt->skbs[idx], + RTW89_TX_MACID_DROP); + tx_rpt->skbs[idx] = skb; + } +} + +static inline +void rtw89_tx_rpt_skbs_purge(struct rtw89_dev *rtwdev) +{ + struct rtw89_tx_rpt *tx_rpt = &rtwdev->tx_rpt; + struct sk_buff *skbs[RTW89_MAX_TX_RPTS]; + + scoped_guard(spinlock_irqsave, &tx_rpt->skb_lock) { + memcpy(skbs, tx_rpt->skbs, sizeof(tx_rpt->skbs)); + memset(tx_rpt->skbs, 0, sizeof(tx_rpt->skbs)); + } + + for (int i = 0; i < ARRAY_SIZE(skbs); i++) + if (skbs[i]) + rtw89_tx_rpt_tx_status(rtwdev, skbs[i], + RTW89_TX_MACID_DROP); +} #endif diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 7b04183a3a5d..f39ca1c2ed10 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -220,6 +220,8 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, if (ret) goto unset_link; + rtwdev->pure_monitor_mode_vif = vif->type == NL80211_IFTYPE_MONITOR ? + rtwvif : NULL; rtw89_recalc_lps(rtwdev); return 0; @@ -267,6 +269,8 @@ bottom: rtw89_core_release_bit_map(rtwdev->hw_port, port); rtw89_release_mac_id(rtwdev, macid); + rtwdev->pure_monitor_mode_vif = NULL; + rtw89_recalc_lps(rtwdev); rtw89_enter_ips_by_hwflags(rtwdev); } @@ -303,7 +307,6 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw, u64 multicast) { struct rtw89_dev *rtwdev = hw->priv; - const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; u32 rx_fltr; lockdep_assert_wiphy(hw->wiphy); @@ -365,16 +368,10 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw, rx_fltr &= ~B_AX_A_A1_MATCH; } - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_RX_FLTR_CFG_MASK, - rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, RTW89_MAC_0, rx_fltr); if (!rtwdev->dbcc_en) return; - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_1), - B_AX_RX_FLTR_CFG_MASK, - rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, RTW89_MAC_1, rx_fltr); } static const u8 ac_to_fw_idx[IEEE80211_NUM_ACS] = { @@ -718,6 +715,17 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ARP_FILTER) rtwvif->ip_addr = vif->cfg.arp_addr_list[0]; + + if (changed & BSS_CHANGED_MLD_VALID_LINKS) { + struct rtw89_vif_link *cur = rtw89_get_designated_link(rtwvif); + + rtw89_chip_rfk_channel(rtwdev, cur); + + if (hweight16(vif->active_links) == 1) + rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR; + else + rtwvif->mlo_mode = RTW89_MLO_MODE_EMLSR; + } } static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, @@ -744,7 +752,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID) { ether_addr_copy(rtwvif_link->bssid, conf->bssid); rtw89_cam_bssid_changed(rtwdev, rtwvif_link); - rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_INFO_CHANGE); WRITE_ONCE(rtwvif_link->sync_bcn_tsf, 0); } @@ -803,7 +811,7 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL); rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_TYPE_CHANGE); rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); - rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_TYPE_CHANGE); rtw89_chip_rfk_channel(rtwdev, rtwvif_link); if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw)) { @@ -954,6 +962,7 @@ static int rtw89_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } break; case DISABLE_KEY: + flush_work(&rtwdev->txq_work); rtw89_hci_flush_queues(rtwdev, BIT(rtwdev->hw->queues) - 1, false); rtw89_mac_flush_txq(rtwdev, BIT(rtwdev->hw->queues) - 1, false); @@ -1132,12 +1141,17 @@ int rtw89_ops_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant, u3 { struct rtw89_dev *rtwdev = hw->priv; struct rtw89_hal *hal = &rtwdev->hal; + const struct rtw89_chip_info *chip; lockdep_assert_wiphy(hw->wiphy); + chip = rtwdev->chip; + if (hal->ant_diversity) { if (tx_ant != rx_ant || hweight32(tx_ant) != 1) return -EINVAL; + } else if (chip->ops->cfg_txrx_path) { + /* With cfg_txrx_path ops, chips can configure rx_ant */ } else if (rx_ant != hw->wiphy->available_antennas_rx && rx_ant != hal->antenna_rx) { return -EINVAL; } @@ -1531,10 +1545,29 @@ static bool rtw89_ops_can_activate_links(struct ieee80211_hw *hw, u16 active_links) { struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + u16 current_links = vif->active_links; + struct rtw89_vif_ml_trans trans = { + .mediate_links = current_links | active_links, + .links_to_del = current_links & ~active_links, + .links_to_add = active_links & ~current_links, + }; lockdep_assert_wiphy(hw->wiphy); - return rtw89_can_work_on_links(rtwdev, vif, active_links); + if (!rtw89_can_work_on_links(rtwdev, vif, active_links)) + return false; + + /* + * Leave LPS at the beginning of ieee80211_set_active_links(). + * Because the entire process takes the same lock as our track + * work, LPS will not enter during ieee80211_set_active_links(). + */ + rtw89_leave_lps(rtwdev); + + rtwvif->ml_trans = trans; + + return true; } static void __rtw89_ops_clr_vif_links(struct rtw89_dev *rtwdev, @@ -1579,6 +1612,36 @@ static int __rtw89_ops_set_vif_links(struct rtw89_dev *rtwdev, return 0; } +static void rtw89_vif_cfg_fw_links(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + unsigned long links, bool en) +{ + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + rtwvif_link = rtwvif->links[link_id]; + if (unlikely(!rtwvif_link)) + continue; + + rtw89_fw_h2c_mlo_link_cfg(rtwdev, rtwvif_link, en); + } +} + +static void rtw89_vif_update_fw_links(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + u16 current_links) +{ + struct rtw89_vif_ml_trans *trans = &rtwvif->ml_trans; + + /* Do follow-up when all updating links exist. */ + if (current_links != trans->mediate_links) + return; + + rtw89_vif_cfg_fw_links(rtwdev, rtwvif, trans->links_to_del, false); + rtw89_vif_cfg_fw_links(rtwdev, rtwvif, trans->links_to_add, true); +} + static int rtw89_ops_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -1620,6 +1683,8 @@ int rtw89_ops_change_vif_links(struct ieee80211_hw *hw, if (rtwdev->scanning) rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); + rtw89_vif_update_fw_links(rtwdev, rtwvif, old_links); + if (!old_links) __rtw89_ops_clr_vif_links(rtwdev, rtwvif, BIT(RTW89_VIF_IDLE_LINK_ID)); diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c index ef69672b6862..556e5f98e8d4 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -458,6 +458,7 @@ static void set_cpu_en(struct rtw89_dev *rtwdev, bool include_bb) static int wcpu_on(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw) { + const struct rtw89_chip_info *chip = rtwdev->chip; u32 val32; int ret; @@ -479,6 +480,7 @@ static int wcpu_on(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw) rtw89_write32(rtwdev, R_BE_UDM1, 0); rtw89_write32(rtwdev, R_BE_UDM2, 0); + rtw89_write32(rtwdev, R_BE_BOOT_DBG, 0x0); rtw89_write32(rtwdev, R_BE_HALT_H2C, 0); rtw89_write32(rtwdev, R_BE_HALT_C2H, 0); rtw89_write32(rtwdev, R_BE_HALT_H2C_CTRL, 0); @@ -493,6 +495,11 @@ static int wcpu_on(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw) B_BE_WDT_WAKE_PCIE_EN | B_BE_WDT_WAKE_USB_EN); rtw89_write32_clr(rtwdev, R_BE_WCPU_FW_CTRL, B_BE_WDT_PLT_RST_EN | B_BE_WCPU_ROM_CUT_GET); + rtw89_write32(rtwdev, R_BE_SECURE_BOOT_MALLOC_INFO, 0); + rtw89_write32_clr(rtwdev, R_BE_GPIO_MUXCFG, B_BE_BOOT_MODE); + + if (chip->chip_id != RTL8922A) + rtw89_write32_set(rtwdev, R_BE_WCPU_FW_CTRL, B_BE_HOST_EXIST); rtw89_write16_mask(rtwdev, R_BE_BOOT_REASON, B_BE_BOOT_REASON_MASK, boot_reason); rtw89_write32_clr(rtwdev, R_BE_PLATFORM_ENABLE, B_BE_WCPU_EN); @@ -2020,7 +2027,7 @@ int rtw89_mac_cfg_ppdu_status_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enab } rtw89_write32_mask(rtwdev, R_BE_HW_PPDU_STATUS, B_BE_FWD_PPDU_STAT_MASK, 3); - rtw89_write32(rtwdev, reg, B_BE_PPDU_STAT_RPT_EN | B_BE_PPDU_MAC_INFO | + rtw89_write32(rtwdev, reg, B_BE_PPDU_STAT_RPT_EN | B_BE_APP_RX_CNT_RPT | B_BE_APP_PLCP_HDR_RPT | B_BE_PPDU_STAT_RPT_CRC32 | B_BE_PPDU_STAT_RPT_DMA); diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 0ee5f8579447..a66fcdb0293b 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -464,7 +464,7 @@ static void rtw89_pci_tx_status(struct rtw89_dev *rtwdev, struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); struct ieee80211_tx_info *info; - if (rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status == RTW89_TX_DONE)) + if (rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status)) return; info = IEEE80211_SKB_CB(skb); @@ -2064,6 +2064,20 @@ static void rtw89_pci_ops_write32(struct rtw89_dev *rtwdev, u32 addr, u32 data) writel(data, rtwpci->mmap + addr); } +static u32 rtw89_pci_ops_read32_pci_cfg(struct rtw89_dev *rtwdev, u32 addr) +{ + struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + struct pci_dev *pdev = rtwpci->pdev; + u32 value; + int ret; + + ret = pci_read_config_dword(pdev, addr, &value); + if (ret) + return RTW89_R32_EA; + + return value; +} + static void rtw89_pci_ctrl_dma_trx(struct rtw89_dev *rtwdev, bool enable) { const struct rtw89_pci_info *info = rtwdev->pci_info; @@ -4683,6 +4697,8 @@ static const struct rtw89_hci_ops rtw89_pci_ops = { .write16 = rtw89_pci_ops_write16, .write32 = rtw89_pci_ops_write32, + .read32_pci_cfg = rtw89_pci_ops_read32_pci_cfg, + .mac_pre_init = rtw89_pci_ops_mac_pre_init, .mac_pre_deinit = rtw89_pci_ops_mac_pre_deinit, .mac_post_init = rtw89_pci_ops_mac_post_init, diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index cb05c83dfd56..16dfb0e79d77 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -1487,10 +1487,6 @@ struct rtw89_pci_tx_addr_info_32_v1 { #define RTW89_PCI_RPP_POLLUTED BIT(31) #define RTW89_PCI_RPP_SEQ GENMASK(30, 16) #define RTW89_PCI_RPP_TX_STATUS GENMASK(15, 13) -#define RTW89_TX_DONE 0x0 -#define RTW89_TX_RETRY_LIMIT 0x1 -#define RTW89_TX_LIFE_TIME 0x2 -#define RTW89_TX_MACID_DROP 0x3 #define RTW89_PCI_RPP_QSEL GENMASK(12, 8) #define RTW89_PCI_RPP_MACID GENMASK(7, 0) diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index ba7feadd7582..9f418b1fb7ed 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -231,7 +231,12 @@ static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, return -1; } - if (link_sta->he_cap.has_he) { + if (link_sta->eht_cap.has_eht) { + cfg_mask |= u64_encode_bits(mask->control[band].eht_mcs[0], + RA_MASK_EHT_1SS_RATES); + cfg_mask |= u64_encode_bits(mask->control[band].eht_mcs[1], + RA_MASK_EHT_2SS_RATES); + } else if (link_sta->he_cap.has_he) { cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[0], RA_MASK_HE_1SS_RATES); cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[1], @@ -471,6 +476,10 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra->ra_mask = ra_mask; ra->fix_giltf_en = fix_giltf_en; ra->fix_giltf = fix_giltf; + ra->partial_bw_er = link_sta->he_cap.has_he ? + !!(link_sta->he_cap.he_cap_elem.phy_cap_info[6] & + IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE) : 0; + ra->band = chan->band_type; if (!csi) return; @@ -557,6 +566,14 @@ static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, return true; } +enum __rtw89_hw_rate_invalid_bases { + /* no EHT rate for ax chip */ + RTW89_HW_RATE_EHT_NSS1_MCS0 = RTW89_HW_RATE_INVAL, + RTW89_HW_RATE_EHT_NSS2_MCS0 = RTW89_HW_RATE_INVAL, + RTW89_HW_RATE_EHT_NSS3_MCS0 = RTW89_HW_RATE_INVAL, + RTW89_HW_RATE_EHT_NSS4_MCS0 = RTW89_HW_RATE_INVAL, +}; + #define RTW89_HW_RATE_BY_CHIP_GEN(rate) \ { \ [RTW89_CHIP_AX] = RTW89_HW_RATE_ ## rate, \ @@ -572,6 +589,12 @@ void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, struct rtw89_phy_rate_pattern next_pattern = {0}; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + static const u16 hw_rate_eht[][RTW89_CHIP_GEN_NUM] = { + RTW89_HW_RATE_BY_CHIP_GEN(EHT_NSS1_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(EHT_NSS2_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(EHT_NSS3_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(EHT_NSS4_MCS0), + }; static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = { RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0), RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0), @@ -596,6 +619,17 @@ void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, u8 tx_nss = rtwdev->hal.tx_nss; u8 i; + if (chip_gen == RTW89_CHIP_AX) + goto rs_11ax; + + for (i = 0; i < tx_nss; i++) + if (!__check_rate_pattern(&next_pattern, hw_rate_eht[i][chip_gen], + RA_MASK_EHT_RATES, RTW89_RA_MODE_EHT, + mask->control[nl_band].eht_mcs[i], + 0, true)) + goto out; + +rs_11ax: for (i = 0; i < tx_nss; i++) if (!__check_rate_pattern(&next_pattern, hw_rate_he[i][chip_gen], RA_MASK_HE_RATES, RTW89_RA_MODE_HE, @@ -640,6 +674,13 @@ void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, if (!next_pattern.enable) goto out; + if (unlikely(next_pattern.rate >= RTW89_HW_RATE_INVAL)) { + rtw89_debug(rtwdev, RTW89_DBG_RA, + "pattern invalid target: chip_gen %d, mode 0x%x\n", + chip_gen, next_pattern.ra_mode); + goto out; + } + rtwvif_link->rate_pattern = next_pattern; rtw89_debug(rtwdev, RTW89_DBG_RA, "configure pattern: rate 0x%x, mask 0x%llx, mode 0x%x\n", @@ -2339,6 +2380,21 @@ static u8 rtw89_channel_to_idx(struct rtw89_dev *rtwdev, u8 band, u8 channel) } } +static bool rtw89_phy_validate_txpwr_limit_bw(struct rtw89_dev *rtwdev, + u8 band, u8 bw) +{ + switch (band) { + case RTW89_BAND_2G: + return bw < RTW89_2G_BW_NUM; + case RTW89_BAND_5G: + return bw < RTW89_5G_BW_NUM; + case RTW89_BAND_6G: + return bw < RTW89_6G_BW_NUM; + default: + return false; + } +} + s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch) { @@ -2363,6 +2419,11 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, }; s8 cstr; + if (!rtw89_phy_validate_txpwr_limit_bw(rtwdev, band, bw)) { + rtw89_warn(rtwdev, "invalid band %u bandwidth %u\n", band, bw); + return 0; + } + switch (band) { case RTW89_BAND_2G: if (has_ant_gain) @@ -4551,7 +4612,7 @@ static void rtw89_dcfo_comp(struct rtw89_dev *rtwdev, s32 curr_cfo) s32 dcfo_comp_val; int sign; - if (rtwdev->chip->chip_id == RTL8922A) + if (!dcfo_comp) return; if (!is_linked) { diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c index 3316a38a62d0..bd17714f13d1 100644 --- a/drivers/net/wireless/realtek/rtw89/phy_be.c +++ b/drivers/net/wireless/realtek/rtw89/phy_be.c @@ -266,6 +266,10 @@ static void rtw89_phy_config_bb_gain_be(struct rtw89_dev *rtwdev, case 3: rtw89_phy_cfg_bb_gain_op1db_be(rtwdev, arg, reg->data); break; + case 15: + rtw89_phy_write32_idx(rtwdev, reg->addr & 0xFFFFF, MASKHWORD, + reg->data, RTW89_PHY_0); + break; case 4: /* This cfg_type is only used by rfe_type >= 50 with eFEM */ if (efuse->rfe_type < 50) diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index cf58121eb541..3f69dd4361c3 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -11,6 +11,7 @@ #include "phy.h" #include "ps.h" #include "reg.h" +#include "ser.h" #include "util.h" static int rtw89_fw_receive_lps_h2c_check(struct rtw89_dev *rtwdev, u8 macid) @@ -26,16 +27,27 @@ static int rtw89_fw_receive_lps_h2c_check(struct rtw89_dev *rtwdev, u8 macid) c2h_info.id = RTW89_FWCMD_C2HREG_FUNC_PS_LEAVE_ACK; ret = rtw89_fw_msg_reg(rtwdev, NULL, &c2h_info); if (ret) - return ret; + goto fw_fail; c2hreg_macid = u32_get_bits(c2h_info.u.c2hreg[0], RTW89_C2HREG_PS_LEAVE_ACK_MACID); c2hreg_ret = u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_PS_LEAVE_ACK_RET); - if (macid != c2hreg_macid || c2hreg_ret) + if (macid != c2hreg_macid || c2hreg_ret) { rtw89_warn(rtwdev, "rtw89: check lps h2c received by firmware fail\n"); + ret = -EINVAL; + goto fw_fail; + } + rtwdev->ps_hang_cnt = 0; return 0; + +fw_fail: + rtwdev->ps_hang_cnt++; + if (rtwdev->ps_hang_cnt >= RTW89_PS_HANG_MAX_CNT) + rtw89_ser_notify(rtwdev, MAC_AX_ERR_ASSERTION); + + return ret; } static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid) @@ -51,9 +63,16 @@ static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid) mac->ps_status, chk_msk); if (ret) { rtw89_info(rtwdev, "rtw89: failed to leave lps state\n"); + + rtwdev->ps_hang_cnt++; + if (rtwdev->ps_hang_cnt >= RTW89_PS_HANG_MAX_CNT) + rtw89_ser_notify(rtwdev, MAC_AX_ERR_ASSERTION); + return -EBUSY; } + rtwdev->ps_hang_cnt = 0; + return 0; } diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index ed1d958bc49e..5b4a459cf29c 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -3963,6 +3963,24 @@ #define R_BE_EFUSE_CTRL_1_V1 0x0034 #define B_BE_EF_DATA_MASK GENMASK(31, 0) +#define R_BE_GPIO_MUXCFG 0x0040 +#define B_BE_WCPU_AUTO_EN BIT(26) +#define B_BE_WCPU_JTAG_EN BIT(24) +#define B_BE_WCPU_DBG_EN BIT(23) +#define B_BE_JTAG_CHAIN_EN BIT(20) +#define B_BE_BOOT_MODE BIT(19) +#define B_BE_WL_EECS_EXT_32K_SEL BIT(18) +#define B_BE_WL_SEC_BONDING_OPT_STS BIT(17) +#define B_BE_SECSIC_SEL BIT(16) +#define B_BE_ENHTP BIT(14) +#define B_BE_ENSIC BIT(12) +#define B_BE_SIC_SWRST BIT(11) +#define B_BE_PINMUX_PTA_EN BIT(10) +#define B_BE_WL_BT_PTA_SEC BIT(9) +#define B_BE_ENUARTTX BIT(8) +#define B_BE_DBG_GNT_BT_S1_POLARITY BIT(4) +#define B_BE_ENUARTRX BIT(2) + #define R_BE_GPIO_EXT_CTRL 0x0060 #define B_BE_GPIO_MOD_15_TO_8_MASK GENMASK(31, 24) #define B_BE_GPIO_MOD_9 BIT(25) @@ -4323,6 +4341,7 @@ #define B_BE_RUN_ENV_MASK GENMASK(31, 30) #define B_BE_WCPU_FWDL_STATUS_MASK GENMASK(29, 26) #define B_BE_WDT_PLT_RST_EN BIT(17) +#define B_BE_HOST_EXIST BIT(16) #define B_BE_FW_SEC_AUTH_DONE BIT(14) #define B_BE_FW_CPU_UTIL_STS_EN BIT(13) #define B_BE_BBMCU1_FWDL_EN BIT(12) @@ -4599,6 +4618,10 @@ #define B_BE_HCI_RXDMA_EN BIT(1) #define B_BE_HCI_TXDMA_EN BIT(0) +#define R_BE_BOOT_DBG 0x78F0 +#define B_BE_BOOT_STATUS_MASK GENMASK(31, 16) +#define B_BE_SECUREBOOT_STATUS_MASK GENMASK(15, 0) + #define R_BE_DBG_WOW_READY 0x815E #define B_BE_DBG_WOW_READY GENMASK(7, 0) @@ -7476,7 +7499,6 @@ #define B_BE_PPDU_STAT_RPT_ADDR BIT(4) #define B_BE_APP_PLCP_HDR_RPT BIT(3) #define B_BE_APP_RX_CNT_RPT BIT(2) -#define B_BE_PPDU_MAC_INFO BIT(1) #define B_BE_PPDU_STAT_RPT_EN BIT(0) #define R_BE_RX_SR_CTRL 0x1144A diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c index 58582f8d2b74..209d84909f88 100644 --- a/drivers/net/wireless/realtek/rtw89/regd.c +++ b/drivers/net/wireless/realtek/rtw89/regd.c @@ -723,6 +723,8 @@ int rtw89_regd_init_hint(struct rtw89_dev *rtwdev) chip_regd = rtw89_regd_find_reg_by_name(rtwdev, rtwdev->efuse.country_code); if (!rtw89_regd_is_ww(chip_regd)) { rtwdev->regulatory.regd = chip_regd; + rtwdev->regulatory.programmed = true; + /* Ignore country ie if there is a country domain programmed in chip */ wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; wiphy->regulatory_flags |= REGULATORY_STRICT_REG; @@ -867,11 +869,6 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev, wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; else wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE; - - rtw89_regd_apply_policy_unii4(rtwdev, wiphy); - rtw89_regd_apply_policy_6ghz(rtwdev, wiphy); - rtw89_regd_apply_policy_tas(rtwdev); - rtw89_regd_apply_policy_ant_gain(rtwdev); } static @@ -883,19 +880,22 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request wiphy_lock(wiphy); rtw89_leave_ps_mode(rtwdev); - if (wiphy->regd) { - rtw89_debug(rtwdev, RTW89_DBG_REGD, - "There is a country domain programmed in chip, ignore notifications\n"); - goto exit; - } + if (rtwdev->regulatory.programmed) + goto policy; + rtw89_regd_notifier_apply(rtwdev, wiphy, request); rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd, "get from initiator %d, alpha2", request->initiator); +policy: + rtw89_regd_apply_policy_unii4(rtwdev, wiphy); + rtw89_regd_apply_policy_6ghz(rtwdev, wiphy); + rtw89_regd_apply_policy_tas(rtwdev); + rtw89_regd_apply_policy_ant_gain(rtwdev); + rtw89_core_set_chip_txpwr(rtwdev); -exit: wiphy_unlock(wiphy); } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index edcbda124916..84b628d23882 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -2537,7 +2537,9 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = { .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, - .get_ch_dma = rtw89_core_get_ch_dma, + .get_ch_dma = {rtw89_core_get_ch_dma, + rtw89_core_get_ch_dma, + NULL,}, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, .mac_cfg_gnt = rtw89_mac_cfg_gnt, .stop_sch_tx = rtw89_mac_stop_sch_tx, @@ -2646,6 +2648,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .bacam_num = 2, .bacam_dynamic_num = 4, .bacam_ver = RTW89_BACAM_V0, + .addrcam_ver = 0, .ppdu_max_usr = 4, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c index 84c46d2f4d85..e574a9950a3b 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c @@ -1626,7 +1626,7 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, iqk_info->iqk_table_idx[path] = idx; rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n", - path, phy, rtwdev->dbcc_en ? "on" : "off", + path, phy, str_on_off(rtwdev->dbcc_en), iqk_info->iqk_band[path] == 0 ? "2G" : iqk_info->iqk_band[path] == 1 ? "5G" : "6G", iqk_info->iqk_ch[path], @@ -1901,8 +1901,8 @@ static void _dpk_information(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", path, dpk->cur_idx[path], phy, - rtwdev->is_tssi_mode[path] ? "on" : "off", - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->is_tssi_mode[path]), + str_on_off(rtwdev->dbcc_en), dpk->bp[path][kidx].band == 0 ? "2G" : dpk->bp[path][kidx].band == 1 ? "5G" : "6G", dpk->bp[path][kidx].ch, @@ -2016,7 +2016,7 @@ static void _dpk_txpwr_bb_force(struct rtw89_dev *rtwdev, rtw89_phy_write32_mask(rtwdev, R_TXPWRB_H + (path << 13), B_TXPWRB_RDY, force); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d txpwr_bb_force %s\n", - path, force ? "on" : "off"); + path, str_on_off(force)); } static void _dpk_kip_pwr_clk_onoff(struct rtw89_dev *rtwdev, bool turn_on) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c index 04e1ab13b753..959d62aefdd8 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c @@ -5,15 +5,39 @@ #include <linux/module.h> #include <linux/usb.h> #include "rtw8851b.h" +#include "reg.h" #include "usb.h" +static const struct rtw89_usb_info rtw8851b_usb_info = { + .usb_host_request_2 = R_AX_USB_HOST_REQUEST_2, + .usb_wlan0_1 = R_AX_USB_WLAN0_1, + .hci_func_en = R_AX_HCI_FUNC_EN, + .usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0, + .usb_endpoint_0 = R_AX_USB_ENDPOINT_0, + .usb_endpoint_2 = R_AX_USB_ENDPOINT_2, + .bulkout_id = { + [RTW89_DMA_ACH0] = 3, + [RTW89_DMA_ACH1] = 4, + [RTW89_DMA_ACH2] = 5, + [RTW89_DMA_ACH3] = 6, + [RTW89_DMA_B0MG] = 0, + [RTW89_DMA_B0HI] = 1, + [RTW89_DMA_H2C] = 2, + }, +}; + static const struct rtw89_driver_info rtw89_8851bu_info = { .chip = &rtw8851b_chip_info, .variant = NULL, .quirks = NULL, + .bus = { + .usb = &rtw8851b_usb_info, + } }; static const struct usb_device_id rtw_8851bu_id_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb831, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8851bu_info }, { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb851, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&rtw89_8851bu_info }, /* D-Link AX9U rev. A1 */ diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index 232f4c1bee1b..8677723e3561 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -48,6 +48,48 @@ static const struct rtw89_hfc_param_ini rtw8852a_hfc_param_ini_pcie[] = { [RTW89_QTA_INVALID] = {NULL}, }; +static const struct rtw89_hfc_ch_cfg rtw8852a_hfc_chcfg_usb[] = { + {22, 402, grp_0}, /* ACH 0 */ + {0, 0, grp_0}, /* ACH 1 */ + {22, 402, grp_0}, /* ACH 2 */ + {0, 0, grp_0}, /* ACH 3 */ + {22, 402, grp_0}, /* ACH 4 */ + {0, 0, grp_0}, /* ACH 5 */ + {22, 402, grp_0}, /* ACH 6 */ + {0, 0, grp_0}, /* ACH 7 */ + {22, 402, grp_0}, /* B0MGQ */ + {0, 0, grp_0}, /* B0HIQ */ + {22, 402, grp_0}, /* B1MGQ */ + {0, 0, grp_0}, /* B1HIQ */ + {0, 0, 0} /* FWCMDQ */ +}; + +static const struct rtw89_hfc_pub_cfg rtw8852a_hfc_pubcfg_usb = { + 512, /* Group 0 */ + 0, /* Group 1 */ + 512, /* Public Max */ + 104 /* WP threshold */ +}; + +static const struct rtw89_hfc_prec_cfg rtw8852a_hfc_preccfg_usb = { + 11, /* CH 0-11 pre-cost */ + 32, /* H2C pre-cost */ + 76, /* WP CH 0-7 pre-cost */ + 25, /* WP CH 8-11 pre-cost */ + 1, /* CH 0-11 full condition */ + 1, /* H2C full condition */ + 1, /* WP CH 0-7 full condition */ + 1, /* WP CH 8-11 full condition */ +}; + +static const struct rtw89_hfc_param_ini rtw8852a_hfc_param_ini_usb[] = { + [RTW89_QTA_SCC] = {rtw8852a_hfc_chcfg_usb, &rtw8852a_hfc_pubcfg_usb, + &rtw8852a_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_DLFW] = {NULL, NULL, + &rtw8852a_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_INVALID] = {NULL}, +}; + static const struct rtw89_dle_mem rtw8852a_dle_mem_pcie[] = { [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size0, &rtw89_mac_size.ple_size0, &rtw89_mac_size.wde_qt0, @@ -65,6 +107,19 @@ static const struct rtw89_dle_mem rtw8852a_dle_mem_pcie[] = { NULL}, }; +static const struct rtw89_dle_mem rtw8852a_dle_mem_usb[] = { + [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size1, + &rtw89_mac_size.ple_size1, &rtw89_mac_size.wde_qt1, + &rtw89_mac_size.wde_qt1, &rtw89_mac_size.ple_qt25, + &rtw89_mac_size.ple_qt26}, + [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size4, + &rtw89_mac_size.ple_size4, &rtw89_mac_size.wde_qt4, + &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13, + &rtw89_mac_size.ple_qt13}, + [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, + NULL}, +}; + static const struct rtw89_reg2_def rtw8852a_pmac_ht20_mcs7_tbl[] = { {0x44AC, 0x00000000}, {0x44B0, 0x00000000}, @@ -566,14 +621,6 @@ static const struct rtw89_edcca_regs rtw8852a_edcca_regs = { .tx_collision_t2r_st_mask = B_TX_COLLISION_T2R_ST_M, }; -static void rtw8852ae_efuse_parsing(struct rtw89_efuse *efuse, - struct rtw8852a_efuse *map) -{ - ether_addr_copy(efuse->addr, map->e.mac_addr); - efuse->rfe_type = map->rfe_type; - efuse->xtal_cap = map->xtal_k; -} - static void rtw8852a_efuse_parsing_tssi(struct rtw89_dev *rtwdev, struct rtw8852a_efuse *map) { @@ -619,12 +666,18 @@ static int rtw8852a_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, switch (rtwdev->hci.type) { case RTW89_HCI_TYPE_PCIE: - rtw8852ae_efuse_parsing(efuse, map); + ether_addr_copy(efuse->addr, map->e.mac_addr); + break; + case RTW89_HCI_TYPE_USB: + ether_addr_copy(efuse->addr, map->u.mac_addr); break; default: return -ENOTSUPP; } + efuse->rfe_type = map->rfe_type; + efuse->xtal_cap = map->xtal_k; + rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); return 0; @@ -2178,7 +2231,9 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, - .get_ch_dma = rtw89_core_get_ch_dma, + .get_ch_dma = {rtw89_core_get_ch_dma, + rtw89_core_get_ch_dma_v2, + NULL,}, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, .mac_cfg_gnt = rtw89_mac_cfg_gnt, .stop_sch_tx = rtw89_mac_stop_sch_tx, @@ -2222,8 +2277,13 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .max_amsdu_limit = 3500, .dis_2g_40m_ul_ofdma = true, .rsvd_ple_ofst = 0x6f800, - .hfc_param_ini = {rtw8852a_hfc_param_ini_pcie, NULL, NULL}, - .dle_mem = {rtw8852a_dle_mem_pcie, NULL, NULL, NULL}, + .hfc_param_ini = {rtw8852a_hfc_param_ini_pcie, + rtw8852a_hfc_param_ini_usb, + NULL}, + .dle_mem = {rtw8852a_dle_mem_pcie, + rtw8852a_dle_mem_usb, + rtw8852a_dle_mem_usb, + NULL}, .wde_qempty_acq_grpnum = 16, .wde_qempty_mgq_grpsel = 16, .rf_base_addr = {0xc000, 0xd000}, @@ -2274,6 +2334,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .bacam_num = 2, .bacam_dynamic_num = 4, .bacam_ver = RTW89_BACAM_V0, + .addrcam_ver = 0, .ppdu_max_usr = 4, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c index 9db8713ac99b..463399413318 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c @@ -756,8 +756,8 @@ static void _iqk_rxk_setting(struct rtw89_dev *rtwdev, u8 path) rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_FLTRST, 0x1); rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15_H2, 0x0); udelay(1); - rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0303); - rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0000); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0303); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0000); switch (iqk_info->iqk_band[path]) { case RTW89_BAND_2G: @@ -1239,8 +1239,8 @@ static void _iqk_txk_setting(struct rtw89_dev *rtwdev, u8 path) udelay(1); rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_15, 0x0041); udelay(1); - rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0303); - rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0000); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0303); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0000); switch (iqk_info->iqk_band[path]) { case RTW89_BAND_2G: rtw89_write_rf(rtwdev, path, RR_XALNA2, RR_XALNA2_SW, 0x00); @@ -1403,7 +1403,7 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, path, iqk_info->iqk_ch[path]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n", path, phy, - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->dbcc_en), iqk_info->iqk_band[path] == 0 ? "2G" : iqk_info->iqk_band[path] == 1 ? "5G" : "6G", iqk_info->iqk_ch[path], @@ -1881,8 +1881,8 @@ static void _dpk_information(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", path, dpk->cur_idx[path], phy, - rtwdev->is_tssi_mode[path] ? "on" : "off", - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->is_tssi_mode[path]), + str_on_off(rtwdev->dbcc_en), dpk->bp[path][kidx].band == 0 ? "2G" : dpk->bp[path][kidx].band == 1 ? "5G" : "6G", dpk->bp[path][kidx].ch, @@ -2736,7 +2736,7 @@ static void _dpk_onoff(struct rtw89_dev *rtwdev, MASKBYTE3, 0x6 | val); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path, - kidx, dpk->is_dpk_enable && !off ? "enable" : "disable"); + kidx, str_enable_disable(dpk->is_dpk_enable && !off)); } static void _dpk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852au.c b/drivers/net/wireless/realtek/rtw89/rtw8852au.c new file mode 100644 index 000000000000..ca782469c455 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/rtw8852au.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2025 Realtek Corporation + */ + +#include <linux/module.h> +#include <linux/usb.h> +#include "rtw8852a.h" +#include "reg.h" +#include "usb.h" + +static const struct rtw89_usb_info rtw8852a_usb_info = { + .usb_host_request_2 = R_AX_USB_HOST_REQUEST_2, + .usb_wlan0_1 = R_AX_USB_WLAN0_1, + .hci_func_en = R_AX_HCI_FUNC_EN, + .usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0, + .usb_endpoint_0 = R_AX_USB_ENDPOINT_0, + .usb_endpoint_2 = R_AX_USB_ENDPOINT_2, + .bulkout_id = { + [RTW89_DMA_ACH0] = 3, + [RTW89_DMA_ACH2] = 5, + [RTW89_DMA_ACH4] = 4, + [RTW89_DMA_ACH6] = 6, + [RTW89_DMA_B0MG] = 0, + [RTW89_DMA_B0HI] = 0, + [RTW89_DMA_B1MG] = 1, + [RTW89_DMA_B1HI] = 1, + [RTW89_DMA_H2C] = 2, + }, +}; + +static const struct rtw89_driver_info rtw89_8852au_info = { + .chip = &rtw8852a_chip_info, + .variant = NULL, + .quirks = NULL, + .bus = { + .usb = &rtw8852a_usb_info, + } +}; + +static const struct usb_device_id rtw_8852au_id_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x0312, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4020, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1997, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0x8832, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0x885a, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0x885c, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3321, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x332c, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x013f, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0140, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0141, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x3625, 0x010f, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852au_info }, + {}, +}; +MODULE_DEVICE_TABLE(usb, rtw_8852au_id_table); + +static struct usb_driver rtw_8852au_driver = { + .name = KBUILD_MODNAME, + .id_table = rtw_8852au_id_table, + .probe = rtw89_usb_probe, + .disconnect = rtw89_usb_disconnect, +}; +module_usb_driver(rtw_8852au_driver); + +MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>"); +MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852AU driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 0777e336aaa1..70fb05bc5e98 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -842,7 +842,9 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, - .get_ch_dma = rtw89_core_get_ch_dma, + .get_ch_dma = {rtw89_core_get_ch_dma, + rtw89_core_get_ch_dma, + NULL,}, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, .mac_cfg_gnt = rtw89_mac_cfg_gnt, .stop_sch_tx = rtw89_mac_stop_sch_tx, @@ -957,6 +959,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .bacam_num = 2, .bacam_dynamic_num = 4, .bacam_ver = RTW89_BACAM_V0, + .addrcam_ver = 0, .ppdu_max_usr = 4, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c index 3fb2972ae6f6..4e72f4961837 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c @@ -1747,11 +1747,15 @@ static void __rtw8852bx_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) struct rtw89_hal *hal = &rtwdev->hal; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); enum rtw89_rf_path_bit rx_path = hal->antenna_rx ? hal->antenna_rx : RF_AB; + u8 rx_nss = rtwdev->hal.rx_nss; + + if (rx_path != RF_AB) + rx_nss = 1; rtw8852bx_bb_ctrl_rx_path(rtwdev, rx_path, chan); rtw8852bx_bb_ctrl_rf_mode_rx_path(rtwdev, rx_path); - if (rtwdev->hal.rx_nss == 1) { + if (rx_nss == 1) { rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c index 4796588c0256..70b1515c00fa 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c @@ -1696,7 +1696,7 @@ static void _dpk_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, bool o MASKBYTE3, _dpk_order_convert(rtwdev) << 1 | val); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path, - kidx, dpk->is_dpk_enable && !off ? "enable" : "disable"); + kidx, str_enable_disable(dpk->is_dpk_enable && !off)); } static void _dpk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, @@ -1763,8 +1763,8 @@ static void _dpk_information(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", path, dpk->cur_idx[path], phy, - rtwdev->is_tssi_mode[path] ? "on" : "off", - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->is_tssi_mode[path]), + str_on_off(rtwdev->dbcc_en), dpk->bp[path][kidx].band == 0 ? "2G" : dpk->bp[path][kidx].band == 1 ? "5G" : "6G", dpk->bp[path][kidx].ch, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c index b3a79ebc7e75..f956474c3b72 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c @@ -708,7 +708,9 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = { .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, - .get_ch_dma = rtw89_core_get_ch_dma, + .get_ch_dma = {rtw89_core_get_ch_dma, + NULL, + NULL,}, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, .mac_cfg_gnt = rtw89_mac_cfg_gnt, .stop_sch_tx = rtw89_mac_stop_sch_tx, @@ -816,6 +818,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .bacam_num = 2, .bacam_dynamic_num = 4, .bacam_ver = RTW89_BACAM_V0, + .addrcam_ver = 0, .ppdu_max_usr = 4, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c index 0694272f7ffa..980d17ef68d0 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c @@ -5,12 +5,34 @@ #include <linux/module.h> #include <linux/usb.h> #include "rtw8852b.h" +#include "reg.h" #include "usb.h" +static const struct rtw89_usb_info rtw8852b_usb_info = { + .usb_host_request_2 = R_AX_USB_HOST_REQUEST_2, + .usb_wlan0_1 = R_AX_USB_WLAN0_1, + .hci_func_en = R_AX_HCI_FUNC_EN, + .usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0, + .usb_endpoint_0 = R_AX_USB_ENDPOINT_0, + .usb_endpoint_2 = R_AX_USB_ENDPOINT_2, + .bulkout_id = { + [RTW89_DMA_ACH0] = 3, + [RTW89_DMA_ACH1] = 4, + [RTW89_DMA_ACH2] = 5, + [RTW89_DMA_ACH3] = 6, + [RTW89_DMA_B0MG] = 0, + [RTW89_DMA_B0HI] = 1, + [RTW89_DMA_H2C] = 2, + }, +}; + static const struct rtw89_driver_info rtw89_8852bu_info = { .chip = &rtw8852b_chip_info, .variant = NULL, .quirks = NULL, + .bus = { + .usb = &rtw8852b_usb_info, + } }; static const struct usb_device_id rtw_8852bu_id_table[] = { @@ -28,6 +50,8 @@ static const struct usb_device_id rtw_8852bu_id_table[] = { .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1a62, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1cb6, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, { USB_DEVICE_AND_INTERFACE_INFO(0x0db0, 0x6931, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3327, 0xff, 0xff, 0xff), diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 440801d63343..db99450e9158 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -51,6 +51,48 @@ static const struct rtw89_hfc_param_ini rtw8852c_hfc_param_ini_pcie[] = { [RTW89_QTA_INVALID] = {NULL}, }; +static const struct rtw89_hfc_ch_cfg rtw8852c_hfc_chcfg_usb[] = { + {18, 344, grp_0}, /* ACH 0 */ + {0, 0, grp_0}, /* ACH 1 */ + {18, 344, grp_0}, /* ACH 2 */ + {0, 0, grp_0}, /* ACH 3 */ + {18, 344, grp_0}, /* ACH 4 */ + {0, 0, grp_0}, /* ACH 5 */ + {18, 344, grp_0}, /* ACH 6 */ + {0, 0, grp_0}, /* ACH 7 */ + {18, 344, grp_0}, /* B0MGQ */ + {0, 0, grp_0}, /* B0HIQ */ + {18, 344, grp_0}, /* B1MGQ */ + {0, 0, grp_0}, /* B1HIQ */ + {0, 0, 0} /* FWCMDQ */ +}; + +static const struct rtw89_hfc_pub_cfg rtw8852c_hfc_pubcfg_usb = { + 344, /* Group 0 */ + 0, /* Group 1 */ + 344, /* Public Max */ + 0 /* WP threshold */ +}; + +static const struct rtw89_hfc_prec_cfg rtw8852c_hfc_preccfg_usb = { + 9, /* CH 0-11 pre-cost */ + 32, /* H2C pre-cost */ + 146, /* WP CH 0-7 pre-cost */ + 146, /* WP CH 8-11 pre-cost */ + 1, /* CH 0-11 full condition */ + 1, /* H2C full condition */ + 1, /* WP CH 0-7 full condition */ + 1, /* WP CH 8-11 full condition */ +}; + +static const struct rtw89_hfc_param_ini rtw8852c_hfc_param_ini_usb[] = { + [RTW89_QTA_SCC] = {rtw8852c_hfc_chcfg_usb, &rtw8852c_hfc_pubcfg_usb, + &rtw8852c_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_DLFW] = {NULL, NULL, + &rtw8852c_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_INVALID] = {NULL}, +}; + static const struct rtw89_dle_mem rtw8852c_dle_mem_pcie[] = { [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size19, &rtw89_mac_size.ple_size19, &rtw89_mac_size.wde_qt18, @@ -64,6 +106,32 @@ static const struct rtw89_dle_mem rtw8852c_dle_mem_pcie[] = { NULL}, }; +static const struct rtw89_dle_mem rtw8852c_dle_mem_usb2[] = { + [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size31, + &rtw89_mac_size.ple_size34, &rtw89_mac_size.wde_qt31, + &rtw89_mac_size.wde_qt31, &rtw89_mac_size.ple_qt78, + &rtw89_mac_size.ple_qt79}, + [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size18, + &rtw89_mac_size.ple_size18, &rtw89_mac_size.wde_qt17, + &rtw89_mac_size.wde_qt17, &rtw89_mac_size.ple_qt44, + &rtw89_mac_size.ple_qt45}, + [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, + NULL}, +}; + +static const struct rtw89_dle_mem rtw8852c_dle_mem_usb3[] = { + [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size17, + &rtw89_mac_size.ple_size17, &rtw89_mac_size.wde_qt16, + &rtw89_mac_size.wde_qt16, &rtw89_mac_size.ple_qt42, + &rtw89_mac_size.ple_qt43}, + [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size18, + &rtw89_mac_size.ple_size18, &rtw89_mac_size.wde_qt17, + &rtw89_mac_size.wde_qt17, &rtw89_mac_size.ple_qt44, + &rtw89_mac_size.ple_qt45}, + [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, + NULL}, +}; + static const u32 rtw8852c_h2c_regs[RTW89_H2CREG_MAX] = { R_AX_H2CREG_DATA0_V1, R_AX_H2CREG_DATA1_V1, R_AX_H2CREG_DATA2_V1, R_AX_H2CREG_DATA3_V1 @@ -214,7 +282,8 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev) int ret; val32 = rtw89_read32_mask(rtwdev, R_AX_SYS_STATUS1, B_AX_PAD_HCI_SEL_V2_MASK); - if (val32 == MAC_AX_HCI_SEL_PCIE_USB) + if (val32 == MAC_AX_HCI_SEL_PCIE_USB || + rtwdev->hci.type == RTW89_HCI_TYPE_USB) rtw89_write32_set(rtwdev, R_AX_LDO_AON_CTRL0, B_AX_PD_REGU_L); rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_AFSM_WLSUS_EN | @@ -246,7 +315,9 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev) rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); - rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); + + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND, B_AX_CMAC1_FEN); rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND, B_AX_R_SYM_ISO_CMAC12PP); @@ -305,9 +376,11 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev) rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14); rtw89_write32_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); - rtw89_write32_set(rtwdev, R_AX_GPIO0_15_EECS_EESK_LED1_PULL_LOW_EN, - B_AX_EECS_PULL_LOW_EN | B_AX_EESK_PULL_LOW_EN | - B_AX_LED1_PULL_LOW_EN); + + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32_set(rtwdev, R_AX_GPIO0_15_EECS_EESK_LED1_PULL_LOW_EN, + B_AX_EECS_PULL_LOW_EN | B_AX_EESK_PULL_LOW_EN | + B_AX_LED1_PULL_LOW_EN); rtw89_write32_set(rtwdev, R_AX_DMAC_FUNC_EN, B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_MPDU_PROC_EN | @@ -385,22 +458,26 @@ static int rtw8852c_pwr_off_func(struct rtw89_dev *rtwdev) if (ret) return ret; - rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION); + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION); + else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_EDSWR); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_XTAL_OFF_A_DIE); rtw89_write32_set(rtwdev, R_AX_SYS_SWR_CTRL1, B_AX_SYM_CTRL_SPS_PWMFREQ); rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0, B_AX_REG_ZCDC_H_MASK, 0x3); - rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); - return 0; -} + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) { + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + } else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) { + val32 = rtw89_read32(rtwdev, R_AX_SYS_PW_CTRL); + val32 &= ~B_AX_AFSM_PCIE_SUS_EN; + val32 |= B_AX_AFSM_WLSUS_EN; + rtw89_write32(rtwdev, R_AX_SYS_PW_CTRL, val32); + } -static void rtw8852c_e_efuse_parsing(struct rtw89_efuse *efuse, - struct rtw8852c_efuse *map) -{ - ether_addr_copy(efuse->addr, map->e.mac_addr); - efuse->rfe_type = map->rfe_type; - efuse->xtal_cap = map->xtal_k; + return 0; } static void rtw8852c_efuse_parsing_tssi(struct rtw89_dev *rtwdev, @@ -511,12 +588,18 @@ static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, switch (rtwdev->hci.type) { case RTW89_HCI_TYPE_PCIE: - rtw8852c_e_efuse_parsing(efuse, map); + ether_addr_copy(efuse->addr, map->e.mac_addr); + break; + case RTW89_HCI_TYPE_USB: + ether_addr_copy(efuse->addr, map->u.mac_addr); break; default: return -ENOTSUPP; } + efuse->rfe_type = map->rfe_type; + efuse->xtal_cap = map->xtal_k; + rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); return 0; @@ -587,12 +670,16 @@ static void rtw8852c_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev, } } +#define __THM_MASK_SIGN BIT(0) +#define __THM_MASK_3BITS GENMASK(3, 1) +#define __THM_MASK_VAL8 BIT(4) + static void rtw8852c_thermal_trim(struct rtw89_dev *rtwdev) { -#define __thm_setting(raw) \ -({ \ - u8 __v = (raw); \ - ((__v & 0x1) << 3) | ((__v & 0x1f) >> 1); \ +#define __thm_setting(raw) \ +({ \ + u8 __v = (raw); \ + ((__v & __THM_MASK_SIGN) << 3) | ((__v & __THM_MASK_3BITS) >> 1); \ }) struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; u8 i, val; @@ -2415,10 +2502,20 @@ static void rtw8852c_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en, static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; + u8 nrx_path = RF_PATH_AB; + u8 rx_nss = hal->rx_nss; + + if (hal->antenna_rx == RF_A) + nrx_path = RF_PATH_A; + else if (hal->antenna_rx == RF_B) + nrx_path = RF_PATH_B; + + if (nrx_path != RF_PATH_AB) + rx_nss = 1; - rtw8852c_bb_cfg_rx_path(rtwdev, RF_PATH_AB); + rtw8852c_bb_cfg_rx_path(rtwdev, nrx_path); - if (hal->rx_nss == 1) { + if (rx_nss == 1) { rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0); @@ -2433,13 +2530,26 @@ static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) static u8 rtw8852c_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path) { + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + s8 comp = 0; + u8 val; + rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x0); rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); fsleep(200); - return rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL); + val = rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL); + + if (info->pg_thermal_trim) { + u8 trim = info->thermal_trim[rf_path]; + + if (trim & __THM_MASK_VAL8) + comp = 8 * (trim & __THM_MASK_SIGN ? -1 : 1); + } + + return val + comp; } static void rtw8852c_btc_set_rfe(struct rtw89_dev *rtwdev) @@ -2962,7 +3072,9 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc_v1, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v1, - .get_ch_dma = rtw89_core_get_ch_dma, + .get_ch_dma = {rtw89_core_get_ch_dma, + rtw89_core_get_ch_dma_v2, + NULL,}, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v1, .mac_cfg_gnt = rtw89_mac_cfg_gnt_v1, .stop_sch_tx = rtw89_mac_stop_sch_tx_v1, @@ -3006,8 +3118,13 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .max_amsdu_limit = 8000, .dis_2g_40m_ul_ofdma = false, .rsvd_ple_ofst = 0x6f800, - .hfc_param_ini = {rtw8852c_hfc_param_ini_pcie, NULL, NULL}, - .dle_mem = {rtw8852c_dle_mem_pcie, NULL, NULL, NULL}, + .hfc_param_ini = {rtw8852c_hfc_param_ini_pcie, + rtw8852c_hfc_param_ini_usb, + NULL}, + .dle_mem = {rtw8852c_dle_mem_pcie, + rtw8852c_dle_mem_usb2, + rtw8852c_dle_mem_usb3, + NULL}, .wde_qempty_acq_grpnum = 16, .wde_qempty_mgq_grpsel = 16, .rf_base_addr = {0xe000, 0xf000}, @@ -3061,6 +3178,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .bacam_num = 8, .bacam_dynamic_num = 8, .bacam_ver = RTW89_BACAM_V0_EXT, + .addrcam_ver = 0, .ppdu_max_usr = 8, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.h b/drivers/net/wireless/realtek/rtw89/rtw8852c.h index 77b05daedd10..8585921ac6c4 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.h @@ -11,7 +11,7 @@ #define BB_PATH_NUM_8852C 2 struct rtw8852c_u_efuse { - u8 rsvd[0x38]; + u8 rsvd[0x88]; u8 mac_addr[ETH_ALEN]; }; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c index b92e2ce4f4ad..cbee484dee30 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c @@ -1344,7 +1344,7 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, path, iqk_info->iqk_ch[path]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n", path, phy, - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->dbcc_en), iqk_info->iqk_band[path] == 0 ? "2G" : iqk_info->iqk_band[path] == 1 ? "5G" : "6G", iqk_info->iqk_ch[path], @@ -1920,8 +1920,8 @@ static void _dpk_information(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", path, dpk->cur_idx[path], phy, - rtwdev->is_tssi_mode[path] ? "on" : "off", - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->is_tssi_mode[path]), + str_on_off(rtwdev->dbcc_en), dpk->bp[path][kidx].band == 0 ? "2G" : dpk->bp[path][kidx].band == 1 ? "5G" : "6G", dpk->bp[path][kidx].ch, @@ -2000,7 +2000,7 @@ static void _dpk_txpwr_bb_force(struct rtw89_dev *rtwdev, u8 path, bool force) rtw89_phy_write32_mask(rtwdev, R_TXPWRB_H + (path << 13), B_TXPWRB_RDY, force); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d txpwr_bb_force %s\n", - path, force ? "on" : "off"); + path, str_on_off(force)); } static void _dpk_kip_restore(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, @@ -2828,7 +2828,7 @@ static void _dpk_onoff(struct rtw89_dev *rtwdev, B_DPD_MEN, val); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path, - kidx, dpk->is_dpk_enable && !off ? "enable" : "disable"); + kidx, str_enable_disable(dpk->is_dpk_enable && !off)); } static void _dpk_track(struct rtw89_dev *rtwdev) @@ -3987,37 +3987,56 @@ static void _ctrl_ch(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, } } +static void _set_rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + enum rtw89_bandwidth bw) +{ + u32 val; + + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x1); + rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_M2, 0xa); + + switch (bw) { + case RTW89_CHANNEL_WIDTH_20: + val = 0x1b; + break; + case RTW89_CHANNEL_WIDTH_40: + val = 0x13; + break; + case RTW89_CHANNEL_WIDTH_80: + val = 0xb; + break; + case RTW89_CHANNEL_WIDTH_160: + default: + val = 0x3; + break; + } + + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, val); + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x0); +} + +static void _set_tia_bw(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + enum rtw89_bandwidth bw) +{ + if (bw == RTW89_CHANNEL_WIDTH_160) + rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_EBW, 0x0); + else + rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_EBW, 0x2); +} + static void _rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, enum rtw89_bandwidth bw) { u8 kpath; u8 path; - u32 val; kpath = _kpath(rtwdev, phy); for (path = 0; path < 2; path++) { if (!(kpath & BIT(path))) continue; - rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x1); - rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_M2, 0xa); - switch (bw) { - case RTW89_CHANNEL_WIDTH_20: - val = 0x1b; - break; - case RTW89_CHANNEL_WIDTH_40: - val = 0x13; - break; - case RTW89_CHANNEL_WIDTH_80: - val = 0xb; - break; - case RTW89_CHANNEL_WIDTH_160: - default: - val = 0x3; - break; - } - rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, val); - rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x0); + _set_rxbb_bw(rtwdev, path, bw); + _set_tia_bw(rtwdev, path, bw); } } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c new file mode 100644 index 000000000000..2708b523ca14 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2025 Realtek Corporation + */ + +#include <linux/module.h> +#include <linux/usb.h> +#include "rtw8852c.h" +#include "reg.h" +#include "usb.h" + +static const struct rtw89_usb_info rtw8852c_usb_info = { + .usb_host_request_2 = R_AX_USB_HOST_REQUEST_2_V1, + .usb_wlan0_1 = R_AX_USB_WLAN0_1_V1, + .hci_func_en = R_AX_HCI_FUNC_EN_V1, + .usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0_V1, + .usb_endpoint_0 = R_AX_USB_ENDPOINT_0_V1, + .usb_endpoint_2 = R_AX_USB_ENDPOINT_2_V1, + .bulkout_id = { + [RTW89_DMA_ACH0] = 3, + [RTW89_DMA_ACH2] = 5, + [RTW89_DMA_ACH4] = 4, + [RTW89_DMA_ACH6] = 6, + [RTW89_DMA_B0MG] = 0, + [RTW89_DMA_B0HI] = 0, + [RTW89_DMA_B1MG] = 1, + [RTW89_DMA_B1HI] = 1, + [RTW89_DMA_H2C] = 2, + }, +}; + +static const struct rtw89_driver_info rtw89_8852cu_info = { + .chip = &rtw8852c_chip_info, + .variant = NULL, + .quirks = NULL, + .bus = { + .usb = &rtw8852c_usb_info, + }, +}; + +static const struct usb_device_id rtw_8852cu_id_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xc832, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xc85a, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xc85d, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0db0, 0x991d, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x35b2, 0x0502, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0101, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0102, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852cu_info }, + {}, +}; +MODULE_DEVICE_TABLE(usb, rtw_8852cu_id_table); + +static struct usb_driver rtw_8852cu_driver = { + .name = KBUILD_MODNAME, + .id_table = rtw_8852cu_id_table, + .probe = rtw89_usb_probe, + .disconnect = rtw89_usb_disconnect, +}; +module_usb_driver(rtw_8852cu_driver); + +MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>"); +MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852CU driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 6aa19ad259ac..4437279c554b 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -2347,19 +2347,29 @@ static void rtw8922a_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) enum rtw89_band band = chan->band_type; struct rtw89_hal *hal = &rtwdev->hal; u8 ntx_path = RF_PATH_AB; + u8 nrx_path = RF_PATH_AB; u32 tx_en0, tx_en1; + u8 rx_nss = 2; if (hal->antenna_tx == RF_A) ntx_path = RF_PATH_A; else if (hal->antenna_tx == RF_B) ntx_path = RF_PATH_B; + if (hal->antenna_rx == RF_A) + nrx_path = RF_PATH_A; + else if (hal->antenna_rx == RF_B) + nrx_path = RF_PATH_B; + + if (nrx_path != RF_PATH_AB) + rx_nss = 1; + rtw8922a_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, true); if (rtwdev->dbcc_en) rtw8922a_hal_reset(rtwdev, RTW89_PHY_1, RTW89_MAC_1, band, &tx_en1, true); - rtw8922a_ctrl_trx_path(rtwdev, ntx_path, 2, RF_PATH_AB, 2); + rtw8922a_ctrl_trx_path(rtwdev, ntx_path, 2, nrx_path, rx_nss); rtw8922a_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, false); if (rtwdev->dbcc_en) @@ -2821,7 +2831,9 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = { .query_rxdesc = rtw89_core_query_rxdesc_v2, .fill_txdesc = rtw89_core_fill_txdesc_v2, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v2, - .get_ch_dma = rtw89_core_get_ch_dma, + .get_ch_dma = {rtw89_core_get_ch_dma, + rtw89_core_get_ch_dma_v2, + NULL,}, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v2, .mac_cfg_gnt = rtw89_mac_cfg_gnt_v2, .stop_sch_tx = rtw89_mac_stop_sch_tx_v2, @@ -2919,6 +2931,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .bacam_num = 24, .bacam_dynamic_num = 8, .bacam_ver = RTW89_BACAM_V1, + .addrcam_ver = 0, .ppdu_max_usr = 16, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 0x1300, diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h index 984c9fdbb018..fa324b4a1dde 100644 --- a/drivers/net/wireless/realtek/rtw89/txrx.h +++ b/drivers/net/wireless/realtek/rtw89/txrx.h @@ -127,6 +127,8 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define RTW89_TXWD_INFO0_MULTIPORT_ID GENMASK(6, 4) /* TX WD INFO DWORD 1 */ +#define RTW89_TXWD_INFO1_DATA_TXCNT_LMT_SEL BIT(31) +#define RTW89_TXWD_INFO1_DATA_TXCNT_LMT GENMASK(30, 25) #define RTW89_TXWD_INFO1_DATA_RTY_LOWEST_RATE GENMASK(24, 16) #define RTW89_TXWD_INFO1_A_CTRL_BSR BIT(14) #define RTW89_TXWD_INFO1_MAX_AGGNUM GENMASK(7, 0) @@ -139,10 +141,12 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define RTW89_TXWD_INFO2_SEC_CAM_IDX GENMASK(7, 0) /* TX WD INFO DWORD 3 */ +#define RTW89_TXWD_INFO3_SPE_RPT BIT(10) /* TX WD INFO DWORD 4 */ -#define RTW89_TXWD_INFO4_RTS_EN BIT(27) #define RTW89_TXWD_INFO4_HW_RTS_EN BIT(31) +#define RTW89_TXWD_INFO4_RTS_EN BIT(27) +#define RTW89_TXWD_INFO4_SW_DEFINE GENMASK(3, 0) /* TX WD INFO DWORD 5 */ @@ -417,6 +421,7 @@ struct rtw89_rxinfo_user { #define RTW89_RXINFO_USER_MGMT BIT(3) #define RTW89_RXINFO_USER_BCN BIT(4) #define RTW89_RXINFO_USER_MACID GENMASK(15, 8) +#define RTW89_RXINFO_USER_MACID_V1 GENMASK(31, 20) struct rtw89_rxinfo { __le32 w0; diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c index 6cf89aee252e..d7d968207a39 100644 --- a/drivers/net/wireless/realtek/rtw89/usb.c +++ b/drivers/net/wireless/realtek/rtw89/usb.c @@ -55,7 +55,7 @@ static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr, else if (ret < 0) rtw89_warn(rtwdev, "usb %s%u 0x%x fail ret=%d value=0x%x attempt=%d\n", - reqtype == RTW89_USB_VENQT_READ ? "read" : "write", + str_read_write(reqtype == RTW89_USB_VENQT_READ), len * 8, addr, ret, le32_to_cpup(rtwusb->vendor_req_buf), attempt); @@ -167,27 +167,6 @@ rtw89_usb_ops_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, return 42; /* TODO some kind of calculation? */ } -static u8 rtw89_usb_get_bulkout_id(u8 ch_dma) -{ - switch (ch_dma) { - case RTW89_DMA_ACH0: - return 3; - case RTW89_DMA_ACH1: - return 4; - case RTW89_DMA_ACH2: - return 5; - case RTW89_DMA_ACH3: - return 6; - default: - case RTW89_DMA_B0MG: - return 0; - case RTW89_DMA_B0HI: - return 1; - case RTW89_DMA_H2C: - return 2; - } -} - static void rtw89_usb_write_port_complete(struct urb *urb) { struct rtw89_usb_tx_ctrl_block *txcb = urb->context; @@ -215,6 +194,15 @@ static void rtw89_usb_write_port_complete(struct urb *urb) skb_pull(skb, txdesc_size); + if (rtw89_is_tx_rpt_skb(rtwdev, skb)) { + if (urb->status == 0) + rtw89_tx_rpt_skb_add(rtwdev, skb); + else + rtw89_tx_rpt_tx_status(rtwdev, skb, + RTW89_TX_MACID_DROP); + continue; + } + info = IEEE80211_SKB_CB(skb); ieee80211_tx_info_clear_status(info); @@ -242,21 +230,21 @@ static void rtw89_usb_write_port_complete(struct urb *urb) } kfree(txcb); - usb_free_urb(urb); } static int rtw89_usb_write_port(struct rtw89_dev *rtwdev, u8 ch_dma, void *data, int len, void *context) { struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + const struct rtw89_usb_info *info = rtwusb->info; struct usb_device *usbd = rtwusb->udev; struct urb *urb; - u8 bulkout_id = rtw89_usb_get_bulkout_id(ch_dma); + u8 bulkout_id = info->bulkout_id[ch_dma]; unsigned int pipe; int ret; if (test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) - return 0; + return -ENODEV; urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) @@ -267,10 +255,17 @@ static int rtw89_usb_write_port(struct rtw89_dev *rtwdev, u8 ch_dma, usb_fill_bulk_urb(urb, usbd, pipe, data, len, rtw89_usb_write_port_complete, context); urb->transfer_flags |= URB_ZERO_PACKET; - ret = usb_submit_urb(urb, GFP_ATOMIC); + usb_anchor_urb(urb, &rtwusb->tx_submitted); + ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret) - usb_free_urb(urb); + usb_unanchor_urb(urb); + + /* release our reference to this URB, USB core will eventually free it + * on its own after the completion callback finishes (or URB is + * immediately freed here if its submission has failed) + */ + usb_free_urb(urb); if (ret == -ENODEV) set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags); @@ -278,6 +273,15 @@ static int rtw89_usb_write_port(struct rtw89_dev *rtwdev, u8 ch_dma, return ret; } +static void rtw89_usb_tx_free_skb(struct rtw89_dev *rtwdev, u8 txch, + struct sk_buff *skb) +{ + if (txch == RTW89_TXCH_CH12) + dev_kfree_skb_any(skb); + else + ieee80211_free_txskb(rtwdev->hw, skb); +} + static void rtw89_usb_ops_tx_kick_off(struct rtw89_dev *rtwdev, u8 txch) { struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); @@ -292,7 +296,7 @@ static void rtw89_usb_ops_tx_kick_off(struct rtw89_dev *rtwdev, u8 txch) txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC); if (!txcb) { - dev_kfree_skb_any(skb); + rtw89_usb_tx_free_skb(rtwdev, txch, skb); continue; } @@ -305,12 +309,13 @@ static void rtw89_usb_ops_tx_kick_off(struct rtw89_dev *rtwdev, u8 txch) ret = rtw89_usb_write_port(rtwdev, txch, skb->data, skb->len, txcb); if (ret) { - rtw89_err(rtwdev, "write port txch %d failed: %d\n", - txch, ret); + if (ret != -ENODEV) + rtw89_err(rtwdev, "write port txch %d failed: %d\n", + txch, ret); skb_dequeue(&txcb->tx_ack_queue); kfree(txcb); - dev_kfree_skb_any(skb); + rtw89_usb_tx_free_skb(rtwdev, txch, skb); } } } @@ -362,6 +367,7 @@ static int rtw89_usb_ops_tx_write(struct rtw89_dev *rtwdev, { struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + struct rtw89_tx_skb_data *skb_data; struct sk_buff *skb = tx_req->skb; struct rtw89_txwd_body *txdesc; u32 txdesc_size; @@ -388,6 +394,12 @@ static int rtw89_usb_ops_tx_write(struct rtw89_dev *rtwdev, le32p_replace_bits(&txdesc->dword0, 1, RTW89_TXWD_BODY0_STF_MODE); + skb_data = RTW89_TX_SKB_CB(skb); + if (tx_req->desc_info.sn) + skb_data->tx_rpt_sn = tx_req->desc_info.sn; + if (tx_req->desc_info.tx_cnt_lmt) + skb_data->tx_pkt_cnt_lmt = tx_req->desc_info.tx_cnt_lmt; + skb_queue_tail(&rtwusb->tx_queue[desc_info->ch_dma], skb); return 0; @@ -410,8 +422,7 @@ static void rtw89_usb_rx_handler(struct work_struct *work) if (skb_queue_len(&rtwusb->rx_queue) >= RTW89_USB_MAX_RXQ_LEN) { rtw89_warn(rtwdev, "rx_queue overflow\n"); - dev_kfree_skb_any(rx_skb); - continue; + goto free_or_reuse; } memset(&desc_info, 0, sizeof(desc_info)); @@ -422,7 +433,7 @@ static void rtw89_usb_rx_handler(struct work_struct *work) rtw89_debug(rtwdev, RTW89_DBG_HCI, "failed to allocate RX skb of size %u\n", desc_info.pkt_size); - continue; + goto free_or_reuse; } pkt_offset = desc_info.offset + desc_info.rxd_len; @@ -432,6 +443,7 @@ static void rtw89_usb_rx_handler(struct work_struct *work) rtw89_core_rx(rtwdev, &desc_info, skb); +free_or_reuse: if (skb_queue_len(&rtwusb->rx_free_queue) >= RTW89_USB_RX_SKB_NUM) dev_kfree_skb_any(rx_skb); else @@ -567,6 +579,11 @@ static void rtw89_usb_cancel_rx_bufs(struct rtw89_usb *rtwusb) } } +static void rtw89_usb_cancel_tx_bufs(struct rtw89_usb *rtwusb) +{ + usb_kill_anchored_urbs(&rtwusb->tx_submitted); +} + static void rtw89_usb_free_rx_bufs(struct rtw89_usb *rtwusb) { struct rtw89_usb_rx_ctrl_block *rxcb; @@ -668,7 +685,10 @@ static void rtw89_usb_deinit_tx(struct rtw89_dev *rtwdev) static void rtw89_usb_ops_reset(struct rtw89_dev *rtwdev) { - /* TODO: anything to do here? */ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + + rtw89_usb_cancel_tx_bufs(rtwusb); + rtw89_tx_rpt_skbs_purge(rtwdev); } static int rtw89_usb_ops_start(struct rtw89_dev *rtwdev) @@ -698,20 +718,23 @@ static int rtw89_usb_ops_deinit(struct rtw89_dev *rtwdev) static int rtw89_usb_ops_mac_pre_init(struct rtw89_dev *rtwdev) { + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + const struct rtw89_usb_info *info = rtwusb->info; u32 val32; - rtw89_write32_set(rtwdev, R_AX_USB_HOST_REQUEST_2, B_AX_R_USBIO_MODE); + rtw89_write32_set(rtwdev, info->usb_host_request_2, + B_AX_R_USBIO_MODE); /* fix USB IO hang suggest by chihhanli@realtek.com */ - rtw89_write32_clr(rtwdev, R_AX_USB_WLAN0_1, + rtw89_write32_clr(rtwdev, info->usb_wlan0_1, B_AX_USBRX_RST | B_AX_USBTX_RST); - val32 = rtw89_read32(rtwdev, R_AX_HCI_FUNC_EN); + val32 = rtw89_read32(rtwdev, info->hci_func_en); val32 &= ~(B_AX_HCI_RXDMA_EN | B_AX_HCI_TXDMA_EN); - rtw89_write32(rtwdev, R_AX_HCI_FUNC_EN, val32); + rtw89_write32(rtwdev, info->hci_func_en, val32); val32 |= B_AX_HCI_RXDMA_EN | B_AX_HCI_TXDMA_EN; - rtw89_write32(rtwdev, R_AX_HCI_FUNC_EN, val32); + rtw89_write32(rtwdev, info->hci_func_en, val32); /* fix USB TRX hang suggest by chihhanli@realtek.com */ return 0; @@ -725,10 +748,11 @@ static int rtw89_usb_ops_mac_pre_deinit(struct rtw89_dev *rtwdev) static int rtw89_usb_ops_mac_post_init(struct rtw89_dev *rtwdev) { struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + const struct rtw89_usb_info *info = rtwusb->info; enum usb_device_speed speed; u32 ep; - rtw89_write32_clr(rtwdev, R_AX_USB3_MAC_NPI_CONFIG_INTF_0, + rtw89_write32_clr(rtwdev, info->usb3_mac_npi_config_intf_0, B_AX_SSPHY_LFPS_FILTER); speed = rtwusb->udev->speed; @@ -744,9 +768,9 @@ static int rtw89_usb_ops_mac_post_init(struct rtw89_dev *rtwdev) if (ep == 8) continue; - rtw89_write8_mask(rtwdev, R_AX_USB_ENDPOINT_0, + rtw89_write8_mask(rtwdev, info->usb_endpoint_0, B_AX_EP_IDX, ep); - rtw89_write8(rtwdev, R_AX_USB_ENDPOINT_2 + 1, NUMP); + rtw89_write8(rtwdev, info->usb_endpoint_2 + 1, NUMP); } return 0; @@ -901,6 +925,8 @@ static int rtw89_usb_intf_init(struct rtw89_dev *rtwdev, struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); int ret; + init_usb_anchor(&rtwusb->tx_submitted); + ret = rtw89_usb_parse(rtwdev, intf); if (ret) return ret; @@ -949,9 +975,11 @@ int rtw89_usb_probe(struct usb_interface *intf, rtwusb = rtw89_usb_priv(rtwdev); rtwusb->rtwdev = rtwdev; + rtwusb->info = info->bus.usb; rtwdev->hci.ops = &rtw89_usb_ops; rtwdev->hci.type = RTW89_HCI_TYPE_USB; + rtwdev->hci.tx_rpt_enabled = true; ret = rtw89_usb_intf_init(rtwdev, intf); if (ret) { @@ -1026,6 +1054,7 @@ void rtw89_usb_disconnect(struct usb_interface *intf) rtwusb = rtw89_usb_priv(rtwdev); rtw89_usb_cancel_rx_bufs(rtwusb); + rtw89_usb_cancel_tx_bufs(rtwusb); rtw89_core_unregister(rtwdev); rtw89_core_deinit(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/usb.h b/drivers/net/wireless/realtek/rtw89/usb.h index c1b4bfa20979..203ec8e993e9 100644 --- a/drivers/net/wireless/realtek/rtw89/usb.h +++ b/drivers/net/wireless/realtek/rtw89/usb.h @@ -20,6 +20,16 @@ #define RTW89_MAX_ENDPOINT_NUM 9 #define RTW89_MAX_BULKOUT_NUM 7 +struct rtw89_usb_info { + u32 usb_host_request_2; + u32 usb_wlan0_1; + u32 hci_func_en; + u32 usb3_mac_npi_config_intf_0; + u32 usb_endpoint_0; + u32 usb_endpoint_2; + u8 bulkout_id[RTW89_DMA_CH_NUM]; +}; + struct rtw89_usb_rx_ctrl_block { struct rtw89_dev *rtwdev; struct urb *rx_urb; @@ -35,6 +45,7 @@ struct rtw89_usb_tx_ctrl_block { struct rtw89_usb { struct rtw89_dev *rtwdev; struct usb_device *udev; + const struct rtw89_usb_info *info; __le32 *vendor_req_buf; @@ -49,6 +60,7 @@ struct rtw89_usb { struct sk_buff_head rx_free_queue; struct work_struct rx_work; struct work_struct rx_urb_work; + struct usb_anchor tx_submitted; struct sk_buff_head tx_queue[RTW89_TXCH_NUM]; }; diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 5faa51ad896a..46aba4cb2ee9 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -1221,7 +1221,8 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) } } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_INFO_CHANGE); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -1248,7 +1249,7 @@ static int rtw89_wow_check_fw_status(struct rtw89_dev *rtwdev, bool wow_enable) mac->wow_ctrl.addr, mac->wow_ctrl.mask); if (ret) rtw89_err(rtwdev, "failed to check wow status %s\n", - wow_enable ? "enabled" : "disabled"); + str_enabled_disabled(wow_enable)); return ret; } @@ -1318,7 +1319,8 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) return ret; } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_FW_RESTORE); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; |
